diff options
Diffstat (limited to 'src/grammar/expressions/mod.rs')
-rw-r--r-- | src/grammar/expressions/mod.rs | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs index 55e965ff4..ce709dbb2 100644 --- a/src/grammar/expressions/mod.rs +++ b/src/grammar/expressions/mod.rs | |||
@@ -5,14 +5,14 @@ pub(super) use self::atom::literal; | |||
5 | 5 | ||
6 | const EXPR_FIRST: TokenSet = LHS_FIRST; | 6 | const EXPR_FIRST: TokenSet = LHS_FIRST; |
7 | 7 | ||
8 | pub(super) fn expr(p: &mut Parser) { | 8 | pub(super) fn expr(p: &mut Parser) -> BlockLike { |
9 | let r = Restrictions { forbid_structs: false }; | 9 | let r = Restrictions { forbid_structs: false }; |
10 | expr_bp(p, r, 1) | 10 | expr_bp(p, r, 1) |
11 | } | 11 | } |
12 | 12 | ||
13 | fn expr_no_struct(p: &mut Parser) { | 13 | fn expr_no_struct(p: &mut Parser) { |
14 | let r = Restrictions { forbid_structs: true }; | 14 | let r = Restrictions { forbid_structs: true }; |
15 | expr_bp(p, r, 1) | 15 | expr_bp(p, r, 1); |
16 | } | 16 | } |
17 | 17 | ||
18 | // test block | 18 | // test block |
@@ -85,10 +85,14 @@ fn current_op(p: &Parser) -> (u8, Op) { | |||
85 | } | 85 | } |
86 | 86 | ||
87 | // Parses expression with binding power of at least bp. | 87 | // Parses expression with binding power of at least bp. |
88 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { | 88 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { |
89 | let mut block: bool; | ||
89 | let mut lhs = match lhs(p, r) { | 90 | let mut lhs = match lhs(p, r) { |
90 | Some(lhs) => lhs, | 91 | Some(lhs) => { |
91 | None => return, | 92 | block = is_block(lhs.kind()); |
93 | lhs | ||
94 | }, | ||
95 | None => return BlockLike::NotBlock, | ||
92 | }; | 96 | }; |
93 | 97 | ||
94 | loop { | 98 | loop { |
@@ -97,6 +101,7 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { | |||
97 | if op_bp < bp { | 101 | if op_bp < bp { |
98 | break; | 102 | break; |
99 | } | 103 | } |
104 | block = false; | ||
100 | let m = lhs.precede(p); | 105 | let m = lhs.precede(p); |
101 | match op { | 106 | match op { |
102 | Op::Simple => p.bump(), | 107 | Op::Simple => p.bump(), |
@@ -107,6 +112,24 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { | |||
107 | expr_bp(p, r, op_bp + 1); | 112 | expr_bp(p, r, op_bp + 1); |
108 | lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); | 113 | lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); |
109 | } | 114 | } |
115 | if block { BlockLike::Block } else { BlockLike::NotBlock } | ||
116 | } | ||
117 | |||
118 | // test no_semi_after_block | ||
119 | // fn foo() { | ||
120 | // if true {} | ||
121 | // loop {} | ||
122 | // match () {} | ||
123 | // while true {} | ||
124 | // for _ in () {} | ||
125 | // {} | ||
126 | // {} | ||
127 | // } | ||
128 | fn is_block(kind: SyntaxKind) -> bool { | ||
129 | match kind { | ||
130 | IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => true, | ||
131 | _ => false, | ||
132 | } | ||
110 | } | 133 | } |
111 | 134 | ||
112 | const LHS_FIRST: TokenSet = | 135 | const LHS_FIRST: TokenSet = |