diff options
author | Aleksey Kladov <[email protected]> | 2018-08-04 14:34:54 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-04 14:34:54 +0100 |
commit | 23cbe7fd4a048ba44aee647b3b7d5a7f3aa575da (patch) | |
tree | 9073fdb27f79fc992c89dbaefc9c7ed16341d303 /src/grammar | |
parent | 4e4ad3d27cd662b790395b61f3cda560fd4e2146 (diff) |
Pratt
Diffstat (limited to 'src/grammar')
-rw-r--r-- | src/grammar/expressions.rs | 79 |
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> { | |||
29 | const EXPR_FIRST: TokenSet = PREFIX_EXPR_FIRST; | 29 | const EXPR_FIRST: TokenSet = PREFIX_EXPR_FIRST; |
30 | 30 | ||
31 | pub(super) fn expr(p: &mut Parser) { | 31 | pub(super) fn expr(p: &mut Parser) { |
32 | let mut lhs = match prefix_expr(p) { | 32 | expr_bp(p, 1) |
33 | } | ||
34 | |||
35 | fn 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. | ||
51 | fn 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 | |||
66 | fn 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 | |||
79 | fn 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 | ||
92 | fn 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 | // } | ||
411 | fn 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 | |||
372 | fn arg_list(p: &mut Parser) { | 418 | fn 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 | |||
482 | fn 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 | } | ||