diff options
Diffstat (limited to 'src/grammar/expressions')
-rw-r--r-- | src/grammar/expressions/mod.rs | 47 |
1 files changed, 37 insertions, 10 deletions
diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs index 15669f99d..baff0da52 100644 --- a/src/grammar/expressions/mod.rs +++ b/src/grammar/expressions/mod.rs | |||
@@ -33,19 +33,45 @@ struct Restrictions { | |||
33 | forbid_structs: bool | 33 | forbid_structs: bool |
34 | } | 34 | } |
35 | 35 | ||
36 | enum Op { | ||
37 | Simple, | ||
38 | Composite(SyntaxKind, u8) | ||
39 | } | ||
40 | |||
36 | // test expr_binding_power | 41 | // test expr_binding_power |
37 | // fn foo() { | 42 | // fn foo() { |
38 | // 1 + 2 * 3 == 1 * 2 + 3; | 43 | // 1 + 2 * 3 == 1 * 2 + 3; |
39 | // *x = 1 + 1; | 44 | // *x = 1 + 1; |
40 | // } | 45 | // } |
41 | fn bp_of(op: SyntaxKind) -> u8 { | 46 | |
42 | match op { | 47 | // test compound_ops |
48 | // fn foo() { | ||
49 | // x += 1; | ||
50 | // 1 + 1 <= 2 * 3; | ||
51 | // z -= 3 >= 0; | ||
52 | // } | ||
53 | fn current_op(p: &Parser) -> (u8, Op) { | ||
54 | if p.at_compound2(L_ANGLE, EQ) { | ||
55 | return (2, Op::Composite(LTEQ, 2)) | ||
56 | } | ||
57 | if p.at_compound2(R_ANGLE, EQ) { | ||
58 | return (2, Op::Composite(GTEQ, 2)) | ||
59 | } | ||
60 | if p.at_compound2(PLUS, EQ) { | ||
61 | return (1, Op::Composite(PLUSEQ, 2)) | ||
62 | } | ||
63 | if p.at_compound2(MINUS, EQ) { | ||
64 | return (1, Op::Composite(MINUSEQ, 2)) | ||
65 | } | ||
66 | |||
67 | let bp = match p.current() { | ||
43 | EQ => 1, | 68 | EQ => 1, |
44 | EQEQ | NEQ => 2, | 69 | EQEQ | NEQ => 2, |
45 | MINUS | PLUS => 3, | 70 | MINUS | PLUS => 3, |
46 | STAR | SLASH => 4, | 71 | STAR | SLASH => 4, |
47 | _ => 0 | 72 | _ => 0, |
48 | } | 73 | }; |
74 | (bp, Op::Simple) | ||
49 | } | 75 | } |
50 | 76 | ||
51 | // Parses expression with binding power of at least bp. | 77 | // Parses expression with binding power of at least bp. |
@@ -56,10 +82,16 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { | |||
56 | }; | 82 | }; |
57 | 83 | ||
58 | loop { | 84 | loop { |
59 | let op_bp = bp_of(p.current()); | 85 | let (op_bp, op) = current_op(p); |
60 | if op_bp < bp { | 86 | if op_bp < bp { |
61 | break; | 87 | break; |
62 | } | 88 | } |
89 | match op { | ||
90 | Op::Simple => p.bump(), | ||
91 | Op::Composite(kind, n) => { | ||
92 | p.bump_compound(kind, n); | ||
93 | }, | ||
94 | } | ||
63 | lhs = bin_expr(p, r, lhs, op_bp); | 95 | lhs = bin_expr(p, r, lhs, op_bp); |
64 | } | 96 | } |
65 | } | 97 | } |
@@ -254,12 +286,7 @@ fn struct_lit(p: &mut Parser) { | |||
254 | } | 286 | } |
255 | 287 | ||
256 | fn bin_expr(p: &mut Parser, r: Restrictions, lhs: CompletedMarker, bp: u8) -> CompletedMarker { | 288 | fn bin_expr(p: &mut Parser, r: Restrictions, lhs: CompletedMarker, bp: u8) -> CompletedMarker { |
257 | assert!(match p.current() { | ||
258 | MINUS | PLUS | STAR | SLASH | EQEQ | NEQ | EQ => true, | ||
259 | _ => false, | ||
260 | }); | ||
261 | let m = lhs.precede(p); | 289 | let m = lhs.precede(p); |
262 | p.bump(); | ||
263 | expr_bp(p, r, bp); | 290 | expr_bp(p, r, bp); |
264 | m.complete(p, BIN_EXPR) | 291 | m.complete(p, BIN_EXPR) |
265 | } | 292 | } |