rslint_parser/syntax/
expr.rs

1//! Expressions, these include `this`, identifiers, arrays, objects,
2//! binary expressions, unary expressions, and more.
3//!
4//! See the [ECMAScript spec](https://www.ecma-international.org/ecma-262/5.1/#sec-11).
5
6use syntax::decl::is_semi;
7
8use super::decl::{
9    arrow_body, class_decl, formal_parameters, function_decl, maybe_private_name, method,
10};
11use super::pat::pattern;
12use super::typescript::*;
13use super::util::*;
14use crate::{SyntaxKind::*, *};
15
16pub const LITERAL: TokenSet = token_set![TRUE_KW, FALSE_KW, NUMBER, STRING, NULL_KW, REGEX];
17
18pub const EXPR_RECOVERY_SET: TokenSet = token_set![VAR_KW, R_PAREN, L_PAREN, L_BRACK, R_BRACK];
19
20pub const ASSIGN_TOKENS: TokenSet = token_set![
21    T![=],
22    T![+=],
23    T![-=],
24    T![*=],
25    T![%=],
26    T![<<=],
27    T![>>=],
28    T![>>>=],
29    T![&=],
30    T![|=],
31    T![^=],
32    T![&&=],
33    T![||=],
34    T![??=],
35    T![/=],
36    T![>>=]
37];
38
39pub const STARTS_EXPR: TokenSet = token_set![
40    T![!],
41    T!['('],
42    T!['['],
43    T!['{'],
44    T![++],
45    T![--],
46    T![~],
47    T![+],
48    T![-],
49    T![throw],
50    T![new],
51    T![typeof],
52    T![void],
53    T![delete],
54    T![ident],
55    T![...],
56    T![this],
57    T![yield],
58    T![await],
59    T![function],
60    T![class],
61    T![import],
62    T![super],
63    BACKTICK,
64]
65.union(LITERAL);
66
67/// A literal expression.
68///
69/// `TRUE | FALSE | NUMBER | STRING | NULL`
70// test literals
71// 5
72// true
73// false
74// 5n
75// "foo"
76// 'bar'
77// null
78pub fn literal(p: &mut Parser) -> Option<CompletedMarker> {
79    if !p.at_ts(LITERAL) {
80        return None;
81    }
82    let m = p.start();
83    p.bump_any();
84    Some(m.complete(p, SyntaxKind::LITERAL))
85}
86
87/// An assignment expression such as `foo += bar` or `foo = 5`.
88pub fn assign_expr(p: &mut Parser) -> Option<CompletedMarker> {
89    if p.at(T![<])
90        && (token_set![T![ident], T![await], T![yield]].contains(p.nth(1)) || p.nth(1).is_keyword())
91    {
92        let res = try_parse_ts(p, |p| {
93            let m = p.start();
94            ts_type_params(p)?;
95            let res = assign_expr_base(p);
96            if res.map(|x| x.kind()) != Some(ARROW_EXPR) {
97                m.abandon(p);
98                None
99            } else {
100                res.unwrap().undo_completion(p).abandon(p);
101                Some(m.complete(p, ARROW_EXPR))
102            }
103        });
104        if let Some(mut res) = res {
105            res.err_if_not_ts(p, "type parameters can only be used in TypeScript files");
106            return Some(res);
107        }
108    }
109    assign_expr_base(p)
110}
111
112fn assign_expr_base(p: &mut Parser) -> Option<CompletedMarker> {
113    if p.state.in_generator && p.at(T![yield]) {
114        return Some(yield_expr(p));
115    }
116    let potential_arrow_start = matches!(p.cur(), T![ident] | T!['('] | T![yield] | T![await]);
117    let mut guard = p.with_state(ParserState {
118        potential_arrow_start,
119        ..p.state.clone()
120    });
121
122    let checkpoint = guard.checkpoint();
123    let target = conditional_expr(&mut *guard)?;
124    assign_expr_recursive(&mut *guard, target, checkpoint)
125}
126
127pub(crate) fn is_valid_target(p: &mut Parser, marker: &CompletedMarker) -> bool {
128    match marker.kind() {
129        DOT_EXPR | BRACKET_EXPR | NAME_REF | PRIVATE_PROP_ACCESS | TS_CONST_ASSERTION
130        | TS_ASSERTION | TS_NON_NULL => true,
131        GROUPING_EXPR => {
132            // avoid parsing the marker because it is incredibly expensive and this is a hot path
133            for (idx, event) in p.events[marker.start_pos as usize..].iter().enumerate() {
134                match event {
135                    Event::Finish { .. } if marker.finish_pos as usize == idx => return true,
136                    Event::Start {
137                        kind: SyntaxKind::GROUPING_EXPR,
138                        ..
139                    } => {}
140                    Event::Start {
141                        kind: SyntaxKind::TOMBSTONE,
142                        ..
143                    } => {}
144                    Event::Start { kind, .. } => {
145                        return matches!(
146                            kind,
147                            DOT_EXPR
148                                | BRACKET_EXPR
149                                | NAME_REF
150                                | PRIVATE_PROP_ACCESS
151                                | TS_CONST_ASSERTION
152                                | TS_ASSERTION
153                                | TS_NON_NULL
154                        );
155                    }
156                    _ => {}
157                }
158            }
159            true
160        }
161        _ => false,
162    }
163}
164
165fn check_assign_target_from_marker(p: &mut Parser, marker: &CompletedMarker) {
166    if !is_valid_target(p, marker) {
167        let err = p
168            .err_builder(&format!(
169                "Invalid assignment to `{}`",
170                p.source(marker.range(p))
171            ))
172            .primary(marker.range(p), "This expression cannot be assigned to");
173        p.error(err);
174    }
175}
176
177// test assign_expr
178// foo += bar = b ??= 3;
179// foo -= bar;
180// [foo, bar] = baz;
181// ({ bar, baz } = {});
182// ({ bar: [baz], foo } = {});
183fn assign_expr_recursive(
184    p: &mut Parser,
185    mut target: CompletedMarker,
186    checkpoint: Checkpoint,
187) -> Option<CompletedMarker> {
188    // TODO: dont always reparse as pattern since it will yield wonky errors for `(foo = true) = bar`
189    if p.at_ts(ASSIGN_TOKENS) {
190        if p.at(T![=]) {
191            if !is_valid_target(p, &target) && target.kind() != TEMPLATE {
192                p.rewind(checkpoint);
193                target = pattern(p, false, true)?;
194            }
195        } else {
196            if !is_valid_target(p, &target) {
197                let err = p
198                    .err_builder(&format!(
199                        "Invalid assignment to `{}`",
200                        p.source(target.range(p)).trim()
201                    ))
202                    .primary(target.range(p), "This expression cannot be assigned to");
203
204                p.error(err);
205            }
206            let text = p.source(target.range(p));
207            if (text == "eval" || text == "arguments") && p.state.strict.is_some() && p.typescript()
208            {
209                let err = p
210                    .err_builder("`eval` and `arguments` cannot be assigned to")
211                    .primary(target.range(p), "");
212
213                p.error(err);
214            }
215        }
216        let m = target.precede(p);
217        p.bump_any();
218        assign_expr(p);
219        Some(m.complete(p, ASSIGN_EXPR))
220    } else {
221        Some(target)
222    }
223}
224
225// test yield_expr
226// function *foo() {
227//  yield foo;
228//  yield* foo;
229// }
230pub fn yield_expr(p: &mut Parser) -> CompletedMarker {
231    let m = p.start();
232    p.expect(T![yield]);
233
234    if !is_semi(p, 0) && (p.at(T![*]) || p.at_ts(STARTS_EXPR)) {
235        p.eat(T![*]);
236        assign_expr(p);
237    }
238
239    m.complete(p, YIELD_EXPR)
240}
241
242/// A conditional expression such as `foo ? bar : baz`
243// test conditional_expr
244// foo ? bar : baz
245// foo ? bar : baz ? bar : baz
246pub fn conditional_expr(p: &mut Parser) -> Option<CompletedMarker> {
247    // test_err conditional_expr_err
248    // foo ? bar baz
249    // foo ? bar baz ? foo : bar
250    let lhs = binary_expr(p);
251
252    if p.at(T![?]) {
253        let m = lhs?.precede(p);
254        p.bump_any();
255        assign_expr(&mut *p.with_state(ParserState {
256            in_cond_expr: true,
257            ..p.state.clone()
258        }));
259        p.expect(T![:]);
260        assign_expr(p);
261        return Some(m.complete(p, COND_EXPR));
262    }
263    lhs
264}
265
266/// A binary expression such as `2 + 2` or `foo * bar + 2`
267pub fn binary_expr(p: &mut Parser) -> Option<CompletedMarker> {
268    let left = unary_expr(p);
269    binary_expr_recursive(p, left, 0)
270}
271
272// test binary_expressions
273// 5 * 5
274// 6 ** 6 ** 7
275// 1 + 2 * 3
276// (1 + 2) * 3
277// 1 / 2
278// 74 in foo
279// foo instanceof Array
280// foo ?? bar
281// 1 + 1 + 1 + 1
282// 5 + 6 - 1 * 2 / 1 ** 6
283
284// test_err binary_expressions_err
285// foo(foo +);
286// foo + * 2;
287// !foo * bar;
288fn binary_expr_recursive(
289    p: &mut Parser,
290    left: Option<CompletedMarker>,
291    min_prec: u8,
292) -> Option<CompletedMarker> {
293    if 7 > min_prec && !p.has_linebreak_before_n(0) && p.cur_src() == "as" {
294        let m = left.map(|x| x.precede(p)).unwrap_or_else(|| p.start());
295        p.bump_any();
296        let mut res = if p.eat(T![const]) {
297            m.complete(p, TS_CONST_ASSERTION)
298        } else {
299            ts_type(p);
300            m.complete(p, TS_ASSERTION)
301        };
302        res.err_if_not_ts(p, "type assertions can only be used in TypeScript files");
303        return binary_expr_recursive(p, Some(res), min_prec);
304    }
305    let kind = match p.cur() {
306        T![>] if p.nth_at(1, T![>]) && p.nth_at(2, T![>]) => T![>>>],
307        T![>] if p.nth_at(1, T![>]) => T![>>],
308        k => k,
309    };
310
311    let precedence = match kind {
312        T![in] if p.state.include_in => 7,
313        T![instanceof] => 7,
314        _ => {
315            if let Some(prec) = get_precedence(kind) {
316                prec
317            } else {
318                return left;
319            }
320        }
321    };
322
323    if precedence <= min_prec {
324        return left;
325    }
326
327    let op = kind;
328    let op_tok = p.cur_tok();
329
330    let m = left.map(|m| m.precede(p)).unwrap_or_else(|| p.start());
331    if op == T![>>] {
332        p.bump_multiple(2, T![>>]);
333    } else if op == T![>>>] {
334        p.bump_multiple(3, T![>>>]);
335    } else {
336        p.bump_any();
337    }
338
339    // This is a hack to allow us to effectively recover from `foo + / bar`
340    let right = if get_precedence(p.cur()).is_some() && !p.at_ts(token_set![T![-], T![+], T![<]]) {
341        let err = p.err_builder(&format!("Expected an expression for the right hand side of a `{}`, but found an operator instead", p.token_src(&op_tok)))
342            .secondary(op_tok.range, "This operator requires a right hand side value")
343            .primary(p.cur_tok().range, "But this operator was encountered instead");
344
345        p.error(err);
346        None
347    } else {
348        unary_expr(p)
349    };
350
351    binary_expr_recursive(
352        p,
353        right,
354        // ** is right recursive
355        if op == T![**] {
356            precedence - 1
357        } else {
358            precedence
359        },
360    );
361
362    let complete = m.complete(p, BIN_EXPR);
363    binary_expr_recursive(p, Some(complete), min_prec)
364
365    // FIXME(RDambrosio016): We should check for nullish-coalescing and logical expr being used together,
366    // however, i can't figure out a way to do this efficiently without using parse_marker which is way too
367    // expensive to use since this is a hot path
368}
369
370/// A parenthesis expression, also called a grouping expression.
371///
372/// `"(" Expr ")"`
373pub fn paren_expr(p: &mut Parser) -> CompletedMarker {
374    let m = p.start();
375    p.expect(T!['(']);
376    expr(p);
377    p.expect(T![')']);
378    m.complete(p, GROUPING_EXPR)
379}
380
381/// A member or new expression with subscripts. e.g. `new foo`, `new Foo()`, `foo`, or `foo().bar[5]`
382// test new_exprs
383// new Foo()
384// new foo;
385// new.target
386// new new new new Foo();
387// new Foo(bar, baz, 6 + 6, foo[bar] + (foo) => {} * foo?.bar)
388pub fn member_or_new_expr(p: &mut Parser, new_expr: bool) -> Option<CompletedMarker> {
389    if p.at(T![new]) {
390        // We must start the marker here and not outside or else we make
391        // a needless node if the node ends up just being a primary expr
392        let m = p.start();
393        p.bump_any();
394
395        // new.target
396        if p.at(T![.]) && p.token_src(&p.nth_tok(1)) == "target" {
397            p.bump_any();
398            p.bump_any();
399            let complete = m.complete(p, NEW_TARGET);
400            return Some(subscripts(p, complete, true));
401        }
402
403        let complete = member_or_new_expr(p, new_expr)?;
404        if complete.kind() == ARROW_EXPR {
405            return Some(complete);
406        }
407
408        if p.at(T![<]) {
409            if let Some(mut complete) = try_parse_ts(p, |p| {
410                let compl = ts_type_args(p);
411                if !p.at(T!['(']) {
412                    return None;
413                }
414                compl
415            }) {
416                complete.err_if_not_ts(
417                    p,
418                    "`new` expressions can only have type arguments in TypeScript files",
419                );
420            }
421        }
422
423        if !new_expr || p.at(T!['(']) {
424            args(p);
425            let complete = m.complete(p, NEW_EXPR);
426            return Some(subscripts(p, complete, true));
427        }
428        return Some(m.complete(p, NEW_EXPR));
429    }
430
431    // super.foo and super[bar]
432    // test super_property_access
433    // super.foo
434    // super[bar]
435    // super[foo][bar]
436    if p.at(T![super]) && token_set!(T![.], T!['[']).contains(p.nth(1)) {
437        let m = p.start();
438        p.bump_any();
439        let lhs = match p.cur() {
440            T![.] => {
441                p.bump_any();
442                identifier_name(p);
443                m.complete(p, DOT_EXPR)
444            }
445            T!['['] => {
446                p.bump_any();
447                expr(p);
448                p.expect(T![']']);
449                m.complete(p, BRACKET_EXPR)
450            }
451            _ => unreachable!(),
452        };
453        return Some(subscripts(p, lhs, true));
454    }
455
456    let lhs = primary_expr(p)?;
457    Some(subscripts(p, lhs, true))
458}
459
460/// Dot, Array, or Call expr subscripts. Including optional chaining.
461// test subscripts
462// foo`bar`
463// foo(bar)(baz)(baz)[bar]
464pub fn subscripts(p: &mut Parser, mut lhs: CompletedMarker, no_call: bool) -> CompletedMarker {
465    // test_err subscripts_err
466    // foo()?.baz[].
467    // BAR`b
468    let mut should_try_parsing_ts = true;
469    while !p.at(EOF) {
470        match p.cur() {
471            T![?.] if p.nth_at(1, T!['(']) => {
472                lhs = {
473                    let m = lhs.precede(p);
474                    p.bump_any();
475                    args(p);
476                    m.complete(p, CALL_EXPR)
477                }
478            }
479            T!['('] if !no_call => {
480                lhs = {
481                    let m = lhs.precede(p);
482                    args(p);
483                    m.complete(p, CALL_EXPR)
484                }
485            }
486            T![?.] if p.nth_at(1, T!['[']) => lhs = bracket_expr(p, lhs, true),
487            T!['['] => lhs = bracket_expr(p, lhs, false),
488            T![?.] => lhs = dot_expr(p, lhs, true),
489            T![.] => lhs = dot_expr(p, lhs, false),
490            T![!] if !p.has_linebreak_before_n(0) => {
491                lhs = {
492                    // FIXME(RDambrosio016): we need to tell the lexer that an expression is not
493                    // allowed here, but we have no way of doing that currently because we get all of the
494                    // tokens ahead of time, therefore we need to switch to using the lexer as an iterator
495                    // which isn't as simple as it sounds :)
496                    let m = lhs.precede(p);
497                    p.bump_any();
498                    let mut comp = m.complete(p, TS_NON_NULL);
499                    comp.err_if_not_ts(
500                        p,
501                        "non-null assertions can only be used in TypeScript files",
502                    );
503                    comp
504                }
505            }
506            T![<] if p.typescript() && should_try_parsing_ts => {
507                let res = try_parse_ts(p, |p| {
508                    let m = lhs.precede(p);
509                    // TODO: handle generic async arrow function expressions
510                    ts_type_args(p)?;
511                    if !no_call && p.at(T!['(']) {
512                        args(p);
513                        Some(m.complete(p, CALL_EXPR))
514                    } else if p.at(BACKTICK) {
515                        m.abandon(p);
516                        Some(template(p, Some(lhs)))
517                    } else {
518                        None
519                    }
520                });
521                if res.is_none() {
522                    should_try_parsing_ts = false;
523                }
524            }
525            BACKTICK => lhs = template(p, Some(lhs)),
526            _ => return lhs,
527        }
528    }
529    lhs
530}
531
532/// A dot expression for accessing a property
533// test dot_expr
534// foo.bar
535// foo.await
536// foo.yield
537// foo.for
538// foo?.for
539// foo?.bar
540pub fn dot_expr(p: &mut Parser, lhs: CompletedMarker, optional_chain: bool) -> CompletedMarker {
541    let m = lhs.precede(p);
542    let range = if optional_chain {
543        Some(p.cur_tok().range).filter(|_| p.expect(T![?.]))
544    } else {
545        p.expect(T![.]);
546        None
547    };
548    if let Some(priv_range) = maybe_private_name(p).filter(|x| x.kind() == PRIVATE_NAME) {
549        if !p.syntax.class_fields {
550            let err = p
551                .err_builder("private identifiers are unsupported")
552                .primary(priv_range.range(p), "");
553
554            p.error(err);
555            return m.complete(p, ERROR);
556        }
557        if let Some(range) = range {
558            let err = p
559                .err_builder("optional chaining cannot contain private identifiers")
560                .primary(range, "");
561
562            p.error(err);
563            m.complete(p, ERROR)
564        } else {
565            m.complete(p, PRIVATE_PROP_ACCESS)
566        }
567    } else {
568        m.complete(p, DOT_EXPR)
569    }
570}
571
572/// An array expression for property access or indexing, such as `foo[0]` or `foo?.["bar"]`
573// test bracket_expr
574// foo[bar]
575// foo[5 + 5]
576// foo["bar"]
577// foo[bar][baz]
578// foo?.[bar]
579pub fn bracket_expr(p: &mut Parser, lhs: CompletedMarker, optional_chain: bool) -> CompletedMarker {
580    // test_err bracket_expr_err
581    // foo[]
582    // foo?.[]
583    // foo[
584    let m = lhs.precede(p);
585    if optional_chain {
586        p.expect(T![?.]);
587    }
588    p.expect(T!['[']);
589    expr(p);
590    p.expect(T![']']);
591    m.complete(p, BRACKET_EXPR)
592}
593
594/// An identifier name, either an ident or a keyword
595pub fn identifier_name(p: &mut Parser) -> Option<CompletedMarker> {
596    let m = p.start();
597    match p.cur() {
598        t if t.is_keyword() || t == T![ident] => p.bump_remap(T![ident]),
599        _ => {
600            let err = p
601                .err_builder("Expected an identifier or keyword")
602                .primary(p.cur_tok().range, "Expected an identifier or keyword here");
603            p.error(err);
604            m.abandon(p);
605            return None;
606        }
607    }
608    Some(m.complete(p, NAME))
609}
610
611/// Arguments to a function.
612///
613/// `"(" (AssignExpr ",")* ")"`
614
615// test_err invalid_arg_list
616// foo(a,b;
617// foo(a,b var
618pub fn args(p: &mut Parser) -> CompletedMarker {
619    let m = p.start();
620    p.expect(T!['(']);
621
622    while !p.at(EOF) && !p.at(T![')']) {
623        if p.at(T![...]) {
624            spread_element(p);
625        } else {
626            assign_expr(p);
627        }
628
629        if p.at(T![,]) {
630            p.bump_any();
631        } else {
632            break;
633        }
634    }
635
636    p.expect(T![')']);
637    m.complete(p, ARG_LIST)
638}
639
640// test paren_or_arrow_expr
641// (foo);
642// (foo) => {};
643// (5 + 5);
644// ({foo, bar, b: [f, ...baz]}) => {};
645// (foo, ...bar) => {}
646
647// test_err paren_or_arrow_expr_invalid_params
648// (5 + 5) => {}
649pub fn paren_or_arrow_expr(p: &mut Parser, can_be_arrow: bool) -> CompletedMarker {
650    let m = p.start();
651    let checkpoint = p.checkpoint();
652    let start = p.cur_tok().range.start;
653    p.expect(T!['(']);
654    let mut spread_range = None;
655    let mut trailing_comma_marker = None;
656    let mut had_comma = false;
657    let mut params_marker = None;
658
659    let mut temp = p.with_state(ParserState {
660        potential_arrow_start: true,
661        ..p.state.clone()
662    });
663    let expr_m = temp.start();
664    let mut is_empty = false;
665
666    if temp.eat(T![')']) {
667        is_empty = true;
668    } else {
669        loop {
670            if temp.at(T![...]) {
671                let m = temp.start();
672                temp.bump_any();
673                pattern(&mut *temp, false, false);
674                if temp.eat(T![:]) {
675                    if let Some(mut ty) = ts_type(&mut *temp) {
676                        ty.err_if_not_ts(
677                            &mut *temp,
678                            "spread elements can only have type annotations in TypeScript files",
679                        );
680                    }
681                }
682                let complete = m.complete(&mut *temp, REST_PATTERN);
683                spread_range = Some(complete.range(&*temp));
684                if !temp.eat(T![')']) {
685                    if temp.eat(T![=]) {
686                        // formal params will handle this error
687                        assign_expr(&mut *temp);
688                        temp.expect(T![')']);
689                    } else {
690                        let err = temp.err_builder(&format!("expect a closing parenthesis after a spread element, but instead found `{}`", temp.cur_src()))
691                    .primary(temp.cur_tok().range, "");
692
693                        temp.err_recover(err, EXPR_RECOVERY_SET, false);
694                    }
695                }
696                break;
697            }
698            let expr = assign_expr(&mut *temp);
699            if expr.is_some() && temp.at(T![:]) {
700                temp.rewind(checkpoint);
701                params_marker = Some(formal_parameters(&mut *temp));
702                break;
703            }
704
705            let sub_m = temp.start();
706            if temp.eat(T![,]) {
707                if temp.at(T![')']) {
708                    trailing_comma_marker = Some(sub_m.complete(&mut *temp, ERROR));
709                    temp.bump_any();
710                    break;
711                } else {
712                    sub_m.abandon(&mut *temp);
713                }
714                had_comma = true;
715            } else {
716                sub_m.abandon(&mut *temp);
717                if had_comma {
718                    expr_m.complete(&mut *temp, SEQUENCE_EXPR);
719                }
720                temp.expect(T![')']);
721                break;
722            }
723        }
724    }
725    drop(temp);
726    // if we are in a ternary expression, then we need to try and see if parsing as an arrow worked
727    // if it did then we just return it, otherwise it should be interpreted as a grouping expr
728    if p.state.in_cond_expr && p.at(T![:]) && params_marker.is_none() {
729        let func = |p: &mut Parser| {
730            let p = &mut *p.with_state(ParserState {
731                no_recovery: true,
732                ..p.state.clone()
733            });
734            p.rewind(checkpoint);
735            formal_parameters(p);
736            if p.at(T![:]) {
737                if let Some(mut ret) = ts_type_or_type_predicate_ann(p, T![:]) {
738                    ret.err_if_not_ts(
739                        p,
740                        "arrow functions can only have return types in TypeScript files",
741                    );
742                }
743            }
744            p.expect_no_recover(T![=>])?;
745            arrow_body(p)?;
746            Some(())
747        };
748        // we can't just rewind the parser, since the function rewinds, and cloning and replacing the
749        // events does not work apparently, therefore we need to clone the entire parser
750        let cloned = p.clone();
751        if func(p).is_some() {
752            let c = m.complete(p, ARROW_EXPR);
753            return c;
754        } else {
755            *p = cloned;
756        }
757    }
758    let has_ret_type = !p.state.in_cond_expr && p.at(T![:]) && !p.state.in_case_cond;
759
760    // This is an arrow expr, so we rewind the parser and reparse as parameters
761    // This is kind of inefficient but in the grand scheme of things it does not matter
762    // FIXME: verify that this logic is correct
763    if (p.at(T![=>]) && !p.has_linebreak_before_n(0)) || has_ret_type || params_marker.is_some() {
764        if !can_be_arrow && !p.at(T![:]) {
765            let err = p
766                .err_builder("Unexpected token `=>`")
767                .primary(p.cur_tok().range, "an arrow expression is not allowed here");
768
769            p.error(err);
770        } else {
771            if params_marker.is_none() {
772                // Rewind the parser so we can reparse as formal parameters
773                p.rewind(checkpoint);
774                formal_parameters(p);
775            }
776
777            if p.at(T![:]) {
778                let complete = ts_type_or_type_predicate_ann(p, T![:]);
779                if let Some(mut complete) = complete {
780                    complete.err_if_not_ts(
781                        p,
782                        "arrow functions can only have return types in TypeScript files",
783                    );
784                }
785            }
786
787            p.bump_any();
788            arrow_body(p);
789            return m.complete(p, ARROW_EXPR);
790        }
791    }
792
793    if let Some(params) = params_marker {
794        let err = p
795            .err_builder("grouping expressions cannot contain parameters")
796            .primary(params.range(p), "");
797
798        p.error(err);
799        return m.complete(p, ERROR);
800    }
801
802    if is_empty {
803        let err = p
804            .err_builder("grouping expressions cannot be empty")
805            .primary(start..p.cur_tok().range.start, "");
806
807        p.error(err);
808        return m.complete(p, GROUPING_EXPR);
809    }
810
811    if let Some(range) = spread_range {
812        let err = p
813            .err_builder("Illegal spread element inside grouping expression")
814            .primary(range, "");
815
816        p.error(err);
817    }
818
819    if let Some(complete) = trailing_comma_marker {
820        let err = p
821            .err_builder("Illegal trailing comma in grouping expression")
822            .primary(complete.range(p), "");
823
824        p.error(err);
825    }
826
827    m.complete(p, GROUPING_EXPR)
828}
829
830pub fn expr_or_spread(p: &mut Parser) -> Option<CompletedMarker> {
831    if p.at(T![...]) {
832        let m = p.start();
833        p.bump_any();
834        assign_expr(p);
835        Some(m.complete(p, SPREAD_ELEMENT))
836    } else {
837        assign_expr(p)
838    }
839}
840
841/// A general expression.
842// test sequence_expr
843// 1, 2, 3, 4, 5
844pub fn expr(p: &mut Parser) -> Option<CompletedMarker> {
845    let first = assign_expr(p)?;
846
847    if p.at(T![,]) {
848        let m = first.precede(p);
849        p.bump_any();
850        assign_expr(p)?;
851
852        while p.at(T![,]) {
853            p.bump_any();
854            assign_expr(p)?;
855        }
856
857        return Some(m.complete(p, SEQUENCE_EXPR));
858    }
859
860    Some(first)
861}
862
863/// A primary expression such as a literal, an object, an array, or `this`.
864pub fn primary_expr(p: &mut Parser) -> Option<CompletedMarker> {
865    if let Some(m) = literal(p) {
866        return Some(m);
867    }
868
869    let complete = match p.cur() {
870        T![this] => {
871            // test this_expr
872            // this
873            // this.foo
874            let m = p.start();
875            p.bump_any();
876            m.complete(p, THIS_EXPR)
877        }
878        T![class] => {
879            // test class_expr
880            // let a = class {};
881            // let a = class foo {
882            //  constructor() {}
883            // }
884            // foo[class {}]
885            let mut m = class_decl(p, true);
886            m.change_kind(p, CLASS_EXPR);
887            m
888        }
889        // test async_ident
890        // let a = async;
891        T![ident] if p.cur_src() == "async" => {
892            // test async_function_expr
893            // let a = async function() {};
894            // let b = async function foo() {};
895            if p.nth_at(1, T![function]) {
896                let m = p.start();
897                p.bump_remap(T![async]);
898                let mut complete = function_decl(
899                    &mut *p.with_state(ParserState {
900                        in_async: true,
901                        ..p.state.clone()
902                    }),
903                    m,
904                    true,
905                );
906                complete.change_kind(p, FN_EXPR);
907                complete
908            } else {
909                // `async a => {}` and `async (a) => {}`
910                if p.state.potential_arrow_start
911                    && token_set![T![ident], T![yield], T!['(']].contains(p.nth(1))
912                {
913                    // test async_arrow_expr
914                    // let a = async foo => {}
915                    // let b = async (bar) => {}
916                    // async (foo, bar, ...baz) => foo
917                    let m = p.start();
918                    p.bump_remap(T![async]);
919                    if p.at(T!['(']) {
920                        formal_parameters(p);
921                    } else {
922                        let m = p.start();
923                        // test_err async_arrow_expr_await_parameter
924                        // let a = async await => {}
925                        p.bump_remap(T![ident]);
926                        m.complete(p, NAME);
927                    }
928                    if p.at(T![:]) {
929                        let complete = ts_type_or_type_predicate_ann(p, T![:]);
930                        if let Some(mut complete) = complete {
931                            complete.err_if_not_ts(
932                                p,
933                                "arrow functions can only have return types in TypeScript files",
934                            );
935                        }
936                    }
937                    p.expect(T![=>]);
938                    arrow_body(&mut *p.with_state(ParserState {
939                        in_async: true,
940                        ..p.state.clone()
941                    }));
942                    m.complete(p, ARROW_EXPR)
943                } else {
944                    identifier_reference(p)?
945                }
946            }
947        }
948        T![function] => {
949            // test function_expr
950            // let a = function() {}
951            // let b = function foo() {}
952            let m = p.start();
953            let mut complete = function_decl(p, m, true);
954            complete.change_kind(p, FN_EXPR);
955            complete
956        }
957        T![ident] | T![yield] | T![await] => {
958            // test identifier_reference
959            // foo;
960            // yield;
961            // await;
962            let mut ident = identifier_reference(p)?;
963            if p.state.potential_arrow_start && p.at(T![=>]) && !p.has_linebreak_before_n(0) {
964                // test arrow_expr_single_param
965                // foo => {}
966                // yield => {}
967                // await => {}
968                // foo =>
969                // {}
970
971                // parameters are binding so we need to change the kind from NAME_REF to NAME
972                ident.change_kind(p, NAME);
973                let m = ident.precede(p);
974                p.bump_any();
975                arrow_body(p);
976                m.complete(p, ARROW_EXPR)
977            } else {
978                ident
979            }
980        }
981        // test grouping_expr
982        // ((foo))
983        // (foo)
984        T!['('] => paren_or_arrow_expr(p, p.state.potential_arrow_start),
985        T!['['] => array_expr(p),
986        T!['{'] if p.state.allow_object_expr => object_expr(p),
987        T![import] => {
988            let m = p.start();
989            p.bump_any();
990
991            // test import_meta
992            // import.meta
993            if p.eat(T![.]) {
994                // test_err import_no_meta
995                // import.foo
996                // import.metaa
997                if p.at(T![ident]) && p.token_src(&p.cur_tok()) == "meta" {
998                    p.bump_any();
999                    m.complete(p, IMPORT_META)
1000                } else if p.at(T![ident]) {
1001                    let err = p
1002                        .err_builder(&format!(
1003                            "Expected `meta` following an import keyword, but found `{}`",
1004                            p.token_src(&p.cur_tok())
1005                        ))
1006                        .primary(p.cur_tok().range, "");
1007
1008                    p.err_and_bump(err);
1009                    m.complete(p, ERROR)
1010                } else {
1011                    let err = p
1012                        .err_builder("Expected `meta` following an import keyword, but found none")
1013                        .primary(p.cur_tok().range, "");
1014
1015                    p.error(err);
1016                    m.complete(p, ERROR)
1017                }
1018            } else {
1019                // test_err import_call_no_arg
1020                // let a = import();
1021                // foo();
1022
1023                // test import_call
1024                // import("foo")
1025                p.expect(T!['(']);
1026                assign_expr(p);
1027                p.expect(T![')']);
1028                m.complete(p, IMPORT_CALL)
1029            }
1030        }
1031        BACKTICK => template(p, None),
1032        ERROR_TOKEN => {
1033            let m = p.start();
1034            p.bump_any();
1035            m.complete(p, ERROR)
1036        }
1037        // test_err primary_expr_invalid_recovery
1038        // let a = \; foo();
1039        _ => {
1040            let err = p
1041                .err_builder("Expected an expression, but found none")
1042                .primary(p.cur_tok().range, "Expected an expression here");
1043            p.err_recover(err, p.state.expr_recovery_set, true);
1044            return None;
1045        }
1046    };
1047
1048    Some(complete)
1049}
1050
1051pub fn identifier_reference(p: &mut Parser) -> Option<CompletedMarker> {
1052    match p.cur() {
1053        T![ident] | T![yield] | T![await] => {
1054            let m = p.start();
1055            p.bump_remap(T![ident]);
1056            Some(m.complete(p, NAME_REF))
1057        }
1058        _ => {
1059            let err = p
1060                .err_builder("Expected an identifier, but found none")
1061                .primary(p.cur_tok().range, "");
1062
1063            p.err_recover(err, p.state.expr_recovery_set, true);
1064            None
1065        }
1066    }
1067}
1068
1069/// A template literal such as "`abcd ${efg}`"
1070// test template_literal
1071// let a = `foo ${bar}`;
1072// let a = ``;
1073// let a = `${foo}`;
1074// let a = `foo`;
1075pub fn template(p: &mut Parser, tag: Option<CompletedMarker>) -> CompletedMarker {
1076    let m = tag.map(|m| m.precede(p)).unwrap_or_else(|| p.start());
1077    p.expect(BACKTICK);
1078
1079    while !p.at(EOF) && !p.at(BACKTICK) {
1080        match p.cur() {
1081            TEMPLATE_CHUNK => p.bump_any(),
1082            DOLLARCURLY => {
1083                let e = p.start();
1084                p.bump_any();
1085                expr(p);
1086                p.expect(T!['}']);
1087                e.complete(p, TEMPLATE_ELEMENT);
1088            },
1089            t => unreachable!("Anything not template chunk or dollarcurly should have been eaten by the lexer, but {:?} was found", t),
1090        }
1091    }
1092
1093    // test_err template_literal_unterminated
1094    // let a = `${foo} bar
1095
1096    // The lexer already should throw an error for unterminated template literal
1097    p.eat(BACKTICK);
1098    m.complete(p, TEMPLATE)
1099}
1100
1101/// An array literal such as `[foo, bar, ...baz]`.
1102// test array_expr
1103// [foo, bar];
1104// [foo];
1105// [,foo];
1106// [foo,];
1107// [,,,,,foo,,,,];
1108// [...a, ...b];
1109pub fn array_expr(p: &mut Parser) -> CompletedMarker {
1110    let m = p.start();
1111    p.expect(T!['[']);
1112
1113    while !p.at(EOF) {
1114        while p.eat(T![,]) {}
1115
1116        if p.at(T![']']) {
1117            break;
1118        }
1119
1120        if p.at(T![...]) {
1121            spread_element(p);
1122        } else {
1123            assign_expr(p);
1124        }
1125
1126        if p.at(T![']']) {
1127            break;
1128        }
1129
1130        p.expect(T![,]);
1131    }
1132
1133    p.expect(T![']']);
1134    m.complete(p, ARRAY_EXPR)
1135}
1136
1137/// A spread element consisting of three dots and an assignment expression such as `...foo`
1138pub fn spread_element(p: &mut Parser) -> CompletedMarker {
1139    let m = p.start();
1140    p.expect(T![...]);
1141    assign_expr(p);
1142    m.complete(p, SPREAD_ELEMENT)
1143}
1144
1145/// An object literal such as `{ a: b, "b": 5 + 5 }`.
1146// test object_expr
1147// let a = {};
1148// let b = {foo,}
1149pub fn object_expr(p: &mut Parser) -> CompletedMarker {
1150    let m = p.start();
1151    p.expect(T!['{']);
1152    let mut first = true;
1153
1154    while !p.at(EOF) && !p.at(T!['}']) {
1155        if first {
1156            first = false;
1157        } else {
1158            p.expect(T![,]);
1159            if p.at(T!['}']) {
1160                break;
1161            }
1162        }
1163        object_property(p);
1164    }
1165
1166    p.expect(T!['}']);
1167    m.complete(p, OBJECT_EXPR)
1168}
1169
1170const STARTS_OBJ_PROP: TokenSet =
1171    token_set![STRING, NUMBER, T![ident], T![await], T![yield], T!['[']];
1172
1173/// An individual object property such as `"a": b` or `5: 6 + 6`.
1174pub fn object_property(p: &mut Parser) -> Option<CompletedMarker> {
1175    let m = p.start();
1176
1177    match p.cur() {
1178        // test object_expr_getter_setter
1179        // let a = {
1180        //  get foo() {
1181        //    return foo;
1182        //  }
1183        // }
1184        //
1185        // let b = {
1186        //  set [foo](bar) {
1187        //     return 5;
1188        //  }
1189        // }
1190        T![ident]
1191            if (p.cur_src() == "get" || p.cur_src() == "set")
1192                && (p.nth_at(1, T![ident]) || p.nth_at(1, T!['['])) =>
1193        {
1194            method(p, None, None)
1195        }
1196        // test object_expr_async_method
1197        // let a = {
1198        //   async foo() {},
1199        //   async *foo() {}
1200        // }
1201        T![ident]
1202            if p.cur_src() == "async"
1203                && !p.has_linebreak_before_n(1)
1204                && (STARTS_OBJ_PROP.contains(p.nth(1)) || p.nth_at(1, T![*])) =>
1205        {
1206            method(p, None, None)
1207        }
1208        // test object_expr_spread_prop
1209        // let a = {...foo}
1210        T![...] => {
1211            p.bump_any();
1212            assign_expr(p);
1213            Some(m.complete(p, SPREAD_PROP))
1214        }
1215        T![*] => {
1216            // test object_expr_generator_method
1217            // let b = { *foo() {} }
1218            let m = p.start();
1219            method(p, m, None)
1220        }
1221        _ => {
1222            let prop = object_prop_name(p, false);
1223            // test object_expr_assign_prop
1224            // let b = { foo = 4, foo = bar }
1225            if let Some(NAME) = prop.map(|m| m.kind()) {
1226                if p.eat(T![=]) {
1227                    assign_expr(p);
1228                    return Some(m.complete(p, INITIALIZED_PROP));
1229                }
1230            }
1231
1232            // test object_expr_method
1233            // let b = {
1234            //  foo() {},
1235            // }
1236            if p.at(T!['(']) || p.at(T![<]) {
1237                method(p, m, None)
1238            } else {
1239                // test_err object_expr_error_prop_name
1240                // let a = { /: 6, /: /foo/ }
1241                // let a = {{}}
1242                if prop.is_none() {
1243                    p.err_recover_no_err(token_set![T![:], T![,]], false);
1244                }
1245                // test_err object_expr_non_ident_literal_prop
1246                // let b = {5}
1247
1248                // test object_expr_ident_literal_prop
1249                // let b = { a: true }
1250                if p.at(T![:]) || prop?.kind() != NAME {
1251                    p.expect(T![:]);
1252                    assign_expr(p);
1253                    Some(m.complete(p, LITERAL_PROP))
1254                } else {
1255                    // test object_expr_ident_prop
1256                    // let b = {foo}
1257                    Some(m.complete(p, IDENT_PROP))
1258                }
1259            }
1260        }
1261    }
1262}
1263
1264// test object_prop_name
1265// let a = {"foo": foo, [6 + 6]: foo, bar: foo, 7: foo}
1266pub fn object_prop_name(p: &mut Parser, binding: bool) -> Option<CompletedMarker> {
1267    match p.cur() {
1268        STRING | NUMBER => literal(p),
1269        T!['['] => {
1270            let m = p.start();
1271            p.bump_any();
1272            assign_expr(p);
1273            p.expect(T![']']);
1274            Some(m.complete(p, COMPUTED_PROPERTY_NAME))
1275        }
1276        _ if binding => super::pat::binding_identifier(p),
1277        _ => identifier_name(p),
1278    }
1279}
1280
1281/// A left hand side expression, either a member expression or a call expression such as `foo()`.
1282pub fn lhs_expr(p: &mut Parser) -> Option<CompletedMarker> {
1283    if p.at(T![super]) && p.nth_at(1, T!['(']) {
1284        let m = p.start();
1285        p.bump_any();
1286        args(p);
1287        let lhs = m.complete(p, SUPER_CALL);
1288        return Some(subscripts(p, lhs, false));
1289    }
1290
1291    let lhs = member_or_new_expr(p, true)?;
1292    if lhs.kind() == ARROW_EXPR {
1293        return Some(lhs);
1294    }
1295
1296    let m = lhs.precede(p);
1297    let type_args = if p.at(T![<]) {
1298        let checkpoint = p.checkpoint();
1299        let mut complete = try_parse_ts(p, |p| ts_type_args(p));
1300        if !p.at(T!['(']) {
1301            p.rewind(checkpoint);
1302            None
1303        } else {
1304            if let Some(ref mut comp) = complete {
1305                comp.err_if_not_ts(p, "type arguments can only be used in TypeScript files");
1306            }
1307            complete
1308        }
1309    } else {
1310        None
1311    };
1312
1313    if p.at(T!['(']) {
1314        args(p);
1315        let lhs = m.complete(p, CALL_EXPR);
1316        return Some(subscripts(p, lhs, false));
1317    }
1318
1319    if type_args.is_some() {
1320        p.expect(T!['(']);
1321    }
1322
1323    m.abandon(p);
1324    Some(lhs)
1325}
1326
1327/// A postifx expression, either `LHSExpr [no linebreak] ++` or `LHSExpr [no linebreak] --`.
1328// test postfix_expr
1329// foo++
1330// foo--
1331pub fn postfix_expr(p: &mut Parser) -> Option<CompletedMarker> {
1332    let lhs = lhs_expr(p);
1333    if !p.has_linebreak_before_n(0) {
1334        match p.cur() {
1335            T![++] => {
1336                check_assign_target_from_marker(p, &lhs?);
1337                let m = lhs?.precede(p);
1338                p.bump(T![++]);
1339                let complete = m.complete(p, UNARY_EXPR);
1340                Some(complete)
1341            }
1342            T![--] => {
1343                check_assign_target_from_marker(p, &lhs?);
1344                let m = lhs?.precede(p);
1345                p.bump(T![--]);
1346                let complete = m.complete(p, UNARY_EXPR);
1347                Some(complete)
1348            }
1349            _ => lhs,
1350        }
1351    } else {
1352        lhs
1353    }
1354}
1355
1356/// A unary expression such as `!foo` or `++bar`
1357pub fn unary_expr(p: &mut Parser) -> Option<CompletedMarker> {
1358    const UNARY_SINGLE: TokenSet =
1359        token_set![T![delete], T![void], T![typeof], T![+], T![-], T![~], T![!]];
1360
1361    // FIXME: this shouldnt allow await in sync functions
1362    if (p.state.in_async || p.syntax.top_level_await) && p.at(T![await]) {
1363        let m = p.start();
1364        p.bump_any();
1365        unary_expr(p);
1366        return Some(m.complete(p, AWAIT_EXPR));
1367    }
1368
1369    if p.at(T![<]) {
1370        let m = p.start();
1371        p.bump_any();
1372        if p.eat(T![const]) {
1373            p.expect(T![>]);
1374            unary_expr(p);
1375            let mut res = m.complete(p, TS_CONST_ASSERTION);
1376            res.err_if_not_ts(p, "const assertions can only be used in TypeScript files");
1377            return Some(res);
1378        } else {
1379            ts_type(p);
1380            p.expect(T![>]);
1381            unary_expr(p);
1382            let mut res = m.complete(p, TS_ASSERTION);
1383            res.err_if_not_ts(p, "type assertions can only be used in TypeScript files");
1384            return Some(res);
1385        }
1386    }
1387
1388    if p.at(T![++]) {
1389        let m = p.start();
1390        p.bump(T![++]);
1391        let right = unary_expr(p)?;
1392        let complete = m.complete(p, UNARY_EXPR);
1393        check_assign_target_from_marker(p, &right);
1394        return Some(complete);
1395    }
1396    if p.at(T![--]) {
1397        let m = p.start();
1398        p.bump(T![--]);
1399        let right = unary_expr(p)?;
1400        let complete = m.complete(p, UNARY_EXPR);
1401        check_assign_target_from_marker(p, &right);
1402        return Some(complete);
1403    }
1404
1405    if p.at_ts(UNARY_SINGLE) {
1406        let m = p.start();
1407        let op = p.cur();
1408        p.bump_any();
1409        let res = unary_expr(p)?;
1410        if op == T![delete] && p.typescript() {
1411            match res.kind() {
1412                DOT_EXPR | BRACKET_EXPR => {}
1413                _ => {
1414                    let err = p
1415                        .err_builder("the target for a delete operator must be a property access")
1416                        .primary(res.range(p), "");
1417
1418                    p.error(err);
1419                }
1420            }
1421        }
1422        return Some(m.complete(p, UNARY_EXPR));
1423    }
1424
1425    postfix_expr(p)
1426}