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