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::InlineCallbackExpression { 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::InlineCallbackExpression { 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::InlineCallbackExpression { 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 Token::NotEqual => {
606 self.advance();
607 let right = self.parse_comparison()?;
608 let right_loc = get_expr_location!(right);
609
610 let location = SourceLocation::new(
611 start_location.start_line,
612 start_location.start_column,
613 right_loc.end_line,
614 right_loc.end_column
615 );
616
617 expr = Expression::BinaryExpression {
618 left: Box::new(expr),
619 operator: Operator::NotEqual,
620 right: Box::new(right),
621 location,
622 };
623 }
624 _ => break,
625 }
626 }
627
628 Ok(expr)
629 }
630
631 fn parse_additive(&mut self) -> Result<Expression, ParseError> {
632 let start_location = self.current_location();
633 let mut expr = self.parse_multiplicative()?;
634
635 while let Some(token_with_span) = self.current_token {
636 match &token_with_span.token {
637 Token::Plus => {
638 self.advance();
639 let right = self.parse_multiplicative()?;
640 let right_loc = get_expr_location!(right);
641
642 let location = SourceLocation::new(
643 start_location.start_line,
644 start_location.start_column,
645 right_loc.end_line,
646 right_loc.end_column
647 );
648
649 expr = Expression::BinaryExpression {
650 left: Box::new(expr),
651 operator: Operator::Plus,
652 right: Box::new(right),
653 location,
654 };
655 },
656 Token::Minus => {
657 self.advance();
658 let right = self.parse_multiplicative()?;
659 let right_loc = get_expr_location!(right);
660
661 let location = SourceLocation::new(
662 start_location.start_line,
663 start_location.start_column,
664 right_loc.end_line,
665 right_loc.end_column
666 );
667
668 expr = Expression::BinaryExpression {
669 left: Box::new(expr),
670 operator: Operator::Minus,
671 right: Box::new(right),
672 location,
673 };
674 }
675 _ => break,
676 }
677 }
678
679 Ok(expr)
680 }
681
682 fn parse_multiplicative(&mut self) -> Result<Expression, ParseError> {
683 let start_location = self.current_location();
684 let mut expr = self.parse_unary()?;
685
686 expr = self.parse_member_access(expr)?;
687
688 while let Some(token_with_span) = self.current_token {
689 match &token_with_span.token {
690 Token::Multiply => {
691 self.advance();
692 let right = self.parse_primary()?;
693 let right_with_member = self.parse_member_access(right)?;
694 let right_loc = get_expr_location!(right_with_member);
695
696 let location = SourceLocation::new(
697 start_location.start_line,
698 start_location.start_column,
699 right_loc.end_line,
700 right_loc.end_column
701 );
702
703 expr = Expression::BinaryExpression {
704 left: Box::new(expr),
705 operator: Operator::Multiply,
706 right: Box::new(right_with_member),
707 location,
708 };
709 }
710 Token::Divide => {
711 self.advance();
712 let right = self.parse_primary()?;
713 let right_with_member = self.parse_member_access(right)?;
714 let right_loc = get_expr_location!(right_with_member);
715
716 let location = SourceLocation::new(
717 start_location.start_line,
718 start_location.start_column,
719 right_loc.end_line,
720 right_loc.end_column
721 );
722
723 expr = Expression::BinaryExpression {
724 left: Box::new(expr),
725 operator: Operator::Divide,
726 right: Box::new(right_with_member),
727 location,
728 };
729 }
730 _ => break,
731 }
732 }
733
734 Ok(expr)
735 }
736
737 fn parse_unary(&mut self) -> Result<Expression, ParseError> {
738 let start_location = self.current_location();
739
740 match &self.current_token {
741 Some(token_with_span) => match &token_with_span.token {
742 Token::Bang => {
743 self.advance();
744 let operand = self.parse_unary()?;
745 let operand_loc = get_expr_location!(operand);
746
747 let location = SourceLocation::new(
748 start_location.start_line,
749 start_location.start_column,
750 operand_loc.end_line,
751 operand_loc.end_column
752 );
753
754 Ok(Expression::UnaryExpression {
755 operator: UnaryOperator::Not,
756 operand: Box::new(operand),
757 location,
758 })
759 },
760 _ => self.parse_primary()
761 },
762 None => Err(ParseError::EndOfInput(start_location)),
763 }
764 }
765
766 fn parse_primary(&mut self) -> Result<Expression, ParseError> {
767 let start_location = self.current_location();
768
769 match &self.current_token {
770 Some(token_with_span) => match &token_with_span.token {
771 Token::KeysOf => {
772 if self.flags.allow_object_keys {
773 self.advance();
774
775 let mut object_expr = self.parse_primary()?;
777
778 object_expr = self.parse_member_access(object_expr)?;
780
781 let object_loc = get_expr_location!(object_expr);
782
783 let location = SourceLocation::new(
784 start_location.start_line,
785 start_location.start_column,
786 object_loc.end_line,
787 object_loc.end_column
788 );
789
790 Ok(Expression::KeysOfExpression {
791 object: Box::new(object_expr),
792 location,
793 })
794 } else {
795 Err(ParseError::FeatureDisabled("Object keys operator (keysof)".to_string(), start_location))
796 }
797 },
798 Token::OpenBracket => {
799 if self.flags.allow_array_constructions {
800 self.parse_array_literal(start_location)
801 } else {
802 Err(ParseError::FeatureDisabled("Array literals".to_string(), start_location))
803 }
804 },
805 Token::OpenBrace => {
806 match self.peek() {
807 Some(next_token) => match &next_token.token {
808 Token::Identifier(_) => {
809 if self.flags.allow_object_constructions {
810 self.parse_object_literal(start_location)
811 } else {
812 Err(ParseError::FeatureDisabled("Object literals".to_string(), start_location))
813 }
814 },
815 Token::CloseBrace => {
816 self.advance();
817 self.advance();
818 if self.flags.allow_object_constructions {
819 Ok(Expression::ObjectExpression { properties: vec![], location: start_location })
820 } else {
821 Err(ParseError::FeatureDisabled("Object literals".to_string(), start_location))
822 }
823 },
824 _ => {
825 if self.flags.allow_object_constructions {
826 self.parse_object_literal(start_location)
827 } else {
828 Err(ParseError::FeatureDisabled("Object literals".to_string(), start_location))
829 }
830 }
831 },
832 None => Err(ParseError::EndOfInput(start_location)),
833 }
834 },
835 Token::OpenParen => {
836 self.advance();
837 let expr = self.parse_expression()?;
838 self.expect(Token::CloseParen)?;
839 Ok(expr)
840 },
841 Token::Identifier(name) => {
842 let id_name = name.clone();
843 self.advance();
844
845 if let Some(next_token) = self.current_token {
846 if next_token.token == Token::OpenParen {
847 return self.parse_function_call(id_name, start_location);
848 }
849 }
850
851 Ok(Expression::Identifier {
852 name: id_name,
853 location: start_location,
854 })
855 },
856 Token::StringLiteral(value) => {
857 let str_value = value.clone();
858 self.advance();
859 Ok(Expression::StringLiteral {
860 value: str_value,
861 location: start_location,
862 })
863 },
864 Token::NumberLiteral(value) => {
865 let num_value = *value;
866 self.advance();
867 Ok(Expression::NumberLiteral {
868 value: num_value,
869 location: start_location,
870 })
871 },
872 Token::True => {
873 self.advance();
874 Ok(Expression::BooleanLiteral {
875 value: true,
876 location: start_location,
877 })
878 },
879
880 Token::False => {
881 self.advance();
882 Ok(Expression::BooleanLiteral {
883 value: false,
884 location: start_location,
885 })
886 },
887
888 Token::Null => {
889 self.advance();
890 Ok(Expression::NullLiteral {
891 location: start_location,
892 })
893 },
894 _ => Err(ParseError::UnexpectedToken(format!(
895 "Unexpected token: {:?}",
896 token_with_span.token
897 ), start_location)),
898 },
899 None => Err(ParseError::EndOfInput(start_location)),
900 }
901 }
902
903 fn parse_function_call(&mut self, callee: String, start_location: SourceLocation) -> Result<Expression, ParseError> {
904 self.expect(Token::OpenParen)?;
905
906 let mut arguments = Vec::new();
907
908 if let Some(token_with_span) = self.current_token {
909 if token_with_span.token == Token::CloseParen {
910 let end_location = self.current_location();
911 self.advance();
912
913 let location = SourceLocation::new(
914 start_location.start_line,
915 start_location.start_column,
916 end_location.end_line,
917 end_location.end_column
918 );
919
920 return Ok(Expression::CallExpression { callee, arguments, location });
921 }
922 }
923
924 if let Some(token_with_span) = self.current_token {
926 if token_with_span.token == Token::Cb {
927 if !self.flags.allow_callbacks {
928 return Err(ParseError::FeatureDisabled("Inline callback expressions".to_string(), self.current_location()));
929 }
930 let inline_callback = self.parse_inline_callback()?;
931 arguments.push(inline_callback);
932 } else {
933 arguments.push(self.parse_expression()?);
934 }
935 }
936
937 while let Some(token_with_span) = self.current_token {
939 match &token_with_span.token {
940 Token::Comma => {
941 self.advance();
942
943 if let Some(token_with_span) = self.current_token {
945 if token_with_span.token == Token::Cb {
946 if !self.flags.allow_callbacks {
947 return Err(ParseError::FeatureDisabled("Inline callback expressions".to_string(), self.current_location()));
948 }
949 let inline_callback = self.parse_inline_callback()?;
950 arguments.push(inline_callback);
951 } else {
952 arguments.push(self.parse_expression()?);
953 }
954 } else {
955 return Err(ParseError::EndOfInput(self.current_location()));
956 }
957 }
958 Token::CloseParen => {
959 let end_location = self.current_location();
960 self.advance();
961
962 let location = SourceLocation::new(
963 start_location.start_line,
964 start_location.start_column,
965 end_location.end_line,
966 end_location.end_column
967 );
968
969 return Ok(Expression::CallExpression { callee, arguments, location });
970 }
971 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
972 }
973 }
974
975 Err(ParseError::ExpectedToken("')'".to_string(), self.current_location()))
976 }
977
978 fn parse_inline_callback(&mut self) -> Result<Expression, ParseError> {
979 let start_location = self.current_location();
980 self.advance(); let name = match &self.current_token {
983 Some(token_with_span) => match &token_with_span.token {
984 Token::Identifier(name) => name.clone(),
985 _ => return Err(ParseError::ExpectedToken("callback name".to_string(), self.current_location())),
986 },
987 None => return Err(ParseError::EndOfInput(self.current_location())),
988 };
989 self.advance();
990
991 self.expect(Token::OpenParen)?;
992 let mut params = Vec::new();
993
994 if let Some(token_with_span) = self.current_token {
995 if token_with_span.token == Token::CloseParen {
996 self.advance();
997 } else {
998 if let Some(token_with_span) = self.current_token {
999 match &token_with_span.token {
1000 Token::Identifier(param) => {
1001 params.push(param.clone());
1002 self.advance();
1003 },
1004 _ => return Err(ParseError::ExpectedToken("parameter name".to_string(), self.current_location())),
1005 }
1006 }
1007
1008 while let Some(token_with_span) = self.current_token {
1009 match &token_with_span.token {
1010 Token::Comma => {
1011 self.advance();
1012 match &self.current_token {
1013 Some(token_with_span) => match &token_with_span.token {
1014 Token::Identifier(param) => {
1015 params.push(param.clone());
1016 self.advance();
1017 },
1018 _ => return Err(ParseError::ExpectedToken("parameter name".to_string(), self.current_location())),
1019 },
1020 None => return Err(ParseError::EndOfInput(self.current_location())),
1021 }
1022 },
1023 Token::CloseParen => {
1024 self.advance();
1025 break;
1026 },
1027 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
1028 }
1029 }
1030 }
1031 } else {
1032 return Err(ParseError::EndOfInput(self.current_location()));
1033 }
1034
1035 let body = self.parse_block()?;
1036
1037 let end_location = body.location.clone();
1038
1039 let location = SourceLocation::new(
1040 start_location.start_line,
1041 start_location.start_column,
1042 end_location.end_line,
1043 end_location.end_column
1044 );
1045
1046 Ok(Expression::InlineCallbackExpression {
1047 name,
1048 params,
1049 body,
1050 location,
1051 })
1052 }
1053
1054 fn parse_callback_declaration(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
1055 self.advance();
1056
1057 let name = match &self.current_token {
1058 Some(token_with_span) => match &token_with_span.token {
1059 Token::Identifier(name) => name.clone(),
1060 _ => return Err(ParseError::ExpectedToken("callback name".to_string(), self.current_location())),
1061 },
1062 None => return Err(ParseError::EndOfInput(self.current_location())),
1063 };
1064 self.advance();
1065
1066 self.expect(Token::OpenParen)?;
1067 let mut params = Vec::new();
1068
1069 if let Some(token_with_span) = self.current_token {
1070 if token_with_span.token == Token::CloseParen {
1071 self.advance();
1072 } else {
1073 if let Some(token_with_span) = self.current_token {
1074 match &token_with_span.token {
1075 Token::Identifier(param) => {
1076 params.push(param.clone());
1077 self.advance();
1078 },
1079 _ => return Err(ParseError::ExpectedToken("parameter name".to_string(), self.current_location())),
1080 }
1081 }
1082
1083 while let Some(token_with_span) = self.current_token {
1084 match &token_with_span.token {
1085 Token::Comma => {
1086 self.advance();
1087 match &self.current_token {
1088 Some(token_with_span) => match &token_with_span.token {
1089 Token::Identifier(param) => {
1090 params.push(param.clone());
1091 self.advance();
1092 },
1093 _ => return Err(ParseError::ExpectedToken("parameter name".to_string(), self.current_location())),
1094 },
1095 None => return Err(ParseError::EndOfInput(self.current_location())),
1096 }
1097 },
1098 Token::CloseParen => {
1099 self.advance();
1100 break;
1101 },
1102 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
1103 }
1104 }
1105 }
1106 } else {
1107 return Err(ParseError::EndOfInput(self.current_location()));
1108 }
1109
1110 let body = self.parse_block()?;
1111
1112 let end_location = body.location.clone();
1113
1114 let location = SourceLocation::new(
1115 start_location.start_line,
1116 start_location.start_column,
1117 end_location.end_line,
1118 end_location.end_column
1119 );
1120
1121 Ok(Statement::CallbackDeclaration {
1122 name,
1123 params,
1124 body,
1125 location,
1126 })
1127 }
1128
1129 fn parse_return_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
1130 self.advance();
1131
1132 let value = self.parse_expression()?;
1133
1134 let semicolon_location = self.current_location();
1135 self.expect(Token::Semicolon)?;
1136
1137 let end_location = semicolon_location;
1138
1139 let location = SourceLocation::new(
1140 start_location.start_line,
1141 start_location.start_column,
1142 end_location.end_line,
1143 end_location.end_column
1144 );
1145
1146 Ok(Statement::ReturnStatement { value, location })
1147 }
1148
1149 fn parse_array_literal(&mut self, start_location: SourceLocation) -> Result<Expression, ParseError> {
1150 self.advance();
1151
1152 let mut elements = Vec::new();
1153
1154 if let Some(token_with_span) = self.current_token {
1155 if token_with_span.token == Token::CloseBracket {
1156 let end_location = self.current_location();
1157 self.advance();
1158
1159 let location = SourceLocation::new(
1160 start_location.start_line,
1161 start_location.start_column,
1162 end_location.end_line,
1163 end_location.end_column
1164 );
1165
1166 return Ok(Expression::ArrayExpression { elements, location });
1167 }
1168 }
1169
1170 elements.push(self.parse_expression()?);
1171
1172 while let Some(token_with_span) = self.current_token {
1173 match &token_with_span.token {
1174 Token::Comma => {
1175 self.advance();
1176 elements.push(self.parse_expression()?);
1177 }
1178 Token::CloseBracket => {
1179 let end_location = self.current_location();
1180 self.advance();
1181
1182 let location = SourceLocation::new(
1183 start_location.start_line,
1184 start_location.start_column,
1185 end_location.end_line,
1186 end_location.end_column
1187 );
1188
1189 return Ok(Expression::ArrayExpression { elements, location });
1190 }
1191 _ => return Err(ParseError::ExpectedToken("',' or ']'".to_string(), self.current_location())),
1192 }
1193 }
1194
1195 Err(ParseError::ExpectedToken("']'".to_string(), self.current_location()))
1196 }
1197
1198 fn parse_object_literal(&mut self, start_location: SourceLocation) -> Result<Expression, ParseError> {
1199 self.advance();
1200
1201 let mut properties = Vec::new();
1202
1203 if let Some(token_with_span) = self.current_token {
1204 if token_with_span.token == Token::CloseBrace {
1205 let end_location = self.current_location();
1206 self.advance();
1207
1208 let location = SourceLocation::new(
1209 start_location.start_line,
1210 start_location.start_column,
1211 end_location.end_line,
1212 end_location.end_column
1213 );
1214
1215 return Ok(Expression::ObjectExpression { properties, location });
1216 }
1217 }
1218
1219 let property = self.parse_object_property()?;
1220 properties.push(property);
1221
1222 while let Some(token_with_span) = self.current_token {
1223 match &token_with_span.token {
1224 Token::Comma => {
1225 self.advance();
1226 let property = self.parse_object_property()?;
1227 properties.push(property);
1228 }
1229 Token::CloseBrace => {
1230 let end_location = self.current_location();
1231 self.advance();
1232
1233 let location = SourceLocation::new(
1234 start_location.start_line,
1235 start_location.start_column,
1236 end_location.end_line,
1237 end_location.end_column
1238 );
1239
1240 return Ok(Expression::ObjectExpression { properties, location });
1241 }
1242 _ => return Err(ParseError::ExpectedToken("',' or '}'".to_string(), self.current_location())),
1243 }
1244 }
1245
1246 Err(ParseError::ExpectedToken("'}'".to_string(), self.current_location()))
1247 }
1248
1249 fn parse_object_property(&mut self) -> Result<Property, ParseError> {
1250 let start_location = self.current_location();
1251
1252 let key = match &self.current_token {
1253 Some(token_with_span) => match &token_with_span.token {
1254 Token::Identifier(name) => name.clone(),
1255 Token::StringLiteral(value) => value.clone(),
1256 _ => return Err(ParseError::ExpectedToken("property key".to_string(), self.current_location())),
1257 },
1258 None => return Err(ParseError::EndOfInput(self.current_location())),
1259 };
1260 self.advance();
1261
1262 self.expect(Token::Colon)?;
1263
1264 let value = self.parse_expression()?;
1265
1266 let end_location = get_expr_location!(value);
1267
1268 let location = SourceLocation::new(
1269 start_location.start_line,
1270 start_location.start_column,
1271 end_location.end_line,
1272 end_location.end_column
1273 );
1274
1275 Ok(Property::new(key, value, location))
1276 }
1277
1278 fn parse_member_access(&mut self, mut object: Expression) -> Result<Expression, ParseError> {
1279 loop {
1280 match &self.current_token {
1281 Some(token_with_span) => match &token_with_span.token {
1282 Token::Dot => {
1283 if !self.flags.allow_object_navigation {
1284 return Err(ParseError::FeatureDisabled("Object navigation (dot notation)".to_string(), self.current_location()));
1285 }
1286
1287 self.advance();
1288
1289 match &self.current_token {
1290 Some(token_with_span) => match &token_with_span.token {
1291 Token::Identifier(prop_name) => {
1292 let property = prop_name.clone();
1293 let property_location = self.current_location();
1294 self.advance();
1295
1296 let obj_start_line = get_expr_start_line!(object);
1297 let obj_start_column = get_expr_start_column!(object);
1298
1299 if let Some(token_with_span) = self.current_token {
1300 if token_with_span.token == Token::OpenParen {
1301 self.advance();
1302
1303 let mut arguments = Vec::new();
1304
1305 if let Some(token_with_span) = self.current_token {
1307 if token_with_span.token == Token::CloseParen {
1308 let end_call_location = self.current_location();
1309 self.advance();
1310
1311 let call_location = SourceLocation::new(
1312 obj_start_line,
1313 obj_start_column,
1314 end_call_location.end_line,
1315 end_call_location.end_column
1316 );
1317
1318 object = Expression::MemberCallExpression {
1319 object: Box::new(object),
1320 property: Some(property),
1321 property_expr: None,
1322 computed: false,
1323 arguments,
1324 location: call_location,
1325 };
1326 continue;
1327 }
1328 }
1329
1330 if let Some(token_with_span) = self.current_token {
1332 if token_with_span.token == Token::Cb {
1333 if !self.flags.allow_callbacks {
1334 return Err(ParseError::FeatureDisabled("Inline callback expressions".to_string(), self.current_location()));
1335 }
1336 let inline_callback = self.parse_inline_callback()?;
1337 arguments.push(inline_callback);
1338 } else {
1339 arguments.push(self.parse_expression()?);
1340 }
1341 } else {
1342 return Err(ParseError::EndOfInput(self.current_location()));
1343 }
1344
1345 while let Some(token_with_span) = self.current_token {
1347 match &token_with_span.token {
1348 Token::Comma => {
1349 self.advance();
1350
1351 if let Some(token_with_span) = self.current_token {
1353 if token_with_span.token == Token::Cb {
1354 if !self.flags.allow_callbacks {
1355 return Err(ParseError::FeatureDisabled("Inline callback expressions".to_string(), self.current_location()));
1356 }
1357 let inline_callback = self.parse_inline_callback()?;
1358 arguments.push(inline_callback);
1359 } else {
1360 arguments.push(self.parse_expression()?);
1361 }
1362 } else {
1363 return Err(ParseError::EndOfInput(self.current_location()));
1364 }
1365 }
1366 Token::CloseParen => {
1367 let end_call_location = self.current_location();
1368 self.advance();
1369
1370 let call_location = SourceLocation::new(
1371 obj_start_line,
1372 obj_start_column,
1373 end_call_location.end_line,
1374 end_call_location.end_column
1375 );
1376
1377 object = Expression::MemberCallExpression {
1378 object: Box::new(object),
1379 property: Some(property),
1380 property_expr: None,
1381 computed: false,
1382 arguments,
1383 location: call_location,
1384 };
1385 break;
1386 }
1387 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
1388 }
1389 }
1390 } else {
1391 let member_expr_location = SourceLocation::new(
1393 obj_start_line,
1394 obj_start_column,
1395 property_location.end_line,
1396 property_location.end_column
1397 );
1398
1399 object = Expression::MemberExpression {
1400 object: Box::new(object),
1401 property: Some(property),
1402 property_expr: None,
1403 computed: false,
1404 location: member_expr_location,
1405 };
1406 }
1407 } else {
1408 let member_expr_location = SourceLocation::new(
1410 obj_start_line,
1411 obj_start_column,
1412 property_location.end_line,
1413 property_location.end_column
1414 );
1415
1416 object = Expression::MemberExpression {
1417 object: Box::new(object),
1418 property: Some(property),
1419 property_expr: None,
1420 computed: false,
1421 location: member_expr_location,
1422 };
1423 }
1424 }
1425 _ => return Err(ParseError::ExpectedToken("property name".to_string(), self.current_location())),
1426 },
1427 None => return Err(ParseError::EndOfInput(self.current_location())),
1428 }
1429 },
1430
1431 Token::OpenBracket => {
1432 if !self.flags.allow_object_navigation {
1433 return Err(ParseError::FeatureDisabled("Object navigation (bracket notation)".to_string(), self.current_location()));
1434 }
1435
1436 self.advance();
1437
1438 let property_expr = self.parse_expression()?;
1439
1440 let close_bracket_location = self.current_location();
1441 self.expect(Token::CloseBracket)?;
1442
1443 let obj_start_line = get_expr_start_line!(object);
1444 let obj_start_column = get_expr_start_column!(object);
1445
1446 let member_expr_location = SourceLocation::new(
1447 obj_start_line,
1448 obj_start_column,
1449 close_bracket_location.end_line,
1450 close_bracket_location.end_column
1451 );
1452
1453 if let Some(token_with_span) = self.current_token {
1454 if token_with_span.token == Token::OpenParen {
1455 self.advance();
1456
1457 let mut arguments = Vec::new();
1458
1459 if let Some(token_with_span) = self.current_token {
1461 if token_with_span.token == Token::CloseParen {
1462 let end_call_location = self.current_location();
1463 self.advance();
1464
1465 let call_location = SourceLocation::new(
1466 obj_start_line,
1467 obj_start_column,
1468 end_call_location.end_line,
1469 end_call_location.end_column
1470 );
1471
1472 object = Expression::MemberCallExpression {
1473 object: Box::new(object),
1474 property: None,
1475 property_expr: Some(Box::new(property_expr)),
1476 computed: true,
1477 arguments,
1478 location: call_location,
1479 };
1480 continue;
1481 }
1482 }
1483
1484 if let Some(token_with_span) = self.current_token {
1486 if token_with_span.token == Token::Cb {
1487 if !self.flags.allow_callbacks {
1488 return Err(ParseError::FeatureDisabled("Inline callback expressions".to_string(), self.current_location()));
1489 }
1490 let inline_callback = self.parse_inline_callback()?;
1491 arguments.push(inline_callback);
1492 } else {
1493 arguments.push(self.parse_expression()?);
1494 }
1495 } else {
1496 return Err(ParseError::EndOfInput(self.current_location()));
1497 }
1498
1499 while let Some(token_with_span) = self.current_token {
1501 match &token_with_span.token {
1502 Token::Comma => {
1503 self.advance();
1504
1505 if let Some(token_with_span) = self.current_token {
1507 if token_with_span.token == Token::Cb {
1508 if !self.flags.allow_callbacks {
1509 return Err(ParseError::FeatureDisabled("Inline callback expressions".to_string(), self.current_location()));
1510 }
1511 let inline_callback = self.parse_inline_callback()?;
1512 arguments.push(inline_callback);
1513 } else {
1514 arguments.push(self.parse_expression()?);
1515 }
1516 } else {
1517 return Err(ParseError::EndOfInput(self.current_location()));
1518 }
1519 }
1520 Token::CloseParen => {
1521 let end_call_location = self.current_location();
1522 self.advance();
1523
1524 let call_location = SourceLocation::new(
1525 obj_start_line,
1526 obj_start_column,
1527 end_call_location.end_line,
1528 end_call_location.end_column
1529 );
1530
1531 object = Expression::MemberCallExpression {
1532 object: Box::new(object),
1533 property: None,
1534 property_expr: Some(Box::new(property_expr)),
1535 computed: true,
1536 arguments,
1537 location: call_location,
1538 };
1539 break;
1540 }
1541 _ => return Err(ParseError::ExpectedToken("',' or ')'".to_string(), self.current_location())),
1542 }
1543 }
1544 } else {
1545 object = Expression::MemberExpression {
1547 object: Box::new(object),
1548 property: None,
1549 property_expr: Some(Box::new(property_expr)),
1550 computed: true,
1551 location: member_expr_location,
1552 };
1553 }
1554 } else {
1555 object = Expression::MemberExpression {
1557 object: Box::new(object),
1558 property: None,
1559 property_expr: Some(Box::new(property_expr)),
1560 computed: true,
1561 location: member_expr_location,
1562 };
1563 }
1564 },
1565 _ => break,
1566 },
1567 None => break,
1568 }
1569 }
1570 Ok(object)
1571 }
1572
1573 fn parse_loop_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
1574 self.advance();
1575
1576 let variable = match &self.current_token {
1577 Some(token_with_span) => match &token_with_span.token {
1578 Token::Identifier(name) => name.clone(),
1579 _ => return Err(ParseError::ExpectedToken("identifier".to_string(), self.current_location())),
1580 },
1581 None => return Err(ParseError::EndOfInput(self.current_location())),
1582 };
1583 self.advance();
1584
1585 match &self.current_token {
1586 Some(token_with_span) => {
1587 if token_with_span.token != Token::In {
1588 return Err(ParseError::ExpectedToken("'in'".to_string(), self.current_location()));
1589 }
1590 self.advance();
1591 },
1592 None => return Err(ParseError::EndOfInput(self.current_location())),
1593 }
1594
1595 let iterable = self.parse_expression()?;
1596
1597 let body = self.parse_block()?;
1598
1599 let end_location = body.location.clone();
1600
1601 let location = SourceLocation::new(
1602 start_location.start_line,
1603 start_location.start_column,
1604 end_location.end_line,
1605 end_location.end_column
1606 );
1607
1608 Ok(Statement::LoopStatement {
1609 variable,
1610 iterable,
1611 body,
1612 location,
1613 })
1614 }
1615
1616 fn parse_end_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
1617 self.advance();
1618
1619 let semicolon_location = self.current_location();
1620 self.expect(Token::Semicolon)?;
1621
1622 let end_location = semicolon_location;
1623
1624 let location = SourceLocation::new(
1625 start_location.start_line,
1626 start_location.start_column,
1627 end_location.end_line,
1628 end_location.end_column
1629 );
1630
1631 Ok(Statement::EndStatement { location })
1632 }
1633
1634 fn parse_continue_statement(&mut self, start_location: SourceLocation) -> Result<Statement, ParseError> {
1635 self.advance();
1636
1637 let semicolon_location = self.current_location();
1638 self.expect(Token::Semicolon)?;
1639
1640 let end_location = semicolon_location;
1641
1642 let location = SourceLocation::new(
1643 start_location.start_line,
1644 start_location.start_column,
1645 end_location.end_line,
1646 end_location.end_column
1647 );
1648
1649 Ok(Statement::ContinueStatement { location })
1650 }
1651}