1use super::ast::Expression;
2use super::ast::LiteralTemplatePart;
3use super::ast::Node;
4use super::error::SyntaxErrorType;
5use super::error::SyntaxResult;
6use super::lex::lex_template_string_continue;
7use super::operator::Associativity;
8use super::operator::ExprOperatorName;
9use super::parse::Parser;
10use super::parse_literal::normalise_literal_float;
11use super::parse_literal::normalise_literal_int;
12use super::parse_literal::normalise_literal_template_string_part;
13use super::parse_operator::BINARY_OPERATOR_MAPPING;
14use super::parse_operator::UNARY_OPERATOR_MAPPING;
15use super::token::TokenType;
16use crate::ast::Statement;
17use crate::symbol::ScopeType;
18use crate::token::TokenTypeSet;
19
20impl<'a> Parser<'a> {
21 pub fn parse_expr(&mut self, terminator: TokenType) -> SyntaxResult<Node<Expression>> {
22 self.parse_expr_until(TokenTypeSet::new(&[terminator]))
23 }
24
25 pub fn parse_expr_until(&mut self, terminators: TokenTypeSet) -> SyntaxResult<Node<Expression>> {
26 self.parse_expr_with_min_prec(1, terminators)
27 }
28
29 pub fn parse_expr_block_without_new_scope(&mut self) -> SyntaxResult<Node<Expression>> {
31 let loc_start = self.require(TokenType::BraceOpen)?.loc;
32 let mut statements = Vec::new();
33 let mut result = None;
34 loop {
35 let Node { loc, scope, stx } = self.parse_stmt(false)?;
36 match (self.peek()?.typ == TokenType::BraceClose, *stx) {
37 (true, Statement::Expression { expression }) => {
38 result = Some(expression);
39 break;
40 }
41 (_, stx) => {
42 statements.push(Node {
43 loc,
44 scope,
45 stx: Box::new(stx),
46 });
47 }
48 };
49 self.require(TokenType::Semicolon)?;
50 if self.peek()?.typ == TokenType::BraceClose {
51 break;
52 };
53 }
54 let loc_end = self.require(TokenType::BraceClose)?.loc;
55 Ok(self.new_expression(loc_start + loc_end, Expression::Block {
56 statements,
57 result,
58 }))
59 }
60
61 pub fn parse_expr_block(&mut self) -> SyntaxResult<Node<Expression>> {
62 let parent_scope = self.enter_new_scope(ScopeType::Block);
63 let res = self.parse_expr_block_without_new_scope()?;
64 self.return_to_scope(parent_scope);
65 Ok(res)
66 }
67
68 pub fn parse_expr_closure(&mut self) -> SyntaxResult<Node<Expression>> {
69 let parent_scope = self.enter_new_scope(ScopeType::Closure);
70 let (no_params, loc_start) = match self.consume_if(TokenType::BarBar)?.match_loc() {
71 Some(loc) => (true, loc),
72 None => (false, self.require(TokenType::Bar)?.loc),
73 };
74 let mut parameters = vec![];
75 if !no_params {
76 loop {
77 if self.peek()?.typ == TokenType::Bar {
78 break;
79 };
80 let (name_loc, name) = self.require_identifier_as_string()?;
81 if !self.scope.add_symbol(name.clone()) {
82 return Err(name_loc.error(SyntaxErrorType::RedeclaredVar, None));
83 };
84 parameters.push(name);
85 if self.peek()?.typ == TokenType::Bar {
86 break;
87 };
88 self.require(TokenType::Comma)?;
89 }
90 self.require(TokenType::Bar)?;
91 };
92 let body = self.parse_expr_block_without_new_scope()?;
93 let loc_end = body.loc;
94 let closure = self.new_expression(loc_start + loc_end, Expression::Closure {
95 parameters,
96 body,
97 });
98 self.return_to_scope(parent_scope);
99 Ok(closure)
100 }
101
102 pub fn parse_expr_if(&mut self) -> SyntaxResult<Node<Expression>> {
103 let loc_start = self.require(TokenType::KeywordIf)?.loc;
104 let condition = self.parse_expr(TokenType::BraceOpen)?;
105 let consequent = self.parse_expr_block()?;
106 let alternate = if self.consume_if(TokenType::KeywordElse)?.is_match() {
107 Some(if self.peek()?.typ == TokenType::KeywordIf {
108 self.parse_expr_if()?
109 } else {
110 self.parse_expr_block()?
111 })
112 } else {
113 None
114 };
115 Ok(self.new_expression(
116 loc_start + alternate.as_ref().map(|s| s.loc).unwrap_or(consequent.loc),
117 Expression::If {
118 condition,
119 consequent,
120 alternate,
121 },
122 ))
123 }
124
125 pub fn parse_expr_grouping(&mut self) -> SyntaxResult<Node<Expression>> {
126 self.require(TokenType::ParenthesisOpen)?;
127 let expr =
128 self.parse_expr_with_min_prec(1, TokenTypeSet::new(&[TokenType::ParenthesisClose]))?;
129 self.require(TokenType::ParenthesisClose)?;
130 Ok(expr)
131 }
132
133 pub fn parse_expr_literal_array(&mut self) -> SyntaxResult<Node<Expression>> {
134 let loc_start = self.require(TokenType::BracketOpen)?.loc;
135 let mut entries = vec![];
136 loop {
137 if self.peek()?.typ == TokenType::BracketClose {
138 break;
139 };
140 let value = self.parse_expr_until(TokenTypeSet::new(&[
141 TokenType::Comma,
142 TokenType::BracketClose,
143 ]))?;
144 entries.push(value);
145 if self.peek()?.typ == TokenType::BracketClose {
146 break;
147 };
148 self.require(TokenType::Comma)?;
149 }
150 let loc_end = self.require(TokenType::BracketClose)?.loc;
151 Ok(self.new_expression(loc_start + loc_end, Expression::LiteralArray { entries }))
152 }
153
154 pub fn parse_expr_literal_object(&mut self) -> SyntaxResult<Node<Expression>> {
155 let loc_start = self.require(TokenType::BraceOpen)?.loc;
156 let mut fields = vec![];
157 loop {
158 if self.peek()?.typ == TokenType::BraceClose {
159 break;
160 };
161 let (_, key) = self.require_identifier_as_string()?;
162 self.require(TokenType::Colon)?;
163 let value = self.parse_expr_until(TokenTypeSet::new(&[
164 TokenType::Comma,
165 TokenType::BraceClose,
166 ]))?;
167 fields.push((key, value));
168 if self.peek()?.typ == TokenType::BraceClose {
169 break;
170 };
171 self.require(TokenType::Comma)?;
172 }
173 let loc_end = self.require(TokenType::BraceClose)?.loc;
174 Ok(self.new_expression(loc_start + loc_end, Expression::LiteralObject { fields }))
175 }
176
177 fn parse_expr_operand(&mut self, terminators: TokenTypeSet) -> SyntaxResult<Node<Expression>> {
178 let cp = self.checkpoint();
179 let t = self.consume()?;
180 let operand = if let Some(&operator) = UNARY_OPERATOR_MAPPING.get(&t.typ) {
181 let next_min_prec =
182 operator.precedence + (operator.associativity == Associativity::Left) as u8;
183 let operand = self.parse_expr_with_min_prec(next_min_prec, terminators)?;
184 self.new_expression(t.loc + operand.loc, Expression::Unary {
185 operand,
186 operator: operator.name,
187 })
188 } else {
189 match t.typ {
190 TokenType::BraceOpen => {
191 self.restore_checkpoint(cp);
192 self.parse_expr_literal_object()?
193 }
194 TokenType::BracketOpen => {
195 self.restore_checkpoint(cp);
196 self.parse_expr_literal_array()?
197 }
198 TokenType::Bar | TokenType::BarBar => {
199 self.restore_checkpoint(cp);
200 self.parse_expr_closure()?
201 }
202 TokenType::Identifier => self.new_expression(t.loc, Expression::Var {
203 name: self.source_as_string(t.loc),
204 }),
205 TokenType::KeywordIf => {
206 self.restore_checkpoint(cp);
207 self.parse_expr_if()?
208 }
209 TokenType::LiteralFloat => self.new_expression(t.loc, Expression::LiteralFloat {
210 value: normalise_literal_float(self.source(t.loc))
211 .ok_or_else(|| t.loc.error(SyntaxErrorType::MalformedLiteral, None))?,
212 }),
213 TokenType::LiteralInt => self.new_expression(t.loc, Expression::LiteralInt {
214 value: normalise_literal_int(self.source(t.loc))
215 .ok_or_else(|| t.loc.error(SyntaxErrorType::MalformedLiteral, None))?,
216 }),
217 TokenType::LiteralNone => self.new_expression(t.loc, Expression::LiteralNone {}),
218 TokenType::LiteralTemplatePartString => {
219 let mut loc = t.loc;
220 let mut parts = vec![];
221 parts.push(LiteralTemplatePart::String(
222 normalise_literal_template_string_part(self.source(t.loc))
223 .ok_or_else(|| t.loc.error(SyntaxErrorType::MalformedLiteral, None))?,
224 ));
225 loop {
226 let substitution = self.parse_expr(TokenType::BraceClose)?;
227 self.require(TokenType::BraceClose)?;
228 parts.push(LiteralTemplatePart::Substitution(substitution));
229 let string = lex_template_string_continue(self.lexer_mut())?;
230 loc.extend(string.loc);
231 parts.push(LiteralTemplatePart::String(
232 normalise_literal_template_string_part(self.source(string.loc))
233 .ok_or_else(|| string.loc.error(SyntaxErrorType::MalformedLiteral, None))?,
234 ));
235 if let TokenType::LiteralTemplatePartStringEnd = string.typ {
236 break;
237 };
238 }
239 self.new_expression(loc, Expression::LiteralTemplateExpr { parts })
240 }
241 TokenType::LiteralTemplatePartStringEnd => {
242 self.new_expression(t.loc, Expression::LiteralTemplateExpr {
243 parts: vec![LiteralTemplatePart::String(
244 normalise_literal_template_string_part(self.source(t.loc))
245 .ok_or_else(|| t.loc.error(SyntaxErrorType::MalformedLiteral, None))?,
246 )],
247 })
248 }
249 TokenType::LiteralTrue | TokenType::LiteralFalse => {
250 self.new_expression(t.loc, Expression::LiteralBoolean {
251 value: t.typ == TokenType::LiteralTrue,
252 })
253 }
254 TokenType::ParenthesisOpen => {
255 self.restore_checkpoint(cp);
256 self.parse_expr_grouping()?
257 }
258 _ => return Err(t.error(SyntaxErrorType::ExpectedSyntax("expression operand"))),
259 }
260 };
261 Ok(operand)
262 }
263
264 fn parse_expr_with_min_prec(
265 &mut self,
266 min_prec: u8,
267 terminators: TokenTypeSet,
268 ) -> SyntaxResult<Node<Expression>> {
269 let mut left = self.parse_expr_operand(terminators)?;
270
271 loop {
272 let cp = self.checkpoint();
273 let t = self.consume()?;
274
275 if terminators.contains(t.typ) {
276 self.restore_checkpoint(cp);
277 break;
278 };
279
280 let Some(operator) = BINARY_OPERATOR_MAPPING.get(&t.typ) else {
281 return Err(t.error(SyntaxErrorType::ExpectedSyntax("expression operator")));
282 };
283
284 if operator.precedence < min_prec {
285 self.restore_checkpoint(cp);
286 break;
287 };
288
289 let next_min_prec =
290 operator.precedence + (operator.associativity == Associativity::Left) as u8;
291
292 left = match operator.name {
293 ExprOperatorName::As => {
294 let (impl_name_loc, impl_name) = self.require_identifier_as_string()?;
295 self.new_expression(left.loc + impl_name_loc, Expression::Cast {
296 value: left,
297 typ: impl_name,
298 })
299 }
300 ExprOperatorName::Bind => {
301 let loc_start = left.loc;
302 let Expression::Var { name: impl_name } = left.stx.as_ref() else {
303 return Err(loc_start.error(SyntaxErrorType::BindingToNonImpl, None));
304 };
305 let (method_name_loc, method_name) = self.require_identifier_as_string()?;
306 let mut arguments = vec![];
307 let mut loc_end = method_name_loc;
308 if self.consume_if(TokenType::ParenthesisOpen)?.is_match() {
309 loop {
310 if self.peek()?.typ == TokenType::ParenthesisClose {
311 break;
312 };
313 let value = self.parse_expr_until(TokenTypeSet::new(&[
314 TokenType::Comma,
315 TokenType::ParenthesisClose,
316 ]))?;
317 arguments.push(value);
318 if !self.consume_if(TokenType::Comma)?.is_match() {
319 break;
320 };
321 }
322 loc_end = self.require(TokenType::ParenthesisClose)?.loc;
323 };
324 self.new_expression(loc_start + loc_end, Expression::BindMethod {
325 impl_: impl_name.clone(),
326 method: method_name,
327 arguments,
328 })
329 }
330 ExprOperatorName::Call | ExprOperatorName::OptionalCall => {
331 let mut arguments = vec![];
332 loop {
333 if self.peek()?.typ == TokenType::ParenthesisClose {
334 break;
335 };
336 let value = self.parse_expr_until(TokenTypeSet::new(&[
337 TokenType::Comma,
338 TokenType::ParenthesisClose,
339 ]))?;
340 arguments.push(value);
341 if !self.consume_if(TokenType::Comma)?.is_match() {
342 break;
343 };
344 }
345 let end = self.require(TokenType::ParenthesisClose)?;
346 let optional = match operator.name {
347 ExprOperatorName::OptionalCall => true,
348 _ => false,
349 };
350 self.new_expression(
351 left.loc + end.loc,
352 if let Expression::Field {
353 object,
354 field,
355 optional,
356 } = *left.stx
357 {
358 Expression::CallMethod {
359 object,
360 method: field,
361 arguments,
362 optional,
363 }
364 } else {
365 Expression::CallValue {
366 callee: left,
367 arguments,
368 optional,
369 }
370 },
371 )
372 }
373 ExprOperatorName::Index | ExprOperatorName::OptionalIndex => {
374 let index = self.parse_expr(TokenType::BracketClose)?;
375 let end = self.require(TokenType::BracketClose)?;
376 self.new_expression(left.loc + end.loc, Expression::Index {
377 object: left,
378 index,
379 optional: match operator.name {
380 ExprOperatorName::OptionalIndex => true,
381 _ => false,
382 },
383 })
384 }
385 ExprOperatorName::MemberAccess | ExprOperatorName::OptionalMemberAccess => {
386 let right_tok = self.consume()?;
387 let TokenType::Identifier = right_tok.typ else {
388 return Err(
389 right_tok.error(SyntaxErrorType::ExpectedSyntax("member access property")),
390 );
391 };
392 let right = right_tok.loc;
393 self.new_expression(left.loc + right, Expression::Field {
394 object: left,
395 field: self.source_as_string(right),
396 optional: match operator.name {
397 ExprOperatorName::OptionalMemberAccess => true,
398 _ => false,
399 },
400 })
401 }
402 _ => {
403 let right = self.parse_expr_with_min_prec(next_min_prec, terminators)?;
404 self.new_expression(left.loc + right.loc, Expression::Binary {
405 operator: operator.name,
406 left,
407 right,
408 })
409 }
410 };
411 }
412
413 Ok(left)
414 }
415}