@@ -18,6 +18,9 @@ use crate::{
18
18
#[ derive( Clone , Debug , PartialEq ) ]
19
19
#[ non_exhaustive]
20
20
pub enum ParseError {
21
+ /// Expected is used when a token was expected but not found. Unlike UnexpectedWanted,
22
+ /// we continue to parse as if this token was found.
23
+ Expected ( TextSize , Box < [ SyntaxKind ] > ) ,
21
24
/// Unexpected is used when the cause cannot be specified further
22
25
Unexpected ( TextRange ) ,
23
26
/// UnexpectedExtra is used when there are additional tokens to the root in the tree
@@ -37,6 +40,12 @@ pub enum ParseError {
37
40
impl fmt:: Display for ParseError {
38
41
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
39
42
match self {
43
+ ParseError :: Expected ( location, kinds) => write ! (
44
+ f,
45
+ "wanted any of {:?} at {}" ,
46
+ kinds,
47
+ usize :: from( * location) ,
48
+ ) ,
40
49
ParseError :: Unexpected ( range) => {
41
50
write ! (
42
51
f,
@@ -189,6 +198,41 @@ where
189
198
fn peek ( & mut self ) -> Option < SyntaxKind > {
190
199
self . peek_data ( ) . map ( |& ( t, _) | t)
191
200
}
201
+
202
+ /// If the next token is in `allowed_slice`, expect_peek_any returns it.
203
+ /// Otherwise, it appends `self.errors` without consuming any tokens.
204
+ ///
205
+ /// This is generally preferred over expect_peek_any, but the callee must
206
+ /// ensure that an infinite loop won't be caused by this method not bumping.
207
+ fn peek_any_or_missing ( & mut self , allowed_slice : & [ SyntaxKind ] ) -> Option < SyntaxKind > {
208
+ let allowed = TokenSet :: from_slice ( allowed_slice) ;
209
+
210
+ match self . peek ( ) {
211
+ Some ( kind) if allowed. contains ( kind) => Some ( kind) ,
212
+ Some ( _) => {
213
+ self . errors . push ( ParseError :: Expected (
214
+ self . get_text_position ( ) ,
215
+ allowed_slice. to_vec ( ) . into_boxed_slice ( ) ,
216
+ ) ) ;
217
+
218
+ None
219
+ }
220
+ None => {
221
+ self . errors
222
+ . push ( ParseError :: UnexpectedEOFWanted ( allowed_slice. to_vec ( ) . into_boxed_slice ( ) ) ) ;
223
+
224
+ None
225
+ } ,
226
+ }
227
+ }
228
+
229
+ /// If the next token is in `allowed_slice`, expect_peek_any returns it.
230
+ /// Otherwise, it appends self.errors and creates a NODE_ERROR containing all tokens
231
+ /// until a token in `allowed_slice` is found.
232
+ ///
233
+ /// This is not always wanted. For example, in `{ foo = 1 } // { bar = 2; }`, it would
234
+ /// be better to recognize the semicolon as missing then move on, rather than bumping
235
+ /// all the way to the semicolon after `bar`.
192
236
fn expect_peek_any ( & mut self , allowed_slice : & [ SyntaxKind ] ) -> Option < SyntaxKind > {
193
237
let allowed = TokenSet :: from_slice ( allowed_slice) ;
194
238
@@ -224,6 +268,17 @@ where
224
268
self . bump ( ) ;
225
269
}
226
270
}
271
+
272
+ // Expect a token or silently ignore if missing. This only bumps if the token is found,
273
+ // so watch out for infinite loops. This returns whether the token was found.
274
+ fn expect_or_missing ( & mut self , expected : SyntaxKind ) -> bool {
275
+ let found = self . peek_any_or_missing ( & [ expected] ) . is_some ( ) ;
276
+ if found {
277
+ self . bump ( ) ;
278
+ }
279
+ found
280
+ }
281
+
227
282
fn expect_ident ( & mut self ) {
228
283
if self . expect_peek_any ( & [ TOKEN_IDENT ] ) . is_some ( ) {
229
284
self . start_node ( NODE_IDENT ) ;
@@ -277,7 +332,14 @@ where
277
332
fn parse_attrpath ( & mut self ) {
278
333
self . start_node ( NODE_ATTRPATH ) ;
279
334
loop {
280
- self . parse_attr ( ) ;
335
+ match self . peek_any_or_missing ( & [ TOKEN_INTERPOL_START , TOKEN_STRING_START , TOKEN_IDENT ] ) {
336
+ Some ( TOKEN_INTERPOL_START ) => self . parse_dynamic ( ) ,
337
+ Some ( TOKEN_STRING_START ) => self . parse_string ( ) ,
338
+ Some ( TOKEN_IDENT ) => self . expect_ident ( ) ,
339
+ _ => {
340
+ break
341
+ }
342
+ }
281
343
282
344
if self . peek ( ) == Some ( TOKEN_DOT ) {
283
345
self . bump ( ) ;
@@ -399,7 +461,7 @@ where
399
461
self . parse_attrpath ( ) ;
400
462
self . expect ( TOKEN_ASSIGN ) ;
401
463
self . parse_expr ( ) ;
402
- self . expect ( TOKEN_SEMICOLON ) ;
464
+ self . expect_or_missing ( TOKEN_SEMICOLON ) ;
403
465
self . finish_node ( ) ;
404
466
}
405
467
}
0 commit comments