1use super::class_or_object::ParseClassBodyResult;
2use super::expr::Asi;
3use super::pattern::is_valid_pattern_identifier;
4use super::pattern::ParsePatternRules;
5use super::ParseCtx;
6use super::Parser;
7use crate::ast::Node;
8use crate::ast::Syntax;
9use crate::ast::VarDeclMode;
10use crate::ast::VariableDeclarator;
11use crate::error::SyntaxErrorType;
12use crate::error::SyntaxResult;
13use crate::token::TokenType;
14
15#[derive(Clone, Copy, PartialEq, Eq)]
16pub enum VarDeclParseMode {
17 Asi,
19 Leftmost,
21}
22
23impl<'a> Parser<'a> {
24 pub fn parse_decl_var(
25 &mut self,
26 ctx: ParseCtx,
27 parse_mode: VarDeclParseMode,
28 export: bool,
29 ) -> SyntaxResult<Node> {
30 let t = self.next()?;
31 let mode = match t.typ {
32 TokenType::KeywordLet => VarDeclMode::Let,
33 TokenType::KeywordConst => VarDeclMode::Const,
34 TokenType::KeywordVar => VarDeclMode::Var,
35 _ => return Err(t.error(SyntaxErrorType::ExpectedSyntax("variable declaration"))),
36 };
37 let mut declarators = Vec::new();
38 let mut loc = t.loc;
39 loop {
40 let pattern = self.parse_pattern(ctx)?;
41 loc.extend(pattern.loc);
42 let mut asi = match parse_mode {
43 VarDeclParseMode::Asi => Asi::can(),
44 VarDeclParseMode::Leftmost => Asi::no(),
45 };
46 let initializer = if self.consume_if(TokenType::Equals)?.is_match() {
47 let expr = self.parse_expr_until_either_with_asi(
48 ctx,
49 TokenType::Semicolon,
50 TokenType::Comma,
51 &mut asi,
52 )?;
53 loc.extend(expr.loc);
54 Some(expr)
55 } else {
56 None
57 };
58 declarators.push(VariableDeclarator {
59 pattern,
60 initializer,
61 });
62 match parse_mode {
63 VarDeclParseMode::Asi => {
64 if self.consume_if(TokenType::Semicolon)?.is_match() || asi.did_end_with_asi {
65 break;
66 }
67 let t = self.peek()?;
68 if t.preceded_by_line_terminator && t.typ != TokenType::Comma {
69 break;
70 };
71 self.require(TokenType::Comma)?;
72 }
73 VarDeclParseMode::Leftmost => {
74 if !self.consume_if(TokenType::Comma)?.is_match() {
75 break;
76 }
77 }
78 }
79 }
80 Ok(Node::new(loc, Syntax::VarDecl {
81 export,
82 mode,
83 declarators,
84 }))
85 }
86
87 pub fn parse_decl_function(
88 &mut self,
89 ctx: ParseCtx,
90 export: bool,
91 export_default: bool,
92 ) -> SyntaxResult<Node> {
93 let is_async = self.consume_if(TokenType::KeywordAsync)?.is_match();
94 let start = self.require(TokenType::KeywordFunction)?.loc;
95 let generator = self.consume_if(TokenType::Asterisk)?.is_match();
96 let name = match self
98 .consume_if_pred(|t| is_valid_pattern_identifier(t.typ, ctx.rules))?
99 .match_loc()
100 {
101 Some(name) => Some(Node::new(name, Syntax::ClassOrFunctionName {
102 name: self.string(name),
103 })),
104 _ => {
105 if !export_default {
106 return Err(start.error(SyntaxErrorType::ExpectedSyntax("function name"), None));
107 };
108 None
109 }
110 };
111 let parameters = self.parse_function_parameters(ctx)?;
112 let body = self.parse_function_body(ctx.with_rules(ParsePatternRules {
113 await_allowed: !is_async && ctx.rules.await_allowed,
114 yield_allowed: !generator && ctx.rules.yield_allowed,
115 }))?;
116 Ok(Node::new(start + body.loc, Syntax::FunctionDecl {
117 export,
118 export_default,
119 name,
120 function: Node::new(start + body.loc, Syntax::Function {
121 arrow: false,
122 async_: is_async,
123 generator,
124 parameters,
125 body,
126 }),
127 }))
128 }
129
130 pub fn parse_decl_class(
131 &mut self,
132 ctx: ParseCtx,
133 export: bool,
134 export_default: bool,
135 ) -> SyntaxResult<Node> {
136 let start = self.require(TokenType::KeywordClass)?.loc;
137 let name = match self
139 .consume_if_pred(|t| is_valid_pattern_identifier(t.typ, ctx.rules))?
140 .match_loc()
141 {
142 Some(name) => {
143 let name_node = Node::new(name, Syntax::ClassOrFunctionName {
144 name: self.string(name),
145 });
146 Some(name_node)
147 }
148 None => {
149 if !export_default {
150 return Err(start.error(SyntaxErrorType::ExpectedSyntax("class name"), None));
151 };
152 None
153 }
154 };
155 let extends = if self.consume_if(TokenType::KeywordExtends)?.is_match() {
157 Some(self.parse_expr(ctx, TokenType::BraceOpen)?)
158 } else {
159 None
160 };
161 let ParseClassBodyResult { end, members } = self.parse_class_body(ctx)?;
162 Ok(Node::new(start + end, Syntax::ClassDecl {
163 export,
164 export_default,
165 name,
166 extends,
167 members,
168 }))
169 }
170}