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_logical_or()?;
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_logical_or()?;
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_logical_or(&mut self) -> Result<Expression, ParseError> {
429 let start_location = self.current_location();
430 let mut expr = self.parse_logical_and()?;
431
432 while let Some(token_with_span) = self.current_token {
433 match &token_with_span.token {
434 Token::Or => {
435 self.advance();
436 let right = self.parse_logical_and()?;
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 expr = Expression::BinaryExpression {
447 left: Box::new(expr),
448 operator: Operator::Or,
449 right: Box::new(right),
450 location,
451 };
452 }
453 _ => break,
454 }
455 }
456
457 Ok(expr)
458 }
459
460 fn parse_logical_and(&mut self) -> Result<Expression, ParseError> {
461 let start_location = self.current_location();
462 let mut expr = self.parse_equality()?;
463
464 while let Some(token_with_span) = self.current_token {
465 match &token_with_span.token {
466 Token::And => {
467 self.advance();
468 let right = self.parse_equality()?;
469 let right_loc = get_expr_location!(right);
470
471 let location = SourceLocation::new(
472 start_location.start_line,
473 start_location.start_column,
474 right_loc.end_line,
475 right_loc.end_column
476 );
477
478 expr = Expression::BinaryExpression {
479 left: Box::new(expr),
480 operator: Operator::And,
481 right: Box::new(right),
482 location,
483 };
484 }
485 _ => break,
486 }
487 }
488
489 Ok(expr)
490 }
491
492 fn parse_comparison(&mut self) -> Result<Expression, ParseError> {
493 let start_location = self.current_location();
494 let mut expr = self.parse_additive()?;
495
496 while let Some(token_with_span) = self.current_token {
497 expr = match token_with_span.token {
498 Token::Greater => {
499 self.advance();
500 let right = self.parse_additive()?;
501 let right_loc = get_expr_location!(right);
502
503 let location = SourceLocation::new(
504 start_location.start_line,
505 start_location.start_column,
506 right_loc.end_line,
507 right_loc.end_column
508 );
509
510 Expression::BinaryExpression {
511 left: Box::new(expr),
512 operator: Operator::Greater,
513 right: Box::new(right),
514 location,
515 }
516 },
517 Token::Less => {
518 self.advance();
519 let right = self.parse_additive()?;
520 let right_loc = get_expr_location!(right);
521
522 let location = SourceLocation::new(
523 start_location.start_line,
524 start_location.start_column,
525 right_loc.end_line,
526 right_loc.end_column
527 );
528
529 Expression::BinaryExpression {
530 left: Box::new(expr),
531 operator: Operator::Less,
532 right: Box::new(right),
533 location,
534 }
535 },
536 Token::GreaterEqual => {
537 self.advance();
538 let right = self.parse_additive()?;
539 let right_loc = get_expr_location!(right);
540
541 let location = SourceLocation::new(
542 start_location.start_line,
543 start_location.start_column,
544 right_loc.end_line,
545 right_loc.end_column
546 );
547
548 Expression::BinaryExpression {
549 left: Box::new(expr),
550 operator: Operator::GreaterEqual,
551 right: Box::new(right),
552 location,
553 }
554 },
555 Token::LessEqual => {
556 self.advance();
557 let right = self.parse_additive()?;
558 let right_loc = get_expr_location!(right);
559
560 let location = SourceLocation::new(
561 start_location.start_line,
562 start_location.start_column,
563 right_loc.end_line,
564 right_loc.end_column
565 );
566
567 Expression::BinaryExpression {
568 left: Box::new(expr),
569 operator: Operator::LessEqual,
570 right: Box::new(right),
571 location,
572 }
573 },
574 _ => break,
575 };
576 }
577 Ok(expr)
578 }
579
580 fn parse_equality(&mut self) -> Result<Expression, ParseError> {
581 let start_location = self.current_location();
582 let mut expr = self.parse_comparison()?;
583
584 while let Some(token_with_span) = self.current_token {
585 match &token_with_span.token {
586 Token::EqualEqual => {
587 self.advance();
588 let right = self.parse_comparison()?;
589 let right_loc = get_expr_location!(right);
590
591 let location = SourceLocation::new(
592 start_location.start_line,
593 start_location.start_column,
594 right_loc.end_line,
595 right_loc.end_column
596 );
597
598 expr = Expression::BinaryExpression {
599 left: Box::new(expr),
600 operator: Operator::Equal,
601 right: Box::new(right),
602 location,
603 };
604 }
605 _ => break,
606 }
607 }
608
609 Ok(expr)
610 }
611
612 fn parse_additive(&mut self) -> Result<Expression, ParseError> {
613 let start_location = self.current_location();
614 let mut expr = self.parse_multiplicative()?;
615
616 while let Some(token_with_span) = self.current_token {
617 match &token_with_span.token {
618 Token::Plus => {
619 self.advance();
620 let right = self.parse_multiplicative()?;
621 let right_loc = get_expr_location!(right);
622
623 let location = SourceLocation::new(
624 start_location.start_line,
625 start_location.start_column,
626 right_loc.end_line,
627 right_loc.end_column
628 );
629
630 expr = Expression::BinaryExpression {
631 left: Box::new(expr),
632 operator: Operator::Plus,
633 right: Box::new(right),
634 location,
635 };
636 }
637 _ => break,
638 }
639 }
640
641 Ok(expr)
642 }
643
644 fn parse_multiplicative(&mut self) -> Result<Expression, ParseError> {
645 let start_location = self.current_location();
646 let mut expr = self.parse_unary()?;
647
648 expr = self.parse_member_access(expr)?;
649
650 while let Some(token_with_span) = self.current_token {
651 match &token_with_span.token {
652 Token::Multiply => {
653 self.advance();
654 let right = self.parse_primary()?;
655 let right_with_member = self.parse_member_access(right)?;
656 let right_loc = get_expr_location!(right_with_member);
657
658 let location = SourceLocation::new(
659 start_location.start_line,
660 start_location.start_column,
661 right_loc.end_line,
662 right_loc.end_column
663 );
664
665 expr = Expression::BinaryExpression {
666 left: Box::new(expr),
667 operator: Operator::Multiply,
668 right: Box::new(right_with_member),
669 location,
670 };
671 }
672 Token::Divide => {
673 self.advance();
674 let right = self.parse_primary()?;
675 let right_with_member = self.parse_member_access(right)?;
676 let right_loc = get_expr_location!(right_with_member);
677
678 let location = SourceLocation::new(
679 start_location.start_line,
680 start_location.start_column,
681 right_loc.end_line,
682 right_loc.end_column
683 );
684
685 expr = Expression::BinaryExpression {
686 left: Box::new(expr),
687 operator: Operator::Divide,
688 right: Box::new(right_with_member),
689 location,
690 };
691 }
692 _ => break,
693 }
694 }
695
696 Ok(expr)
697 }
698
699 fn parse_unary(&mut self) -> Result<Expression, ParseError> {
700 let start_location = self.current_location();
701
702 match &self.current_token {
703 Some(token_with_span) => match &token_with_span.token {
704 Token::Bang => {
705 self.advance();
706 let operand = self.parse_unary()?;
707 let operand_loc = get_expr_location!(operand);
708
709 let location = SourceLocation::new(
710 start_location.start_line,
711 start_location.start_column,
712 operand_loc.end_line,
713 operand_loc.end_column
714 );
715
716 Ok(Expression::UnaryExpression {
717 operator: UnaryOperator::Not,
718 operand: Box::new(operand),
719 location,
720 })
721 },
722 _ => self.parse_primary()
723 },
724 None => Err(ParseError::EndOfInput(start_location)),
725 }
726 }
727
728 fn parse_primary(&mut self) -> Result<Expression, ParseError> {
729 let start_location = self.current_location();
730
731 match &self.current_token {
732 Some(token_with_span) => match &token_with_span.token {
733 Token::KeysOf => {
734 if self.flags.allow_object_keys {
735 self.advance();
736
737 let mut object_expr = self.parse_primary()?;
739
740 object_expr = self.parse_member_access(object_expr)?;
742
743 let object_loc = get_expr_location!(object_expr);
744
745 let location = SourceLocation::new(
746 start_location.start_line,
747 start_location.start_column,
748 object_loc.end_line,
749 object_loc.end_column
750 );
751
752 Ok(Expression::KeysOfExpression {
753 object: Box::new(object_expr),
754 location,
755 })
756 } else {
757 Err(ParseError::FeatureDisabled("Object keys operator (keysof)".to_string(), start_location))
758 }
759 },
760 Token::OpenBracket => {
761 if self.flags.allow_array_constructions {
762 self.parse_array_literal(start_location)
763 } else {
764 Err(ParseError::FeatureDisabled("Array literals".to_string(), start_location))
765 }
766 },
767 Token::OpenBrace => {
768 match self.peek() {
769 Some(next_token) => match &next_token.token {
770 Token::Identifier(_) => {
771 if self.flags.allow_object_constructions {
772 self.parse_object_literal(start_location)
773 } else {
774 Err(ParseError::FeatureDisabled("Object literals".to_string(), start_location))
775 }
776 },
777 Token::CloseBrace => {
778 self.advance();
779 self.advance();
780 if self.flags.allow_object_constructions {
781 Ok(Expression::ObjectExpression { properties: vec![], location: start_location })
782 } else {
783 Err(ParseError::FeatureDisabled("Object literals".to_string(), start_location))
784 }
785 },
786 _ => {
787 if self.flags.allow_object_constructions {
788 self.parse_object_literal(start_location)
789 } else {
790 Err(ParseError::FeatureDisabled("Object literals".to_string(), start_location))
791 }
792 }
793 },
794 None => Err(ParseError::EndOfInput(start_location)),
795 }
796 },
797 Token::OpenParen => {
798 self.advance();
799 let expr = self.parse_expression()?;
800 self.expect(Token::CloseParen)?;
801 Ok(expr)
802 },
803 Token::Identifier(name) => {
804 let id_name = name.clone();
805 self.advance();
806
807 if let Some(next_token) = self.current_token {
808 if next_token.token == Token::OpenParen {
809 return self.parse_function_call(id_name, start_location);
810 }
811 }
812
813 Ok(Expression::Identifier {
814 name: id_name,
815 location: start_location,
816 })
817 },
818 Token::StringLiteral(value) => {
819 let str_value = value.clone();
820 self.advance();
821 Ok(Expression::StringLiteral {
822 value: str_value,
823 location: start_location,
824 })
825 },
826 Token::NumberLiteral(value) => {
827 let num_value = *value;
828 self.advance();
829 Ok(Expression::NumberLiteral {
830 value: num_value,
831 location: start_location,
832 })
833 },
834 Token::True => {
835 self.advance();
836 Ok(Expression::BooleanLiteral {
837 value: true,
838 location: start_location,
839 })
840 },
841
842 Token::False => {
843 self.advance();
844 Ok(Expression::BooleanLiteral {
845 value: false,
846 location: start_location,
847 })
848 },
849
850 Token::Null => {
851 self.advance();
852 Ok(Expression::NullLiteral {
853 location: start_location,
854 })
855 },
856 _ => Err(ParseError::UnexpectedToken(format!(
857 "Unexpected token: {:?}",
858 token_with_span.token
859 ), start_location)),
860 },
861 None => Err(ParseError::EndOfInput(start_location)),
862 }
863 }
864
865 fn parse_function_call(&mut self, callee: String, start_location: SourceLocation) -> Result<Expression, ParseError> {
866 self.expect(Token::OpenParen)?;
867
868 let mut arguments = Vec::new();
869
870 if let Some(token_with_span) = self.current_token {
871 if token_with_span.token == Token::CloseParen {
872 let end_location = self.current_location();
873 self.advance();
874
875 let location = SourceLocation::new(
876 start_location.start_line,
877 start_location.start_column,
878 end_location.end_line,
879 end_location.end_column
880 );
881
882 return Ok(Expression::CallExpression { callee, arguments, location });
883 }
884 }
885
886 arguments.push(self.parse_expression()?);
887
888 while let Some(token_with_span) = self.current_token {
889 match &token_with_span.token {
890 Token::Comma => {
891 self.advance();
892 arguments.push(self.parse_expression()?);
893 }
894 Token::CloseParen => {
895 let end_location = self.current_location();
896 self.advance();
897
898 let location = SourceLocation::new(
899 start_location.start_line,
900 start_location.start_column,
901 end_location.end_line,
902 end_location.end_column
903 );
904
905 return Ok(Expression::CallExpression { callee, arguments, location });
906 }
907 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
908 }
909 }
910
911 Err(ParseError::ExpectedToken("')'".to_string(), self.current_location()))
912 }
913
914 fn parse_callback_declaration(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
915 self.advance();
916
917 let name = match &self.current_token {
918 Some(token_with_span) => match &token_with_span.token {
919 Token::Identifier(name) => name.clone(),
920 _ => return Err(ParseError::ExpectedToken("callback name".to_string(), self.current_location())),
921 },
922 None => return Err(ParseError::EndOfInput(self.current_location())),
923 };
924 self.advance();
925
926 self.expect(Token::OpenParen)?;
927 let mut params = Vec::new();
928
929 if let Some(token_with_span) = self.current_token {
930 if token_with_span.token == Token::CloseParen {
931 self.advance();
932 } else {
933 if let Some(token_with_span) = self.current_token {
934 match &token_with_span.token {
935 Token::Identifier(param) => {
936 params.push(param.clone());
937 self.advance();
938 },
939 _ => return Err(ParseError::ExpectedToken("parameter name".to_string(), self.current_location())),
940 }
941 }
942
943 while let Some(token_with_span) = self.current_token {
944 match &token_with_span.token {
945 Token::Comma => {
946 self.advance();
947 match &self.current_token {
948 Some(token_with_span) => match &token_with_span.token {
949 Token::Identifier(param) => {
950 params.push(param.clone());
951 self.advance();
952 },
953 _ => return Err(ParseError::ExpectedToken("parameter name".to_string(), self.current_location())),
954 },
955 None => return Err(ParseError::EndOfInput(self.current_location())),
956 }
957 },
958 Token::CloseParen => {
959 self.advance();
960 break;
961 },
962 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
963 }
964 }
965 }
966 } else {
967 return Err(ParseError::EndOfInput(self.current_location()));
968 }
969
970 let body = self.parse_block()?;
971
972 let end_location = body.location.clone();
973
974 let location = SourceLocation::new(
975 start_location.start_line,
976 start_location.start_column,
977 end_location.end_line,
978 end_location.end_column
979 );
980
981 Ok(Statement::CallbackDeclaration {
982 name,
983 params,
984 body,
985 location,
986 })
987 }
988
989 fn parse_return_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
990 self.advance();
991
992 let value = self.parse_expression()?;
993
994 let semicolon_location = self.current_location();
995 self.expect(Token::Semicolon)?;
996
997 let end_location = semicolon_location;
998
999 let location = SourceLocation::new(
1000 start_location.start_line,
1001 start_location.start_column,
1002 end_location.end_line,
1003 end_location.end_column
1004 );
1005
1006 Ok(Statement::ReturnStatement { value, location })
1007 }
1008
1009 fn parse_array_literal(&mut self, start_location: SourceLocation) -> Result<Expression, ParseError> {
1010 self.advance();
1011
1012 let mut elements = Vec::new();
1013
1014 if let Some(token_with_span) = self.current_token {
1015 if token_with_span.token == Token::CloseBracket {
1016 let end_location = self.current_location();
1017 self.advance();
1018
1019 let location = SourceLocation::new(
1020 start_location.start_line,
1021 start_location.start_column,
1022 end_location.end_line,
1023 end_location.end_column
1024 );
1025
1026 return Ok(Expression::ArrayExpression { elements, location });
1027 }
1028 }
1029
1030 elements.push(self.parse_expression()?);
1031
1032 while let Some(token_with_span) = self.current_token {
1033 match &token_with_span.token {
1034 Token::Comma => {
1035 self.advance();
1036 elements.push(self.parse_expression()?);
1037 }
1038 Token::CloseBracket => {
1039 let end_location = self.current_location();
1040 self.advance();
1041
1042 let location = SourceLocation::new(
1043 start_location.start_line,
1044 start_location.start_column,
1045 end_location.end_line,
1046 end_location.end_column
1047 );
1048
1049 return Ok(Expression::ArrayExpression { elements, location });
1050 }
1051 _ => return Err(ParseError::ExpectedToken("',' or ']'".to_string(), self.current_location())),
1052 }
1053 }
1054
1055 Err(ParseError::ExpectedToken("']'".to_string(), self.current_location()))
1056 }
1057
1058 fn parse_object_literal(&mut self, start_location: SourceLocation) -> Result<Expression, ParseError> {
1059 self.advance();
1060
1061 let mut properties = Vec::new();
1062
1063 if let Some(token_with_span) = self.current_token {
1064 if token_with_span.token == Token::CloseBrace {
1065 let end_location = self.current_location();
1066 self.advance();
1067
1068 let location = SourceLocation::new(
1069 start_location.start_line,
1070 start_location.start_column,
1071 end_location.end_line,
1072 end_location.end_column
1073 );
1074
1075 return Ok(Expression::ObjectExpression { properties, location });
1076 }
1077 }
1078
1079 let property = self.parse_object_property()?;
1080 properties.push(property);
1081
1082 while let Some(token_with_span) = self.current_token {
1083 match &token_with_span.token {
1084 Token::Comma => {
1085 self.advance();
1086 let property = self.parse_object_property()?;
1087 properties.push(property);
1088 }
1089 Token::CloseBrace => {
1090 let end_location = self.current_location();
1091 self.advance();
1092
1093 let location = SourceLocation::new(
1094 start_location.start_line,
1095 start_location.start_column,
1096 end_location.end_line,
1097 end_location.end_column
1098 );
1099
1100 return Ok(Expression::ObjectExpression { properties, location });
1101 }
1102 _ => return Err(ParseError::ExpectedToken("',' or '}'".to_string(), self.current_location())),
1103 }
1104 }
1105
1106 Err(ParseError::ExpectedToken("'}'".to_string(), self.current_location()))
1107 }
1108
1109 fn parse_object_property(&mut self) -> Result<Property, ParseError> {
1110 let start_location = self.current_location();
1111
1112 let key = match &self.current_token {
1113 Some(token_with_span) => match &token_with_span.token {
1114 Token::Identifier(name) => name.clone(),
1115 Token::StringLiteral(value) => value.clone(),
1116 _ => return Err(ParseError::ExpectedToken("property key".to_string(), self.current_location())),
1117 },
1118 None => return Err(ParseError::EndOfInput(self.current_location())),
1119 };
1120 self.advance();
1121
1122 self.expect(Token::Colon)?;
1123
1124 let value = self.parse_expression()?;
1125
1126 let end_location = get_expr_location!(value);
1127
1128 let location = SourceLocation::new(
1129 start_location.start_line,
1130 start_location.start_column,
1131 end_location.end_line,
1132 end_location.end_column
1133 );
1134
1135 Ok(Property::new(key, value, location))
1136 }
1137
1138 fn parse_member_access(&mut self, mut object: Expression) -> Result<Expression, ParseError> {
1139 loop {
1140 match &self.current_token {
1141 Some(token_with_span) => match &token_with_span.token {
1142 Token::Dot => {
1143 if !self.flags.allow_object_navigation {
1144 return Err(ParseError::FeatureDisabled("Object navigation (dot notation)".to_string(), self.current_location()));
1145 }
1146
1147 self.advance();
1148
1149 match &self.current_token {
1150 Some(token_with_span) => match &token_with_span.token {
1151 Token::Identifier(prop_name) => {
1152 let property = prop_name.clone();
1153 let property_location = self.current_location();
1154 self.advance();
1155
1156
1157 let obj_start_line = get_expr_start_line!(object);
1158
1159 let obj_start_column = get_expr_start_column!(object);
1160
1161
1162 if let Some(token_with_span) = self.current_token {
1163 if token_with_span.token == Token::OpenParen {
1164 self.advance();
1165
1166
1167 let mut arguments = Vec::new();
1168
1169
1170 if let Some(token_with_span) = self.current_token {
1171 if token_with_span.token == Token::CloseParen {
1172
1173 let end_call_location = self.current_location();
1174 self.advance();
1175
1176
1177 let call_location = SourceLocation::new(
1178 obj_start_line,
1179 obj_start_column,
1180 end_call_location.end_line,
1181 end_call_location.end_column
1182 );
1183
1184
1185 object = Expression::MemberCallExpression {
1186 object: Box::new(object),
1187 property: Some(property),
1188 property_expr: None,
1189 computed: false,
1190 arguments,
1191 location: call_location,
1192 };
1193 continue;
1194 }
1195 }
1196
1197
1198 arguments.push(self.parse_expression()?);
1199
1200
1201 while let Some(token_with_span) = self.current_token {
1202 match &token_with_span.token {
1203 Token::Comma => {
1204 self.advance();
1205 arguments.push(self.parse_expression()?);
1206 }
1207 Token::CloseParen => {
1208 let end_call_location = self.current_location();
1209 self.advance();
1210
1211
1212 let call_location = SourceLocation::new(
1213 obj_start_line,
1214 obj_start_column,
1215 end_call_location.end_line,
1216 end_call_location.end_column
1217 );
1218
1219
1220 object = Expression::MemberCallExpression {
1221 object: Box::new(object),
1222 property: Some(property),
1223 property_expr: None,
1224 computed: false,
1225 arguments,
1226 location: call_location,
1227 };
1228 break;
1229 }
1230 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
1231 }
1232 }
1233 } else {
1234
1235 let member_expr_location = SourceLocation::new(
1236 obj_start_line,
1237 obj_start_column,
1238 property_location.end_line,
1239 property_location.end_column
1240 );
1241
1242 object = Expression::MemberExpression {
1243 object: Box::new(object),
1244 property: Some(property),
1245 property_expr: None,
1246 computed: false,
1247 location: member_expr_location,
1248 };
1249 }
1250 } else {
1251
1252 let member_expr_location = SourceLocation::new(
1253 obj_start_line,
1254 obj_start_column,
1255 property_location.end_line,
1256 property_location.end_column
1257 );
1258
1259 object = Expression::MemberExpression {
1260 object: Box::new(object),
1261 property: Some(property),
1262 property_expr: None,
1263 computed: false,
1264 location: member_expr_location,
1265 };
1266 }
1267 }
1268 _ => return Err(ParseError::ExpectedToken("property name".to_string(), self.current_location())),
1269 },
1270 None => return Err(ParseError::EndOfInput(self.current_location())),
1271 }
1272 },
1273
1274 Token::OpenBracket => {
1275 if !self.flags.allow_object_navigation {
1276 return Err(ParseError::FeatureDisabled("Object navigation (bracket notation)".to_string(), self.current_location()));
1277 }
1278
1279 self.advance();
1280
1281 let property_expr = self.parse_expression()?;
1282
1283 let close_bracket_location = self.current_location();
1284 self.expect(Token::CloseBracket)?;
1285
1286 let obj_start_line = get_expr_start_line!(object);
1287
1288 let obj_start_column = get_expr_start_column!(object);
1289
1290 let member_expr_location = SourceLocation::new(
1291 obj_start_line,
1292 obj_start_column,
1293 close_bracket_location.end_line,
1294 close_bracket_location.end_column
1295 );
1296
1297 if let Some(token_with_span) = self.current_token {
1298 if token_with_span.token == Token::OpenParen {
1299
1300 self.advance();
1301
1302 let mut arguments = Vec::new();
1303
1304
1305 if let Some(token_with_span) = self.current_token {
1306 if token_with_span.token == Token::CloseParen {
1307 let end_call_location = self.current_location();
1308 self.advance();
1309
1310 let call_location = SourceLocation::new(
1311 obj_start_line,
1312 obj_start_column,
1313 end_call_location.end_line,
1314 end_call_location.end_column
1315 );
1316
1317
1318 object = Expression::MemberCallExpression {
1319 object: Box::new(object),
1320 property: None,
1321 property_expr: Some(Box::new(property_expr)),
1322 computed: true,
1323 arguments,
1324 location: call_location,
1325 };
1326 continue;
1327 }
1328 }
1329
1330
1331 arguments.push(self.parse_expression()?);
1332
1333 while let Some(token_with_span) = self.current_token {
1334 match &token_with_span.token {
1335 Token::Comma => {
1336 self.advance();
1337 arguments.push(self.parse_expression()?);
1338 }
1339 Token::CloseParen => {
1340 let end_call_location = self.current_location();
1341 self.advance();
1342
1343 let call_location = SourceLocation::new(
1344 obj_start_line,
1345 obj_start_column,
1346 end_call_location.end_line,
1347 end_call_location.end_column
1348 );
1349
1350
1351 object = Expression::MemberCallExpression {
1352 object: Box::new(object),
1353 property: None,
1354 property_expr: Some(Box::new(property_expr)),
1355 computed: true,
1356 arguments,
1357 location: call_location,
1358 };
1359 break;
1360 }
1361 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
1362 }
1363 }
1364 } else {
1365
1366 object = Expression::MemberExpression {
1367 object: Box::new(object),
1368 property: None,
1369 property_expr: Some(Box::new(property_expr)),
1370 computed: true,
1371 location: member_expr_location,
1372 };
1373 }
1374 } else {
1375
1376 object = Expression::MemberExpression {
1377 object: Box::new(object),
1378 property: None,
1379 property_expr: Some(Box::new(property_expr)),
1380 computed: true,
1381 location: member_expr_location,
1382 };
1383 }
1384 },
1385 _ => break,
1386 },
1387 None => break,
1388 }
1389 }
1390 Ok(object)
1391 }
1392
1393 fn parse_loop_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
1394 self.advance();
1395
1396 let variable = match &self.current_token {
1397 Some(token_with_span) => match &token_with_span.token {
1398 Token::Identifier(name) => name.clone(),
1399 _ => return Err(ParseError::ExpectedToken("identifier".to_string(), self.current_location())),
1400 },
1401 None => return Err(ParseError::EndOfInput(self.current_location())),
1402 };
1403 self.advance();
1404
1405 match &self.current_token {
1406 Some(token_with_span) => {
1407 if token_with_span.token != Token::In {
1408 return Err(ParseError::ExpectedToken("'in'".to_string(), self.current_location()));
1409 }
1410 self.advance();
1411 },
1412 None => return Err(ParseError::EndOfInput(self.current_location())),
1413 }
1414
1415 let iterable = self.parse_expression()?;
1416
1417 let body = self.parse_block()?;
1418
1419 let end_location = body.location.clone();
1420
1421 let location = SourceLocation::new(
1422 start_location.start_line,
1423 start_location.start_column,
1424 end_location.end_line,
1425 end_location.end_column
1426 );
1427
1428 Ok(Statement::LoopStatement {
1429 variable,
1430 iterable,
1431 body,
1432 location,
1433 })
1434 }
1435
1436 fn parse_end_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
1437 self.advance();
1438
1439 let semicolon_location = self.current_location();
1440 self.expect(Token::Semicolon)?;
1441
1442 let end_location = semicolon_location;
1443
1444 let location = SourceLocation::new(
1445 start_location.start_line,
1446 start_location.start_column,
1447 end_location.end_line,
1448 end_location.end_column
1449 );
1450
1451 Ok(Statement::EndStatement { location })
1452 }
1453
1454 fn parse_continue_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
1455 self.advance();
1456
1457 let semicolon_location = self.current_location();
1458 self.expect(Token::Semicolon)?;
1459
1460 let end_location = semicolon_location;
1461
1462 let location = SourceLocation::new(
1463 start_location.start_line,
1464 start_location.start_column,
1465 end_location.end_line,
1466 end_location.end_column
1467 );
1468
1469 Ok(Statement::ContinueStatement { location })
1470 }
1471}