aboutsummaryrefslogtreecommitdiff
path: root/src/grammar
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-04 14:34:54 +0100
committerAleksey Kladov <[email protected]>2018-08-04 14:34:54 +0100
commit23cbe7fd4a048ba44aee647b3b7d5a7f3aa575da (patch)
tree9073fdb27f79fc992c89dbaefc9c7ed16341d303 /src/grammar
parent4e4ad3d27cd662b790395b61f3cda560fd4e2146 (diff)
Pratt
Diffstat (limited to 'src/grammar')
-rw-r--r--src/grammar/expressions.rs79
1 files changed, 68 insertions, 11 deletions
diff --git a/src/grammar/expressions.rs b/src/grammar/expressions.rs
index 6506892e1..ecca2a3f9 100644
--- a/src/grammar/expressions.rs
+++ b/src/grammar/expressions.rs
@@ -29,12 +29,55 @@ pub(super) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
29const EXPR_FIRST: TokenSet = PREFIX_EXPR_FIRST; 29const EXPR_FIRST: TokenSet = PREFIX_EXPR_FIRST;
30 30
31pub(super) fn expr(p: &mut Parser) { 31pub(super) fn expr(p: &mut Parser) {
32 let mut lhs = match prefix_expr(p) { 32 expr_bp(p, 1)
33}
34
35fn bp_of(op: SyntaxKind) -> u8 {
36 match op {
37 EQEQ | NEQ => 1,
38 MINUS | PLUS => 2,
39 STAR | SLASH => 3,
40 _ => 0
41 }
42}
43
44
45// test expr_binding_power
46// fn foo() {
47// 1 + 2 * 3 == 1 * 2 + 3
48// }
49
50// Parses expression with binding power of at least bp.
51fn expr_bp(p: &mut Parser, bp: u8) {
52 let mut lhs = match unary_expr(p) {
33 Some(lhs) => lhs, 53 Some(lhs) => lhs,
34 None => return, 54 None => return,
35 }; 55 };
36 56
37 loop { 57 loop {
58 let op_bp = bp_of(p.current());
59 if op_bp < bp {
60 break;
61 }
62 lhs = bin_expr(p, lhs, op_bp);
63 }
64}
65
66fn unary_expr(p: &mut Parser) -> Option<CompletedMarker> {
67 let done = match p.current() {
68 AMPERSAND => ref_expr(p),
69 STAR => deref_expr(p),
70 EXCL => not_expr(p),
71 _ => {
72 let lhs = atom_expr(p)?;
73 postfix_expr(p, lhs)
74 }
75 };
76 Some(done)
77}
78
79fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker {
80 loop {
38 lhs = match p.current() { 81 lhs = match p.current() {
39 L_PAREN => call_expr(p, lhs), 82 L_PAREN => call_expr(p, lhs),
40 DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN { 83 DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN {
@@ -43,9 +86,11 @@ pub(super) fn expr(p: &mut Parser) {
43 field_expr(p, lhs) 86 field_expr(p, lhs)
44 }, 87 },
45 DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs), 88 DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs),
89 QUESTION => try_expr(p, lhs),
46 _ => break, 90 _ => break,
47 } 91 }
48 } 92 }
93 lhs
49} 94}
50 95
51// test block 96// test block
@@ -89,16 +134,6 @@ const PREFIX_EXPR_FIRST: TokenSet =
89 ATOM_EXPR_FIRST, 134 ATOM_EXPR_FIRST,
90 ]; 135 ];
91 136
92fn prefix_expr(p: &mut Parser) -> Option<CompletedMarker> {
93 let done = match p.current() {
94 AMPERSAND => ref_expr(p),
95 STAR => deref_expr(p),
96 EXCL => not_expr(p),
97 _ => return atom_expr(p),
98 };
99 Some(done)
100}
101
102// test ref_expr 137// test ref_expr
103// fn foo() { 138// fn foo() {
104// let _ = &1; 139// let _ = &1;
@@ -369,6 +404,17 @@ fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
369 m.complete(p, FIELD_EXPR) 404 m.complete(p, FIELD_EXPR)
370} 405}
371 406
407// test try_expr
408// fn foo() {
409// x?;
410// }
411fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
412 assert!(p.at(QUESTION));
413 let m = lhs.precede(p);
414 p.bump();
415 m.complete(p, TRY_EXPR)
416}
417
372fn arg_list(p: &mut Parser) { 418fn arg_list(p: &mut Parser) {
373 assert!(p.at(L_PAREN)); 419 assert!(p.at(L_PAREN));
374 let m = p.start(); 420 let m = p.start();
@@ -432,3 +478,14 @@ fn struct_lit(p: &mut Parser) {
432 } 478 }
433 p.expect(R_CURLY); 479 p.expect(R_CURLY);
434} 480}
481
482fn bin_expr(p: &mut Parser, lhs: CompletedMarker, bp: u8) -> CompletedMarker {
483 assert!(match p.current() {
484 MINUS | PLUS | STAR | SLASH | EQEQ | NEQ => true,
485 _ => false,
486 });
487 let m = lhs.precede(p);
488 p.bump();
489 expr_bp(p, bp);
490 m.complete(p, BIN_EXPR)
491}