1use crate::ast_structs::{Block, Expression, Operator, Program, Property, Statement, SourceLocation, UnaryOperator};
2use crate::feature_flags::FeatureFlags;
3use crate::lexer::{Token, TokenWithSpan};
4use std::fmt;
5use std::iter::Peekable;
6use std::slice::Iter;
7
8macro_rules! get_expr_location {
10 ($expr:expr) => {
11 match &$expr {
12 Expression::StringLiteral { location, .. } |
13 Expression::NumberLiteral { location, .. } |
14 Expression::Identifier { location, .. } |
15 Expression::BinaryExpression { location, .. } |
16 Expression::AssignmentExpression { location, .. } |
17 Expression::MemberAssignmentExpression { location, .. } |
18 Expression::CallExpression { location, .. } |
19 Expression::MemberCallExpression { location, .. } |
20 Expression::CallbackReference { location, .. } |
21 Expression::ArrayExpression { location, .. } |
22 Expression::ObjectExpression { location, .. } |
23 Expression::MemberExpression { location, .. } |
24 Expression::KeysOfExpression { location, .. } |
25 Expression::BooleanLiteral { location, .. } |
26 Expression::UnaryExpression { location, .. } |
27 Expression::NullLiteral { location, .. } => location.clone(),
28 }
29 };
30}
31
32macro_rules! get_expr_start_line {
34 ($expr:expr) => {
35 match &$expr {
36 Expression::StringLiteral { location, .. } |
37 Expression::NumberLiteral { location, .. } |
38 Expression::Identifier { location, .. } |
39 Expression::BinaryExpression { location, .. } |
40 Expression::AssignmentExpression { location, .. } |
41 Expression::MemberAssignmentExpression { location, .. } |
42 Expression::CallExpression { location, .. } |
43 Expression::MemberCallExpression { location, .. } |
44 Expression::CallbackReference { location, .. } |
45 Expression::ArrayExpression { location, .. } |
46 Expression::ObjectExpression { location, .. } |
47 Expression::MemberExpression { location, .. } |
48 Expression::KeysOfExpression { location, .. } |
49 Expression::BooleanLiteral { location, .. } |
50 Expression::UnaryExpression { location, .. } |
51 Expression::NullLiteral { location, .. } => location.start_line,
52 }
53 };
54}
55
56macro_rules! get_expr_start_column {
58 ($expr:expr) => {
59 match &$expr {
60 Expression::StringLiteral { location, .. } |
61 Expression::NumberLiteral { location, .. } |
62 Expression::Identifier { location, .. } |
63 Expression::BinaryExpression { location, .. } |
64 Expression::AssignmentExpression { location, .. } |
65 Expression::MemberAssignmentExpression { location, .. } |
66 Expression::CallExpression { location, .. } |
67 Expression::MemberCallExpression { location, .. } |
68 Expression::CallbackReference { location, .. } |
69 Expression::ArrayExpression { location, .. } |
70 Expression::ObjectExpression { location, .. } |
71 Expression::MemberExpression { location, .. } |
72 Expression::KeysOfExpression { location, .. } |
73 Expression::BooleanLiteral { location, .. } |
74 Expression::UnaryExpression { location, .. } |
75 Expression::NullLiteral { location, .. } => location.start_column,
76 }
77 };
78}
79
80pub struct Parser<'a> {
81 tokens: Peekable<Iter<'a, TokenWithSpan>>,
82 current_token: Option<&'a TokenWithSpan>,
83 flags: FeatureFlags,
84 source_code: &'a str,
85}
86
87#[derive(Debug)]
88pub enum ParseError {
89 UnexpectedToken(String, SourceLocation),
90 ExpectedToken(String, SourceLocation),
91 EndOfInput(SourceLocation),
92 FeatureDisabled(String, SourceLocation),
93}
94
95impl fmt::Display for ParseError {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 match self {
98 ParseError::UnexpectedToken(msg, loc) =>
99 write!(f, "Unexpected token: {} at line {}, column {}",
100 msg, loc.start_line, loc.start_column),
101 ParseError::ExpectedToken(msg, loc) =>
102 write!(f, "Expected token: {} at line {}, column {}",
103 msg, loc.start_line, loc.start_column),
104 ParseError::EndOfInput(loc) =>
105 write!(f, "Unexpected end of input at line {}, column {}",
106 loc.start_line, loc.start_column),
107 ParseError::FeatureDisabled(feature, loc) =>
108 write!(f, "Feature disabled: {} is not allowed with current settings at line {}, column {}",
109 feature, loc.start_line, loc.start_column),
110 }
111 }
112}
113
114impl<'a> Parser<'a> {
115 pub fn new(tokens: &'a [TokenWithSpan], flags: FeatureFlags, source_code: &'a str) -> Self {
116 let mut parser = Parser {
117 tokens: tokens.iter().peekable(),
118 current_token: None,
119 flags,
120 source_code,
121 };
122 parser.advance();
123 parser
124 }
125
126 fn current_location(&self) -> SourceLocation {
127 match self.current_token {
128 Some(token) => token.get_location(self.source_code),
129 None => {
130 let end_pos = self.source_code.len();
131 SourceLocation::from_spans(self.source_code, end_pos, end_pos)
132 }
133 }
134 }
135
136 fn advance(&mut self) {
137 self.current_token = self.tokens.next();
138 }
139
140 fn peek(&mut self) -> Option<&&TokenWithSpan> {
141 self.tokens.peek()
142 }
143
144 fn expect(&mut self, expected: Token) -> Result<(), ParseError> {
145 let location = self.current_location();
146 match self.current_token {
147 Some(token_with_span) if token_with_span.token == expected => {
148 self.advance();
149 Ok(())
150 }
151 Some(token_with_span) => Err(ParseError::UnexpectedToken(format!(
152 "Expected {:?}, got {:?}",
153 expected, token_with_span.token
154 ), location)),
155 None => Err(ParseError::EndOfInput(location)),
156 }
157 }
158
159 pub fn parse_program(&mut self) -> Result<Program, ParseError> {
160 let start_location = self.current_location();
161
162 let mut statements = Vec::new();
163
164 while self.current_token.is_some() {
165 let stmt = self.parse_statement()?;
166 statements.push(stmt);
167 }
168
169 let end_location = if let Some(last_token) = self.tokens.clone().last() {
170 last_token.get_location(self.source_code)
171 } else {
172 let end_pos = self.source_code.len();
173 SourceLocation::from_spans(self.source_code, end_pos, end_pos)
174 };
175
176 let program_location = SourceLocation::new(
177 start_location.start_line,
178 start_location.start_column,
179 end_location.end_line,
180 end_location.end_column
181 );
182
183 Ok(Program::new(statements, program_location))
184 }
185
186 fn parse_statement(&mut self) -> Result<Statement, ParseError> {
187 let start_location = self.current_location();
188
189 let stmt = match &self.current_token {
190 Some(token_with_span) => match &token_with_span.token {
191 Token::Vl => {
192 if self.flags.allow_variable_declaration {
193 self.parse_variable_declaration(start_location)
194 } else {
195 Err(ParseError::FeatureDisabled("Variable declarations".to_string(), start_location))
196 }
197 },
198 Token::If => {
199 if self.flags.allow_conditionals {
200 self.parse_if_statement(start_location)
201 } else {
202 Err(ParseError::FeatureDisabled("Conditional statements".to_string(), start_location))
203 }
204 },
205 Token::Loop => {
206 if self.flags.allow_loops {
207 self.parse_loop_statement(start_location)
208 } else {
209 Err(ParseError::FeatureDisabled("Loop statements".to_string(), start_location))
210 }
211 },
212 Token::OpenBrace => self.parse_block_statement(start_location),
213 Token::Cb => {
214 if self.flags.allow_callbacks {
215 self.parse_callback_declaration(start_location)
216 } else {
217 Err(ParseError::FeatureDisabled("Callback declarations".to_string(), start_location))
218 }
219 },
220 Token::Res => {
221 if self.flags.allow_return_statements {
222 self.parse_return_statement(start_location)
223 } else {
224 Err(ParseError::FeatureDisabled("Return statements".to_string(), start_location))
225 }
226 },
227 Token::End => {
228 if self.flags.allow_loop_control {
229 self.parse_end_statement(start_location)
230 } else {
231 Err(ParseError::FeatureDisabled("Loop control statements (end)".to_string(), start_location))
232 }
233 },
234 Token::Continue => {
235 if self.flags.allow_loop_control {
236 self.parse_continue_statement(start_location)
237 } else {
238 Err(ParseError::FeatureDisabled("Loop control statements (continue)".to_string(), start_location))
239 }
240 },
241 _ => {
242 let expr = self.parse_expression()?;
243 let end_location = self.current_location();
244 self.expect(Token::Semicolon)?;
245
246 let location = SourceLocation::new(
247 start_location.start_line,
248 start_location.start_column,
249 end_location.end_line,
250 end_location.end_column
251 );
252
253 Ok(Statement::ExpressionStatement {
254 expression: expr,
255 location
256 })
257 }
258 },
259 None => Err(ParseError::EndOfInput(start_location)),
260 }?;
261
262 Ok(stmt)
263 }
264
265 fn parse_variable_declaration(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
266 self.advance();
267
268 let name = match &self.current_token {
269 Some(token_with_span) => match &token_with_span.token {
270 Token::Identifier(name) => name.clone(),
271 _ => return Err(ParseError::ExpectedToken("identifier".to_string(), self.current_location())),
272 },
273 None => return Err(ParseError::EndOfInput(self.current_location())),
274 };
275 self.advance();
276
277 self.expect(Token::Equal)?;
278
279 let value = self.parse_expression()?;
280
281 let semicolon_location = self.current_location();
282 self.expect(Token::Semicolon)?;
283
284 let end_location = semicolon_location;
285
286 let location = SourceLocation::new(
287 start_location.start_line,
288 start_location.start_column,
289 end_location.end_line,
290 end_location.end_column
291 );
292
293 Ok(Statement::VariableDeclaration { name, value, location })
294 }
295
296 fn parse_if_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
297 self.advance();
298
299 let condition = self.parse_expression()?;
300 let body = self.parse_block()?;
301
302 let else_body = if let Some(token_with_span) = self.current_token {
303 if token_with_span.token == Token::Else {
304 self.advance();
305 Some(self.parse_block()?)
306 } else {
307 None
308 }
309 } else {
310 None
311 };
312
313 let end_location = else_body.as_ref().map_or_else(
314 || body.location.clone(),
315 |else_block| else_block.location.clone()
316 );
317
318 let location = SourceLocation::new(
319 start_location.start_line,
320 start_location.start_column,
321 end_location.end_line,
322 end_location.end_column
323 );
324
325 Ok(Statement::IfStatement {
326 condition,
327 body,
328 else_body,
329 location,
330 })
331 }
332
333 fn parse_block_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
334 let block = self.parse_block()?;
335
336 let end_location = block.location.clone();
337
338 let location = SourceLocation::new(
339 start_location.start_line,
340 start_location.start_column,
341 end_location.end_line,
342 end_location.end_column
343 );
344
345 Ok(Statement::Block { block, location })
346 }
347
348 fn parse_block(&mut self) -> Result<Block, ParseError> {
349 let start_location = self.current_location();
350
351 self.expect(Token::OpenBrace)?;
352
353 let mut statements = Vec::new();
354 while let Some(token_with_span) = self.current_token {
355 if token_with_span.token == Token::CloseBrace {
356 break;
357 }
358 statements.push(self.parse_statement()?);
359 }
360
361 let end_location = self.current_location();
362 self.expect(Token::CloseBrace)?;
363
364 let location = SourceLocation::new(
365 start_location.start_line,
366 start_location.start_column,
367 end_location.end_line,
368 end_location.end_column
369 );
370
371 Ok(Block::new(statements, location))
372 }
373
374 fn parse_expression(&mut self) -> Result<Expression, ParseError> {
375 let expr = self.parse_assignment()?;
376 Ok(expr)
377 }
378
379 fn parse_assignment(&mut self) -> Result<Expression, ParseError> {
380 let start_location = self.current_location();
381 let expr = self.parse_equality()?;
382
383 if let Some(token_with_span) = self.current_token {
384 if token_with_span.token == Token::Equal {
385 if !self.flags.allow_assignments {
386 return Err(ParseError::FeatureDisabled("Assignments".to_string(), start_location));
387 }
388
389 self.advance();
390 let value = self.parse_equality()?;
391 let end_location = get_expr_location!(value);
392
393 let location = SourceLocation::new(
394 start_location.start_line,
395 start_location.start_column,
396 end_location.end_line,
397 end_location.end_column
398 );
399
400 let new_expr = match expr {
401 Expression::Identifier { name, .. } => Expression::AssignmentExpression {
402 target: name,
403 value: Box::new(value),
404 location,
405 },
406 Expression::MemberExpression { object, property, property_expr, computed, .. } => {
407 if !self.flags.allow_object_navigation {
408 return Err(ParseError::FeatureDisabled("Object property assignment".to_string(), start_location));
409 }
410
411 Expression::MemberAssignmentExpression {
412 object,
413 property,
414 property_expr,
415 computed,
416 value: Box::new(value),
417 location,
418 }
419 },
420 _ => return Err(ParseError::UnexpectedToken("Invalid assignment target".to_string(), start_location)),
421 };
422 return Ok(new_expr);
423 }
424 }
425 Ok(expr)
426 }
427
428 fn parse_comparison(&mut self) -> Result<Expression, ParseError> {
429 let start_location = self.current_location();
430 let mut expr = self.parse_additive()?;
431
432 while let Some(token_with_span) = self.current_token {
433 expr = match token_with_span.token {
434 Token::Greater => {
435 self.advance();
436 let right = self.parse_additive()?;
437 let right_loc = get_expr_location!(right);
438
439 let location = SourceLocation::new(
440 start_location.start_line,
441 start_location.start_column,
442 right_loc.end_line,
443 right_loc.end_column
444 );
445
446 Expression::BinaryExpression {
447 left: Box::new(expr),
448 operator: Operator::Greater,
449 right: Box::new(right),
450 location,
451 }
452 },
453 Token::Less => {
454 self.advance();
455 let right = self.parse_additive()?;
456 let right_loc = get_expr_location!(right);
457
458 let location = SourceLocation::new(
459 start_location.start_line,
460 start_location.start_column,
461 right_loc.end_line,
462 right_loc.end_column
463 );
464
465 Expression::BinaryExpression {
466 left: Box::new(expr),
467 operator: Operator::Less,
468 right: Box::new(right),
469 location,
470 }
471 },
472 Token::GreaterEqual => {
473 self.advance();
474 let right = self.parse_additive()?;
475 let right_loc = get_expr_location!(right);
476
477 let location = SourceLocation::new(
478 start_location.start_line,
479 start_location.start_column,
480 right_loc.end_line,
481 right_loc.end_column
482 );
483
484 Expression::BinaryExpression {
485 left: Box::new(expr),
486 operator: Operator::GreaterEqual,
487 right: Box::new(right),
488 location,
489 }
490 },
491 Token::LessEqual => {
492 self.advance();
493 let right = self.parse_additive()?;
494 let right_loc = get_expr_location!(right);
495
496 let location = SourceLocation::new(
497 start_location.start_line,
498 start_location.start_column,
499 right_loc.end_line,
500 right_loc.end_column
501 );
502
503 Expression::BinaryExpression {
504 left: Box::new(expr),
505 operator: Operator::LessEqual,
506 right: Box::new(right),
507 location,
508 }
509 },
510 _ => break,
511 };
512 }
513 Ok(expr)
514 }
515
516 fn parse_equality(&mut self) -> Result<Expression, ParseError> {
517 let start_location = self.current_location();
518 let mut expr = self.parse_comparison()?;
519
520 while let Some(token_with_span) = self.current_token {
521 match &token_with_span.token {
522 Token::EqualEqual => {
523 self.advance();
524 let right = self.parse_comparison()?;
525 let right_loc = get_expr_location!(right);
526
527 let location = SourceLocation::new(
528 start_location.start_line,
529 start_location.start_column,
530 right_loc.end_line,
531 right_loc.end_column
532 );
533
534 expr = Expression::BinaryExpression {
535 left: Box::new(expr),
536 operator: Operator::Equal,
537 right: Box::new(right),
538 location,
539 };
540 }
541 _ => break,
542 }
543 }
544
545 Ok(expr)
546 }
547
548 fn parse_additive(&mut self) -> Result<Expression, ParseError> {
549 let start_location = self.current_location();
550 let mut expr = self.parse_multiplicative()?;
551
552 while let Some(token_with_span) = self.current_token {
553 match &token_with_span.token {
554 Token::Plus => {
555 self.advance();
556 let right = self.parse_multiplicative()?;
557 let right_loc = get_expr_location!(right);
558
559 let location = SourceLocation::new(
560 start_location.start_line,
561 start_location.start_column,
562 right_loc.end_line,
563 right_loc.end_column
564 );
565
566 expr = Expression::BinaryExpression {
567 left: Box::new(expr),
568 operator: Operator::Plus,
569 right: Box::new(right),
570 location,
571 };
572 }
573 _ => break,
574 }
575 }
576
577 Ok(expr)
578 }
579
580 fn parse_multiplicative(&mut self) -> Result<Expression, ParseError> {
581 let start_location = self.current_location();
582 let mut expr = self.parse_unary()?;
583
584 expr = self.parse_member_access(expr)?;
585
586 while let Some(token_with_span) = self.current_token {
587 match &token_with_span.token {
588 Token::Multiply => {
589 self.advance();
590 let right = self.parse_primary()?;
591 let right_with_member = self.parse_member_access(right)?;
592 let right_loc = get_expr_location!(right_with_member);
593
594 let location = SourceLocation::new(
595 start_location.start_line,
596 start_location.start_column,
597 right_loc.end_line,
598 right_loc.end_column
599 );
600
601 expr = Expression::BinaryExpression {
602 left: Box::new(expr),
603 operator: Operator::Multiply,
604 right: Box::new(right_with_member),
605 location,
606 };
607 }
608 Token::Divide => {
609 self.advance();
610 let right = self.parse_primary()?;
611 let right_with_member = self.parse_member_access(right)?;
612 let right_loc = get_expr_location!(right_with_member);
613
614 let location = SourceLocation::new(
615 start_location.start_line,
616 start_location.start_column,
617 right_loc.end_line,
618 right_loc.end_column
619 );
620
621 expr = Expression::BinaryExpression {
622 left: Box::new(expr),
623 operator: Operator::Divide,
624 right: Box::new(right_with_member),
625 location,
626 };
627 }
628 _ => break,
629 }
630 }
631
632 Ok(expr)
633 }
634
635 fn parse_unary(&mut self) -> Result<Expression, ParseError> {
636 let start_location = self.current_location();
637
638 match &self.current_token {
639 Some(token_with_span) => match &token_with_span.token {
640 Token::Bang => {
641 self.advance();
642 let operand = self.parse_unary()?;
643 let operand_loc = get_expr_location!(operand);
644
645 let location = SourceLocation::new(
646 start_location.start_line,
647 start_location.start_column,
648 operand_loc.end_line,
649 operand_loc.end_column
650 );
651
652 Ok(Expression::UnaryExpression {
653 operator: UnaryOperator::Not,
654 operand: Box::new(operand),
655 location,
656 })
657 },
658 _ => self.parse_primary()
659 },
660 None => Err(ParseError::EndOfInput(start_location)),
661 }
662 }
663
664 fn parse_primary(&mut self) -> Result<Expression, ParseError> {
665 let start_location = self.current_location();
666
667 match &self.current_token {
668 Some(token_with_span) => match &token_with_span.token {
669 Token::KeysOf => {
670 if self.flags.allow_object_keys {
671 self.advance();
672
673 let mut object_expr = self.parse_primary()?;
675
676 object_expr = self.parse_member_access(object_expr)?;
678
679 let object_loc = get_expr_location!(object_expr);
680
681 let location = SourceLocation::new(
682 start_location.start_line,
683 start_location.start_column,
684 object_loc.end_line,
685 object_loc.end_column
686 );
687
688 Ok(Expression::KeysOfExpression {
689 object: Box::new(object_expr),
690 location,
691 })
692 } else {
693 Err(ParseError::FeatureDisabled("Object keys operator (keysof)".to_string(), start_location))
694 }
695 },
696 Token::OpenBracket => {
697 if self.flags.allow_array_constructions {
698 self.parse_array_literal(start_location)
699 } else {
700 Err(ParseError::FeatureDisabled("Array literals".to_string(), start_location))
701 }
702 },
703 Token::OpenBrace => {
704 match self.peek() {
705 Some(next_token) => match &next_token.token {
706 Token::Identifier(_) => {
707 if self.flags.allow_object_constructions {
708 self.parse_object_literal(start_location)
709 } else {
710 Err(ParseError::FeatureDisabled("Object literals".to_string(), start_location))
711 }
712 },
713 Token::CloseBrace => {
714 self.advance();
715 self.advance();
716 if self.flags.allow_object_constructions {
717 Ok(Expression::ObjectExpression { properties: vec![], location: start_location })
718 } else {
719 Err(ParseError::FeatureDisabled("Object literals".to_string(), start_location))
720 }
721 },
722 _ => {
723 if self.flags.allow_object_constructions {
724 self.parse_object_literal(start_location)
725 } else {
726 Err(ParseError::FeatureDisabled("Object literals".to_string(), start_location))
727 }
728 }
729 },
730 None => Err(ParseError::EndOfInput(start_location)),
731 }
732 },
733 Token::OpenParen => {
734 self.advance();
735 let expr = self.parse_expression()?;
736 self.expect(Token::CloseParen)?;
737 Ok(expr)
738 },
739 Token::Identifier(name) => {
740 let id_name = name.clone();
741 self.advance();
742
743 if let Some(next_token) = self.current_token {
744 if next_token.token == Token::OpenParen {
745 return self.parse_function_call(id_name, start_location);
746 }
747 }
748
749 Ok(Expression::Identifier {
750 name: id_name,
751 location: start_location,
752 })
753 },
754 Token::StringLiteral(value) => {
755 let str_value = value.clone();
756 self.advance();
757 Ok(Expression::StringLiteral {
758 value: str_value,
759 location: start_location,
760 })
761 },
762 Token::NumberLiteral(value) => {
763 let num_value = *value;
764 self.advance();
765 Ok(Expression::NumberLiteral {
766 value: num_value,
767 location: start_location,
768 })
769 },
770 Token::True => {
771 self.advance();
772 Ok(Expression::BooleanLiteral {
773 value: true,
774 location: start_location,
775 })
776 },
777
778 Token::False => {
779 self.advance();
780 Ok(Expression::BooleanLiteral {
781 value: false,
782 location: start_location,
783 })
784 },
785
786 Token::Null => {
787 self.advance();
788 Ok(Expression::NullLiteral {
789 location: start_location,
790 })
791 },
792 _ => Err(ParseError::UnexpectedToken(format!(
793 "Unexpected token: {:?}",
794 token_with_span.token
795 ), start_location)),
796 },
797 None => Err(ParseError::EndOfInput(start_location)),
798 }
799 }
800
801 fn parse_function_call(&mut self, callee: String, start_location: SourceLocation) -> Result<Expression, ParseError> {
802 self.expect(Token::OpenParen)?;
803
804 let mut arguments = Vec::new();
805
806 if let Some(token_with_span) = self.current_token {
807 if token_with_span.token == Token::CloseParen {
808 let end_location = self.current_location();
809 self.advance();
810
811 let location = SourceLocation::new(
812 start_location.start_line,
813 start_location.start_column,
814 end_location.end_line,
815 end_location.end_column
816 );
817
818 return Ok(Expression::CallExpression { callee, arguments, location });
819 }
820 }
821
822 arguments.push(self.parse_expression()?);
823
824 while let Some(token_with_span) = self.current_token {
825 match &token_with_span.token {
826 Token::Comma => {
827 self.advance();
828 arguments.push(self.parse_expression()?);
829 }
830 Token::CloseParen => {
831 let end_location = self.current_location();
832 self.advance();
833
834 let location = SourceLocation::new(
835 start_location.start_line,
836 start_location.start_column,
837 end_location.end_line,
838 end_location.end_column
839 );
840
841 return Ok(Expression::CallExpression { callee, arguments, location });
842 }
843 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
844 }
845 }
846
847 Err(ParseError::ExpectedToken("')'".to_string(), self.current_location()))
848 }
849
850 fn parse_callback_declaration(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
851 self.advance();
852
853 let name = match &self.current_token {
854 Some(token_with_span) => match &token_with_span.token {
855 Token::Identifier(name) => name.clone(),
856 _ => return Err(ParseError::ExpectedToken("callback name".to_string(), self.current_location())),
857 },
858 None => return Err(ParseError::EndOfInput(self.current_location())),
859 };
860 self.advance();
861
862 self.expect(Token::OpenParen)?;
863 let mut params = Vec::new();
864
865 if let Some(token_with_span) = self.current_token {
866 if token_with_span.token == Token::CloseParen {
867 self.advance();
868 } else {
869 if let Some(token_with_span) = self.current_token {
870 match &token_with_span.token {
871 Token::Identifier(param) => {
872 params.push(param.clone());
873 self.advance();
874 },
875 _ => return Err(ParseError::ExpectedToken("parameter name".to_string(), self.current_location())),
876 }
877 }
878
879 while let Some(token_with_span) = self.current_token {
880 match &token_with_span.token {
881 Token::Comma => {
882 self.advance();
883 match &self.current_token {
884 Some(token_with_span) => match &token_with_span.token {
885 Token::Identifier(param) => {
886 params.push(param.clone());
887 self.advance();
888 },
889 _ => return Err(ParseError::ExpectedToken("parameter name".to_string(), self.current_location())),
890 },
891 None => return Err(ParseError::EndOfInput(self.current_location())),
892 }
893 },
894 Token::CloseParen => {
895 self.advance();
896 break;
897 },
898 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
899 }
900 }
901 }
902 } else {
903 return Err(ParseError::EndOfInput(self.current_location()));
904 }
905
906 let body = self.parse_block()?;
907
908 let end_location = body.location.clone();
909
910 let location = SourceLocation::new(
911 start_location.start_line,
912 start_location.start_column,
913 end_location.end_line,
914 end_location.end_column
915 );
916
917 Ok(Statement::CallbackDeclaration {
918 name,
919 params,
920 body,
921 location,
922 })
923 }
924
925 fn parse_return_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
926 self.advance();
927
928 let value = self.parse_expression()?;
929
930 let semicolon_location = self.current_location();
931 self.expect(Token::Semicolon)?;
932
933 let end_location = semicolon_location;
934
935 let location = SourceLocation::new(
936 start_location.start_line,
937 start_location.start_column,
938 end_location.end_line,
939 end_location.end_column
940 );
941
942 Ok(Statement::ReturnStatement { value, location })
943 }
944
945 fn parse_array_literal(&mut self, start_location: SourceLocation) -> Result<Expression, ParseError> {
946 self.advance();
947
948 let mut elements = Vec::new();
949
950 if let Some(token_with_span) = self.current_token {
951 if token_with_span.token == Token::CloseBracket {
952 let end_location = self.current_location();
953 self.advance();
954
955 let location = SourceLocation::new(
956 start_location.start_line,
957 start_location.start_column,
958 end_location.end_line,
959 end_location.end_column
960 );
961
962 return Ok(Expression::ArrayExpression { elements, location });
963 }
964 }
965
966 elements.push(self.parse_expression()?);
967
968 while let Some(token_with_span) = self.current_token {
969 match &token_with_span.token {
970 Token::Comma => {
971 self.advance();
972 elements.push(self.parse_expression()?);
973 }
974 Token::CloseBracket => {
975 let end_location = self.current_location();
976 self.advance();
977
978 let location = SourceLocation::new(
979 start_location.start_line,
980 start_location.start_column,
981 end_location.end_line,
982 end_location.end_column
983 );
984
985 return Ok(Expression::ArrayExpression { elements, location });
986 }
987 _ => return Err(ParseError::ExpectedToken("',' or ']'".to_string(), self.current_location())),
988 }
989 }
990
991 Err(ParseError::ExpectedToken("']'".to_string(), self.current_location()))
992 }
993
994 fn parse_object_literal(&mut self, start_location: SourceLocation) -> Result<Expression, ParseError> {
995 self.advance();
996
997 let mut properties = Vec::new();
998
999 if let Some(token_with_span) = self.current_token {
1000 if token_with_span.token == Token::CloseBrace {
1001 let end_location = self.current_location();
1002 self.advance();
1003
1004 let location = SourceLocation::new(
1005 start_location.start_line,
1006 start_location.start_column,
1007 end_location.end_line,
1008 end_location.end_column
1009 );
1010
1011 return Ok(Expression::ObjectExpression { properties, location });
1012 }
1013 }
1014
1015 let property = self.parse_object_property()?;
1016 properties.push(property);
1017
1018 while let Some(token_with_span) = self.current_token {
1019 match &token_with_span.token {
1020 Token::Comma => {
1021 self.advance();
1022 let property = self.parse_object_property()?;
1023 properties.push(property);
1024 }
1025 Token::CloseBrace => {
1026 let end_location = self.current_location();
1027 self.advance();
1028
1029 let location = SourceLocation::new(
1030 start_location.start_line,
1031 start_location.start_column,
1032 end_location.end_line,
1033 end_location.end_column
1034 );
1035
1036 return Ok(Expression::ObjectExpression { properties, location });
1037 }
1038 _ => return Err(ParseError::ExpectedToken("',' or '}'".to_string(), self.current_location())),
1039 }
1040 }
1041
1042 Err(ParseError::ExpectedToken("'}'".to_string(), self.current_location()))
1043 }
1044
1045 fn parse_object_property(&mut self) -> Result<Property, ParseError> {
1046 let start_location = self.current_location();
1047
1048 let key = match &self.current_token {
1049 Some(token_with_span) => match &token_with_span.token {
1050 Token::Identifier(name) => name.clone(),
1051 Token::StringLiteral(value) => value.clone(),
1052 _ => return Err(ParseError::ExpectedToken("property key".to_string(), self.current_location())),
1053 },
1054 None => return Err(ParseError::EndOfInput(self.current_location())),
1055 };
1056 self.advance();
1057
1058 self.expect(Token::Colon)?;
1059
1060 let value = self.parse_expression()?;
1061
1062 let end_location = get_expr_location!(value);
1063
1064 let location = SourceLocation::new(
1065 start_location.start_line,
1066 start_location.start_column,
1067 end_location.end_line,
1068 end_location.end_column
1069 );
1070
1071 Ok(Property::new(key, value, location))
1072 }
1073
1074 fn parse_member_access(&mut self, mut object: Expression) -> Result<Expression, ParseError> {
1075 loop {
1076 match &self.current_token {
1077 Some(token_with_span) => match &token_with_span.token {
1078 Token::Dot => {
1079 if !self.flags.allow_object_navigation {
1080 return Err(ParseError::FeatureDisabled("Object navigation (dot notation)".to_string(), self.current_location()));
1081 }
1082
1083 self.advance();
1084
1085 match &self.current_token {
1086 Some(token_with_span) => match &token_with_span.token {
1087 Token::Identifier(prop_name) => {
1088 let property = prop_name.clone();
1089 let property_location = self.current_location();
1090 self.advance();
1091
1092
1093 let obj_start_line = get_expr_start_line!(object);
1094
1095 let obj_start_column = get_expr_start_column!(object);
1096
1097
1098 if let Some(token_with_span) = self.current_token {
1099 if token_with_span.token == Token::OpenParen {
1100 self.advance();
1101
1102
1103 let mut arguments = Vec::new();
1104
1105
1106 if let Some(token_with_span) = self.current_token {
1107 if token_with_span.token == Token::CloseParen {
1108
1109 let end_call_location = self.current_location();
1110 self.advance();
1111
1112
1113 let call_location = SourceLocation::new(
1114 obj_start_line,
1115 obj_start_column,
1116 end_call_location.end_line,
1117 end_call_location.end_column
1118 );
1119
1120
1121 object = Expression::MemberCallExpression {
1122 object: Box::new(object),
1123 property: Some(property),
1124 property_expr: None,
1125 computed: false,
1126 arguments,
1127 location: call_location,
1128 };
1129 continue;
1130 }
1131 }
1132
1133
1134 arguments.push(self.parse_expression()?);
1135
1136
1137 while let Some(token_with_span) = self.current_token {
1138 match &token_with_span.token {
1139 Token::Comma => {
1140 self.advance();
1141 arguments.push(self.parse_expression()?);
1142 }
1143 Token::CloseParen => {
1144 let end_call_location = self.current_location();
1145 self.advance();
1146
1147
1148 let call_location = SourceLocation::new(
1149 obj_start_line,
1150 obj_start_column,
1151 end_call_location.end_line,
1152 end_call_location.end_column
1153 );
1154
1155
1156 object = Expression::MemberCallExpression {
1157 object: Box::new(object),
1158 property: Some(property),
1159 property_expr: None,
1160 computed: false,
1161 arguments,
1162 location: call_location,
1163 };
1164 break;
1165 }
1166 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
1167 }
1168 }
1169 } else {
1170
1171 let member_expr_location = SourceLocation::new(
1172 obj_start_line,
1173 obj_start_column,
1174 property_location.end_line,
1175 property_location.end_column
1176 );
1177
1178 object = Expression::MemberExpression {
1179 object: Box::new(object),
1180 property: Some(property),
1181 property_expr: None,
1182 computed: false,
1183 location: member_expr_location,
1184 };
1185 }
1186 } else {
1187
1188 let member_expr_location = SourceLocation::new(
1189 obj_start_line,
1190 obj_start_column,
1191 property_location.end_line,
1192 property_location.end_column
1193 );
1194
1195 object = Expression::MemberExpression {
1196 object: Box::new(object),
1197 property: Some(property),
1198 property_expr: None,
1199 computed: false,
1200 location: member_expr_location,
1201 };
1202 }
1203 }
1204 _ => return Err(ParseError::ExpectedToken("property name".to_string(), self.current_location())),
1205 },
1206 None => return Err(ParseError::EndOfInput(self.current_location())),
1207 }
1208 },
1209
1210 Token::OpenBracket => {
1211 if !self.flags.allow_object_navigation {
1212 return Err(ParseError::FeatureDisabled("Object navigation (bracket notation)".to_string(), self.current_location()));
1213 }
1214
1215 self.advance();
1216
1217 let property_expr = self.parse_expression()?;
1218
1219 let close_bracket_location = self.current_location();
1220 self.expect(Token::CloseBracket)?;
1221
1222 let obj_start_line = get_expr_start_line!(object);
1223
1224 let obj_start_column = get_expr_start_column!(object);
1225
1226 let member_expr_location = SourceLocation::new(
1227 obj_start_line,
1228 obj_start_column,
1229 close_bracket_location.end_line,
1230 close_bracket_location.end_column
1231 );
1232
1233 if let Some(token_with_span) = self.current_token {
1234 if token_with_span.token == Token::OpenParen {
1235
1236 self.advance();
1237
1238 let mut arguments = Vec::new();
1239
1240
1241 if let Some(token_with_span) = self.current_token {
1242 if token_with_span.token == Token::CloseParen {
1243 let end_call_location = self.current_location();
1244 self.advance();
1245
1246 let call_location = SourceLocation::new(
1247 obj_start_line,
1248 obj_start_column,
1249 end_call_location.end_line,
1250 end_call_location.end_column
1251 );
1252
1253
1254 object = Expression::MemberCallExpression {
1255 object: Box::new(object),
1256 property: None,
1257 property_expr: Some(Box::new(property_expr)),
1258 computed: true,
1259 arguments,
1260 location: call_location,
1261 };
1262 continue;
1263 }
1264 }
1265
1266
1267 arguments.push(self.parse_expression()?);
1268
1269 while let Some(token_with_span) = self.current_token {
1270 match &token_with_span.token {
1271 Token::Comma => {
1272 self.advance();
1273 arguments.push(self.parse_expression()?);
1274 }
1275 Token::CloseParen => {
1276 let end_call_location = self.current_location();
1277 self.advance();
1278
1279 let call_location = SourceLocation::new(
1280 obj_start_line,
1281 obj_start_column,
1282 end_call_location.end_line,
1283 end_call_location.end_column
1284 );
1285
1286
1287 object = Expression::MemberCallExpression {
1288 object: Box::new(object),
1289 property: None,
1290 property_expr: Some(Box::new(property_expr)),
1291 computed: true,
1292 arguments,
1293 location: call_location,
1294 };
1295 break;
1296 }
1297 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
1298 }
1299 }
1300 } else {
1301
1302 object = Expression::MemberExpression {
1303 object: Box::new(object),
1304 property: None,
1305 property_expr: Some(Box::new(property_expr)),
1306 computed: true,
1307 location: member_expr_location,
1308 };
1309 }
1310 } else {
1311
1312 object = Expression::MemberExpression {
1313 object: Box::new(object),
1314 property: None,
1315 property_expr: Some(Box::new(property_expr)),
1316 computed: true,
1317 location: member_expr_location,
1318 };
1319 }
1320 },
1321 _ => break,
1322 },
1323 None => break,
1324 }
1325 }
1326 Ok(object)
1327 }
1328
1329 fn parse_loop_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
1330 self.advance();
1331
1332 let variable = match &self.current_token {
1333 Some(token_with_span) => match &token_with_span.token {
1334 Token::Identifier(name) => name.clone(),
1335 _ => return Err(ParseError::ExpectedToken("identifier".to_string(), self.current_location())),
1336 },
1337 None => return Err(ParseError::EndOfInput(self.current_location())),
1338 };
1339 self.advance();
1340
1341 match &self.current_token {
1342 Some(token_with_span) => {
1343 if token_with_span.token != Token::In {
1344 return Err(ParseError::ExpectedToken("'in'".to_string(), self.current_location()));
1345 }
1346 self.advance();
1347 },
1348 None => return Err(ParseError::EndOfInput(self.current_location())),
1349 }
1350
1351 let iterable = self.parse_expression()?;
1352
1353 let body = self.parse_block()?;
1354
1355 let end_location = body.location.clone();
1356
1357 let location = SourceLocation::new(
1358 start_location.start_line,
1359 start_location.start_column,
1360 end_location.end_line,
1361 end_location.end_column
1362 );
1363
1364 Ok(Statement::LoopStatement {
1365 variable,
1366 iterable,
1367 body,
1368 location,
1369 })
1370 }
1371
1372 fn parse_end_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
1373 self.advance();
1374
1375 let semicolon_location = self.current_location();
1376 self.expect(Token::Semicolon)?;
1377
1378 let end_location = semicolon_location;
1379
1380 let location = SourceLocation::new(
1381 start_location.start_line,
1382 start_location.start_column,
1383 end_location.end_line,
1384 end_location.end_column
1385 );
1386
1387 Ok(Statement::EndStatement { location })
1388 }
1389
1390 fn parse_continue_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
1391 self.advance();
1392
1393 let semicolon_location = self.current_location();
1394 self.expect(Token::Semicolon)?;
1395
1396 let end_location = semicolon_location;
1397
1398 let location = SourceLocation::new(
1399 start_location.start_line,
1400 start_location.start_column,
1401 end_location.end_line,
1402 end_location.end_column
1403 );
1404
1405 Ok(Statement::ContinueStatement { location })
1406 }
1407}