1use crate::ast::*;
4use crate::lexer::Token;
5use xdl_core::{XdlError, XdlResult, XdlValue};
6
7struct Parser<'a> {
9 tokens: &'a [Token],
10 current: usize,
11}
12
13impl<'a> Parser<'a> {
14 fn new(tokens: &'a [Token]) -> Self {
15 Self { tokens, current: 0 }
16 }
17
18 fn peek(&self) -> &Token {
20 self.tokens.get(self.current).unwrap_or(&Token::EOF)
21 }
22
23 fn advance(&mut self) -> &Token {
25 if self.current < self.tokens.len() {
26 let token = &self.tokens[self.current];
27 self.current += 1;
28 token
29 } else {
30 &Token::EOF
31 }
32 }
33
34 fn check(&self, expected: &Token) -> bool {
36 std::mem::discriminant(self.peek()) == std::mem::discriminant(expected)
37 }
38
39 fn consume(&mut self, expected: Token, message: &str) -> XdlResult<()> {
41 if self.check(&expected) {
42 self.advance();
43 Ok(())
44 } else {
45 Err(XdlError::ParseError {
46 message: format!("{}, got {:?}", message, self.peek()),
47 line: 1, column: self.current,
49 })
50 }
51 }
52
53 fn is_at_end(&self) -> bool {
55 matches!(self.peek(), Token::EOF)
56 }
57
58 fn parse_program(&mut self) -> XdlResult<Program> {
60 let mut statements = Vec::new();
61
62 loop {
63 while matches!(self.peek(), Token::Newline) {
65 self.advance();
66 }
67 if self.is_at_end() {
69 break;
70 }
71 statements.push(self.parse_statement()?);
72 }
73
74 Ok(Program {
75 statements,
76 location: Location::unknown(),
77 })
78 }
79
80 fn parse_block_or_statement(&mut self, terminators: &[Token]) -> XdlResult<Vec<Statement>> {
82 if self.check(&Token::Begin) {
84 self.advance(); let mut statements = Vec::new();
86
87 while !self.is_at_end() {
90 while matches!(self.peek(), Token::Newline) {
92 self.advance();
93 }
94
95 if self.check(&Token::End) {
97 self.advance(); break;
99 }
100
101 let is_terminator = terminators.iter().any(|term| {
103 std::mem::discriminant(self.peek()) == std::mem::discriminant(term)
104 });
105 if is_terminator {
106 break;
108 }
109
110 statements.push(self.parse_statement()?);
111 }
112 Ok(statements)
113 } else {
114 let mut statements = Vec::new();
117 while !self.is_at_end() {
118 while matches!(self.peek(), Token::Newline) {
120 self.advance();
121 }
122
123 let is_terminator = terminators.iter().any(|term| {
124 std::mem::discriminant(self.peek()) == std::mem::discriminant(term)
125 });
126 if is_terminator {
127 break;
128 }
129 statements.push(self.parse_statement()?);
130 }
131 Ok(statements)
132 }
133 }
134
135 fn parse_statement(&mut self) -> XdlResult<Statement> {
137 while matches!(self.peek(), Token::Newline) {
139 self.advance();
140 }
141
142 if self.is_at_end() {
144 return Err(XdlError::ParseError {
145 message: "Unexpected end of file".to_string(),
146 line: 0,
147 column: self.current,
148 });
149 }
150
151 match self.peek() {
152 Token::If => self.parse_if_statement(),
153 Token::For => self.parse_for_statement(),
154 Token::Foreach => self.parse_foreach_statement(),
155 Token::While => self.parse_while_statement(),
156 Token::Repeat => self.parse_repeat_statement(),
157 Token::Return => self.parse_return_statement(),
158 Token::Goto => self.parse_goto_statement(),
159 Token::Label(name) => {
160 let label_name = name.clone();
161 self.advance();
162 Ok(Statement::Label {
163 name: label_name,
164 location: Location::unknown(),
165 })
166 }
167 Token::Break => {
168 self.advance();
169 Ok(Statement::Break {
170 location: Location::unknown(),
171 })
172 }
173 Token::Continue => {
174 self.advance();
175 Ok(Statement::Continue {
176 location: Location::unknown(),
177 })
178 }
179 Token::Pro | Token::Procedure => self.parse_procedure_definition(),
180 Token::Function => self.parse_function_definition(),
181 Token::Case => self.parse_case_statement(),
182 Token::Switch => self.parse_switch_statement(),
183 _ => {
184 if let Token::Identifier(name) = self.peek() {
186 let name = name.clone();
187 let start_pos = self.current;
188 self.advance(); if self.check(&Token::Comma)
192 || self.is_at_end()
193 || matches!(self.peek(), Token::EOF | Token::Newline)
194 {
195 return self.parse_procedure_call(name);
196 }
197
198 self.current = start_pos;
200 }
201
202 let expr = self.parse_expression()?;
203
204 if self.check(&Token::Assign) {
206 self.advance(); let value = self.parse_expression()?;
208 Ok(Statement::Assignment {
209 target: expr,
210 value,
211 location: Location::unknown(),
212 })
213 } else {
214 Ok(Statement::Expression {
215 expr,
216 location: Location::unknown(),
217 })
218 }
219 }
220 }
221 }
222
223 fn parse_if_statement(&mut self) -> XdlResult<Statement> {
230 self.consume(Token::If, "Expected 'if'")?;
231 let condition = self.parse_expression()?;
232 self.consume(Token::Then, "Expected 'then' after if condition")?;
233
234 let is_block = self.check(&Token::Begin);
236
237 let is_single_line = !is_block && !matches!(self.peek(), Token::Newline);
241
242 let then_block = if is_block {
243 self.parse_block_or_statement(&[Token::Else, Token::Endif])?
245 } else if is_single_line {
246 let stmt = self.parse_statement()?;
249 vec![stmt]
250 } else {
251 let mut stmts = Vec::new();
254 loop {
255 while matches!(self.peek(), Token::Newline) {
257 self.advance();
258 }
259 if matches!(self.peek(), Token::Else | Token::Endif | Token::EOF) {
260 break;
261 }
262 stmts.push(self.parse_statement()?);
263 }
264 stmts
265 };
266
267 let else_block = if is_single_line {
269 if self.check(&Token::Else) {
270 self.advance(); let stmt = self.parse_statement()?;
273 Some(vec![stmt])
274 } else {
275 None
276 }
277 } else {
278 while matches!(self.peek(), Token::Newline) {
280 self.advance();
281 }
282
283 if self.check(&Token::Else) {
284 self.advance(); if is_block || self.check(&Token::Begin) {
286 Some(self.parse_block_or_statement(&[Token::Endif])?)
288 } else {
289 let mut stmts = Vec::new();
291 loop {
292 while matches!(self.peek(), Token::Newline) {
293 self.advance();
294 }
295 if matches!(self.peek(), Token::Endif | Token::EOF) {
296 break;
297 }
298 stmts.push(self.parse_statement()?);
299 }
300 Some(stmts)
301 }
302 } else {
303 None
304 }
305 };
306
307 if !is_single_line {
309 while matches!(self.peek(), Token::Newline) {
310 self.advance();
311 }
312 }
313
314 if self.check(&Token::Endif) {
316 self.advance(); }
318
319 Ok(Statement::If {
320 condition,
321 then_block,
322 else_block,
323 location: Location::unknown(),
324 })
325 }
326
327 fn parse_for_statement(&mut self) -> XdlResult<Statement> {
329 self.consume(Token::For, "Expected 'for'")?;
330
331 let variable = if let Token::Identifier(name) = self.advance() {
333 name.clone()
334 } else {
335 return Err(XdlError::ParseError {
336 message: "Expected variable name in for loop".to_string(),
337 line: 1,
338 column: self.current,
339 });
340 };
341
342 self.consume(Token::Assign, "Expected '=' after for variable")?;
343 let start = self.parse_expression()?;
344 self.consume(Token::Comma, "Expected ',' after for start value")?;
345 let end = self.parse_expression()?;
346
347 let step = if self.check(&Token::Comma) {
348 self.advance(); Some(self.parse_expression()?)
350 } else {
351 None
352 };
353
354 if matches!(self.peek(), Token::Identifier(s) if s.to_uppercase() == "DO") {
356 self.advance(); }
358
359 let body = if self.check(&Token::Begin) {
361 self.parse_block_or_statement(&[Token::Endfor])?
362 } else {
363 let mut stmts = Vec::new();
365 loop {
366 while matches!(self.peek(), Token::Newline) {
367 self.advance();
368 }
369 if matches!(self.peek(), Token::Endfor | Token::EOF) {
370 break;
371 }
372 stmts.push(self.parse_statement()?);
373 }
374 stmts
375 };
376
377 while matches!(self.peek(), Token::Newline) {
379 self.advance();
380 }
381
382 self.consume(Token::Endfor, "Expected 'endfor' to close for loop")?;
383
384 Ok(Statement::For {
385 variable,
386 start,
387 end,
388 step,
389 body,
390 location: Location::unknown(),
391 })
392 }
393
394 fn parse_procedure_call(&mut self, name: String) -> XdlResult<Statement> {
396 let mut args = Vec::new();
397 let mut keywords = Vec::new();
398
399 while self.check(&Token::Comma) {
401 self.advance(); if matches!(self.peek(), Token::Newline | Token::EOF) {
405 break;
406 }
407
408 if matches!(self.peek(), Token::Divide) {
410 let next_pos = self.current + 1;
411 if next_pos < self.tokens.len() {
412 if let Token::Identifier(kw_name) = &self.tokens[next_pos] {
413 let kw_name = kw_name.clone();
414 self.advance(); self.advance(); keywords.push(Keyword {
417 name: kw_name,
418 value: Some(Expression::Literal {
419 value: XdlValue::Long(1),
420 location: Location::unknown(),
421 }),
422 location: Location::unknown(),
423 });
424 continue;
425 }
426 }
427 }
428
429 if let Token::Identifier(kw_name) = self.peek() {
432 let kw_name = kw_name.clone();
433 let next_pos = self.current + 1;
434
435 if next_pos < self.tokens.len() && matches!(self.tokens[next_pos], Token::Assign) {
436 self.advance(); self.advance(); let value = self.parse_expression()?;
440 keywords.push(Keyword {
441 name: kw_name,
442 value: Some(value),
443 location: Location::unknown(),
444 });
445 continue;
446 }
447 }
448
449 args.push(self.parse_expression()?);
451 }
452
453 if name.to_uppercase() == "OBJ_DESTROY" {
455 return Ok(Statement::ObjectDestroy {
456 objects: args,
457 location: Location::unknown(),
458 });
459 }
460
461 Ok(Statement::ProcedureCall {
462 name,
463 args,
464 keywords,
465 location: Location::unknown(),
466 })
467 }
468
469 fn parse_foreach_statement(&mut self) -> XdlResult<Statement> {
471 self.consume(Token::Foreach, "Expected 'foreach'")?;
472
473 let variable = if let Token::Identifier(name) = self.advance() {
475 name.clone()
476 } else {
477 return Err(XdlError::ParseError {
478 message: "Expected variable name in foreach loop".to_string(),
479 line: 1,
480 column: self.current,
481 });
482 };
483
484 self.consume(Token::Comma, "Expected ',' after foreach variable")?;
485 let iterable = self.parse_expression()?;
486
487 let index_var = if self.check(&Token::Comma) {
489 self.advance(); if let Token::Identifier(name) = self.advance() {
491 Some(name.clone())
492 } else {
493 return Err(XdlError::ParseError {
494 message: "Expected index variable name".to_string(),
495 line: 1,
496 column: self.current,
497 });
498 }
499 } else {
500 None
501 };
502
503 if matches!(self.peek(), Token::Identifier(s) if s.to_uppercase() == "DO") {
505 self.advance(); }
507
508 let body = self.parse_block_or_statement(&[Token::Endfor])?;
510
511 self.consume(
512 Token::Endfor,
513 "Expected 'endfor' or 'endforeach' to close foreach loop",
514 )?;
515
516 Ok(Statement::Foreach {
517 variable,
518 iterable,
519 index_var,
520 body,
521 location: Location::unknown(),
522 })
523 }
524
525 fn parse_while_statement(&mut self) -> XdlResult<Statement> {
527 self.consume(Token::While, "Expected 'while'")?;
528 let condition = self.parse_expression()?;
529
530 if matches!(self.peek(), Token::Identifier(s) if s.to_uppercase() == "DO") {
532 self.advance(); }
534
535 let body = self.parse_block_or_statement(&[Token::Endwhile])?;
537
538 self.consume(Token::Endwhile, "Expected 'endwhile' to close while loop")?;
539
540 Ok(Statement::While {
541 condition,
542 body,
543 location: Location::unknown(),
544 })
545 }
546
547 fn parse_repeat_statement(&mut self) -> XdlResult<Statement> {
549 self.consume(Token::Repeat, "Expected 'repeat'")?;
550
551 let body = self.parse_block_or_statement(&[Token::Until])?;
553
554 self.consume(Token::Until, "Expected 'until' to close repeat loop")?;
555 let condition = self.parse_expression()?;
556
557 Ok(Statement::Repeat {
558 body,
559 condition,
560 location: Location::unknown(),
561 })
562 }
563
564 fn parse_return_statement(&mut self) -> XdlResult<Statement> {
566 self.consume(Token::Return, "Expected 'return'")?;
567
568 let value = if matches!(self.peek(), Token::Newline | Token::EOF) {
570 None
571 } else {
572 if self.check(&Token::Comma) {
574 self.advance();
575 }
576 if matches!(self.peek(), Token::Newline | Token::EOF) {
578 None
579 } else {
580 Some(self.parse_expression()?)
581 }
582 };
583
584 Ok(Statement::Return {
585 value,
586 location: Location::unknown(),
587 })
588 }
589
590 fn parse_goto_statement(&mut self) -> XdlResult<Statement> {
593 self.consume(Token::Goto, "Expected 'goto'")?;
594
595 if self.check(&Token::Comma) {
597 self.advance();
598 }
599
600 let label = if let Token::Identifier(name) = self.peek() {
602 name.clone()
603 } else {
604 return Err(XdlError::ParseError {
605 message: "Expected label name after GOTO".to_string(),
606 line: 1,
607 column: self.current,
608 });
609 };
610
611 self.advance(); Ok(Statement::Goto {
614 label,
615 location: Location::unknown(),
616 })
617 }
618
619 fn parse_case_statement(&mut self) -> XdlResult<Statement> {
626 self.consume(Token::Case, "Expected 'case'")?;
627 let expr = self.parse_expression()?;
628 self.consume(Token::Of, "Expected 'of' after case expression")?;
629
630 while matches!(self.peek(), Token::Newline) {
632 self.advance();
633 }
634
635 let mut branches = Vec::new();
636 let mut else_block = None;
637
638 while !matches!(self.peek(), Token::Endcase | Token::EOF) {
640 while matches!(self.peek(), Token::Newline) {
642 self.advance();
643 }
644
645 if matches!(self.peek(), Token::Endcase) {
646 break;
647 }
648
649 if matches!(self.peek(), Token::Else) {
651 self.advance(); self.consume(Token::Colon, "Expected ':' after ELSE")?;
653
654 let body = if matches!(self.peek(), Token::Begin) {
656 self.parse_block_or_statement(&[Token::Endcase])?
657 } else {
658 vec![self.parse_statement()?]
659 };
660 else_block = Some(body);
661
662 while matches!(self.peek(), Token::Newline) {
664 self.advance();
665 }
666 break;
667 }
668
669 let mut values = Vec::new();
671 loop {
672 values.push(self.parse_expression()?);
673 if matches!(self.peek(), Token::Comma) {
674 self.advance(); } else {
676 break;
677 }
678 }
679
680 self.consume(Token::Colon, "Expected ':' after case value")?;
681
682 let body = if matches!(self.peek(), Token::Begin) {
684 self.parse_block_or_statement(&[Token::Endcase])?
685 } else {
686 vec![self.parse_statement()?]
687 };
688
689 branches.push(CaseBranch { values, body, location: Location::unknown() });
690
691 while matches!(self.peek(), Token::Newline) {
693 self.advance();
694 }
695 }
696
697 self.consume(Token::Endcase, "Expected 'endcase' to close case statement")?;
698
699 Ok(Statement::Case {
700 expr,
701 branches,
702 else_block,
703 location: Location::unknown(),
704 })
705 }
706
707 fn parse_switch_statement(&mut self) -> XdlResult<Statement> {
709 self.consume(Token::Switch, "Expected 'switch'")?;
710 let expr = self.parse_expression()?;
711 self.consume(Token::Of, "Expected 'of' after switch expression")?;
712
713 while matches!(self.peek(), Token::Newline) {
715 self.advance();
716 }
717
718 let mut branches = Vec::new();
719 let mut else_block = None;
720
721 while !matches!(self.peek(), Token::Endswitch | Token::EOF) {
723 while matches!(self.peek(), Token::Newline) {
724 self.advance();
725 }
726
727 if matches!(self.peek(), Token::Endswitch) {
728 break;
729 }
730
731 if matches!(self.peek(), Token::Else) {
732 self.advance();
733 self.consume(Token::Colon, "Expected ':' after ELSE")?;
734 let body = if matches!(self.peek(), Token::Begin) {
735 self.parse_block_or_statement(&[Token::Endswitch])?
736 } else {
737 vec![self.parse_statement()?]
738 };
739 else_block = Some(body);
740 while matches!(self.peek(), Token::Newline) {
741 self.advance();
742 }
743 break;
744 }
745
746 let mut values = Vec::new();
747 loop {
748 values.push(self.parse_expression()?);
749 if matches!(self.peek(), Token::Comma) {
750 self.advance();
751 } else {
752 break;
753 }
754 }
755
756 self.consume(Token::Colon, "Expected ':' after case value")?;
757
758 let body = if matches!(self.peek(), Token::Begin) {
759 self.parse_block_or_statement(&[Token::Endswitch])?
760 } else {
761 vec![self.parse_statement()?]
762 };
763
764 branches.push(CaseBranch { values, body, location: Location::unknown() });
765
766 while matches!(self.peek(), Token::Newline) {
767 self.advance();
768 }
769 }
770
771 self.consume(Token::Endswitch, "Expected 'endswitch' to close switch statement")?;
772
773 Ok(Statement::Switch {
774 expr,
775 branches,
776 else_block,
777 location: Location::unknown(),
778 })
779 }
780
781 fn parse_procedure_definition(&mut self) -> XdlResult<Statement> {
783 self.advance(); let name = if let Token::Identifier(name) = self.advance() {
786 name.clone()
787 } else {
788 return Err(XdlError::ParseError {
789 message: "Expected procedure name".to_string(),
790 line: 1,
791 column: self.current,
792 });
793 };
794
795 if name.ends_with("__define") {
797 return self.parse_class_definition_body(name);
798 }
799
800 if name.contains("::") {
802 return self.parse_method_definition_body(name, false); }
804
805 let mut params = Vec::new();
807 let mut keywords = Vec::new();
808
809 if self.check(&Token::Comma) {
811 self.advance(); loop {
815 if matches!(self.peek(), Token::Newline | Token::EOF) {
817 break;
818 }
819
820 let param_name = if let Token::Identifier(name) = self.peek() {
822 name.clone()
823 } else {
824 break; };
826
827 self.advance(); if self.check(&Token::Assign) {
831 self.advance(); keywords.push(KeywordDecl {
836 name: param_name,
837 by_reference: false,
838 location: Location::unknown(),
839 });
840 } else {
841 params.push(Parameter {
843 name: param_name,
844 by_reference: false,
845 optional: false,
846 location: Location::unknown(),
847 });
848 }
849
850 if !self.check(&Token::Comma) {
852 break;
853 }
854 self.advance(); }
856 }
857
858 while matches!(self.peek(), Token::Comma | Token::Newline) {
860 self.advance();
861 }
862
863 let mut body = Vec::new();
865 loop {
867 while matches!(self.peek(), Token::Newline) {
869 self.advance();
870 }
871 if matches!(self.peek(), Token::Endpro | Token::End | Token::EOF) {
872 break;
873 }
874 body.push(self.parse_statement()?);
875 }
876
877 if !matches!(self.peek(), Token::Endpro | Token::End) {
879 return Err(XdlError::ParseError {
880 message: "Expected 'END' or 'ENDPRO' to close procedure".to_string(),
881 line: 1,
882 column: self.current,
883 });
884 }
885 self.advance(); Ok(Statement::ProcedureDef {
888 name,
889 params,
890 keywords,
891 body,
892 location: Location::unknown(),
893 })
894 }
895
896 fn parse_function_definition(&mut self) -> XdlResult<Statement> {
898 self.consume(Token::Function, "Expected 'function'")?;
899
900 let name = if let Token::Identifier(name) = self.advance() {
901 name.clone()
902 } else {
903 return Err(XdlError::ParseError {
904 message: "Expected function name".to_string(),
905 line: 1,
906 column: self.current,
907 });
908 };
909
910 if name.contains("::") {
912 return self.parse_method_definition_body(name, true); }
914
915 let mut params = Vec::new();
917 let mut keywords = Vec::new();
918
919 let has_paren = self.check(&Token::LeftParen);
921 if has_paren {
922 self.advance(); }
924
925 if has_paren || self.check(&Token::Comma) {
927 if self.check(&Token::Comma) {
928 self.advance(); }
930
931 loop {
933 if has_paren && self.check(&Token::RightParen) {
935 self.advance(); break;
937 }
938 if !has_paren && matches!(self.peek(), Token::Newline | Token::EOF) {
939 break;
940 }
941
942 let param_name = if let Token::Identifier(name) = self.peek() {
944 name.clone()
945 } else {
946 break; };
948
949 self.advance(); if self.check(&Token::Assign) {
953 self.advance(); keywords.push(KeywordDecl {
955 name: param_name,
956 by_reference: false,
957 location: Location::unknown(),
958 });
959 } else {
960 params.push(Parameter {
962 name: param_name,
963 by_reference: false,
964 optional: false,
965 location: Location::unknown(),
966 });
967 }
968
969 if !self.check(&Token::Comma) {
971 if has_paren && self.check(&Token::RightParen) {
972 self.advance(); }
974 break;
975 }
976 self.advance(); }
978 }
979
980 while matches!(self.peek(), Token::Comma | Token::Newline) {
982 self.advance();
983 }
984
985 let mut body = Vec::new();
987 loop {
989 while matches!(self.peek(), Token::Newline) {
991 self.advance();
992 }
993 if matches!(self.peek(), Token::Endfunction | Token::End | Token::EOF) {
994 break;
995 }
996 body.push(self.parse_statement()?);
997 }
998
999 if !matches!(self.peek(), Token::Endfunction | Token::End) {
1001 return Err(XdlError::ParseError {
1002 message: "Expected 'END' or 'ENDFUNCTION' to close function".to_string(),
1003 line: 1,
1004 column: self.current,
1005 });
1006 }
1007 self.advance(); Ok(Statement::FunctionDef {
1010 name,
1011 params,
1012 keywords,
1013 body,
1014 location: Location::unknown(),
1015 })
1016 }
1017
1018 fn parse_class_definition_body(&mut self, full_name: String) -> XdlResult<Statement> {
1020 let class_name = full_name.trim_end_matches("__define").to_string();
1022
1023 while matches!(self.peek(), Token::Comma) {
1025 self.advance();
1026 if matches!(self.peek(), Token::Identifier(_)) {
1027 self.advance(); }
1029 }
1030
1031 while matches!(self.peek(), Token::Comma | Token::Newline) {
1033 self.advance();
1034 }
1035
1036 let mut body = Vec::new();
1038 while !matches!(self.peek(), Token::Endpro | Token::EOF) {
1039 body.push(self.parse_statement()?);
1040 }
1041
1042 self.consume(Token::Endpro, "Expected 'endpro' to close class definition")?;
1043
1044 Ok(Statement::ClassDefinition {
1045 name: class_name,
1046 body,
1047 location: Location::unknown(),
1048 })
1049 }
1050
1051 fn parse_method_definition_body(
1053 &mut self,
1054 full_name: String,
1055 is_function: bool,
1056 ) -> XdlResult<Statement> {
1057 let parts: Vec<&str> = full_name.split("::").collect();
1059 if parts.len() != 2 {
1060 return Err(XdlError::ParseError {
1061 message: format!(
1062 "Invalid method name format '{}'. Expected ClassName::MethodName",
1063 full_name
1064 ),
1065 line: 1,
1066 column: self.current,
1067 });
1068 }
1069
1070 let class_name = parts[0].to_string();
1071 let method_name = parts[1].to_string();
1072
1073 let mut params = Vec::new();
1075 let mut keywords = Vec::new();
1076
1077 if self.check(&Token::Comma) {
1078 self.advance(); loop {
1081 if matches!(self.peek(), Token::Newline | Token::EOF) {
1082 break;
1083 }
1084
1085 let param_name = if let Token::Identifier(name) = self.peek() {
1086 name.clone()
1087 } else {
1088 break;
1089 };
1090
1091 self.advance();
1092
1093 if self.check(&Token::Assign) {
1094 self.advance(); keywords.push(KeywordDecl {
1096 name: param_name,
1097 by_reference: false,
1098 location: Location::unknown(),
1099 });
1100 } else {
1101 params.push(Parameter {
1102 name: param_name,
1103 by_reference: false,
1104 optional: false,
1105 location: Location::unknown(),
1106 });
1107 }
1108
1109 if !self.check(&Token::Comma) {
1110 break;
1111 }
1112 self.advance();
1113 }
1114 }
1115
1116 while matches!(self.peek(), Token::Comma | Token::Newline) {
1118 self.advance();
1119 }
1120
1121 let mut body = Vec::new();
1123
1124 while !self.is_at_end() {
1125 if is_function && self.check(&Token::Endfunction) {
1127 break;
1128 }
1129 if !is_function && self.check(&Token::Endpro) {
1130 break;
1131 }
1132
1133 body.push(self.parse_statement()?);
1134 }
1135
1136 if is_function {
1138 self.consume(
1139 Token::Endfunction,
1140 "Expected 'endfunction' to close method definition",
1141 )?;
1142 } else {
1143 self.consume(
1144 Token::Endpro,
1145 "Expected 'endpro' to close method definition",
1146 )?;
1147 }
1148
1149 Ok(Statement::MethodDefinition {
1150 class_name,
1151 method_name,
1152 is_function,
1153 params,
1154 keywords,
1155 body,
1156 location: Location::unknown(),
1157 })
1158 }
1159
1160 fn parse_expression(&mut self) -> XdlResult<Expression> {
1162 self.parse_ternary()
1163 }
1164
1165 fn parse_ternary(&mut self) -> XdlResult<Expression> {
1167 let condition = self.parse_logical_or()?;
1168
1169 if self.check(&Token::QuestionMark) {
1171 self.advance(); let if_true = self.parse_expression()?;
1173 self.consume(Token::Colon, "Expected ':' in ternary expression")?;
1174 let if_false = self.parse_expression()?;
1175
1176 Ok(Expression::Ternary {
1177 condition: Box::new(condition),
1178 if_true: Box::new(if_true),
1179 if_false: Box::new(if_false),
1180 location: Location::unknown(),
1181 })
1182 } else {
1183 Ok(condition)
1184 }
1185 }
1186
1187 fn parse_logical_or(&mut self) -> XdlResult<Expression> {
1189 let mut expr = self.parse_logical_and()?;
1190
1191 while self.check(&Token::Or) {
1192 self.advance();
1193 let right = self.parse_logical_and()?;
1194 expr = Expression::Binary {
1195 op: BinaryOp::Or,
1196 left: Box::new(expr),
1197 right: Box::new(right),
1198 location: Location::unknown(),
1199 };
1200 }
1201
1202 Ok(expr)
1203 }
1204
1205 fn parse_logical_and(&mut self) -> XdlResult<Expression> {
1207 let mut expr = self.parse_equality()?;
1208
1209 while self.check(&Token::And) {
1210 self.advance();
1211 let right = self.parse_equality()?;
1212 expr = Expression::Binary {
1213 op: BinaryOp::And,
1214 left: Box::new(expr),
1215 right: Box::new(right),
1216 location: Location::unknown(),
1217 };
1218 }
1219
1220 Ok(expr)
1221 }
1222
1223 fn parse_equality(&mut self) -> XdlResult<Expression> {
1225 let mut expr = self.parse_comparison()?;
1226
1227 loop {
1228 let op = match self.peek() {
1229 Token::Equal => BinaryOp::Equal,
1230 Token::NotEqual => BinaryOp::NotEqual,
1231 _ => break,
1232 };
1233
1234 self.advance();
1235 let right = self.parse_comparison()?;
1236 expr = Expression::Binary {
1237 op,
1238 left: Box::new(expr),
1239 right: Box::new(right),
1240 location: Location::unknown(),
1241 };
1242 }
1243
1244 Ok(expr)
1245 }
1246
1247 fn parse_comparison(&mut self) -> XdlResult<Expression> {
1249 let mut expr = self.parse_addition()?;
1250
1251 loop {
1252 let op = match self.peek() {
1253 Token::Less => BinaryOp::Less,
1254 Token::Greater => BinaryOp::Greater,
1255 Token::LessEqual => BinaryOp::LessEqual,
1256 Token::GreaterEqual => BinaryOp::GreaterEqual,
1257 _ => break,
1258 };
1259
1260 self.advance();
1261 let right = self.parse_addition()?;
1262 expr = Expression::Binary {
1263 op,
1264 left: Box::new(expr),
1265 right: Box::new(right),
1266 location: Location::unknown(),
1267 };
1268 }
1269
1270 Ok(expr)
1271 }
1272
1273 fn parse_addition(&mut self) -> XdlResult<Expression> {
1275 let mut expr = self.parse_multiplication()?;
1276
1277 loop {
1278 let op = match self.peek() {
1279 Token::Plus => BinaryOp::Add,
1280 Token::Minus => BinaryOp::Subtract,
1281 _ => break,
1282 };
1283
1284 self.advance();
1285 let right = self.parse_multiplication()?;
1286 expr = Expression::Binary {
1287 op,
1288 left: Box::new(expr),
1289 right: Box::new(right),
1290 location: Location::unknown(),
1291 };
1292 }
1293
1294 Ok(expr)
1295 }
1296
1297 fn parse_multiplication(&mut self) -> XdlResult<Expression> {
1299 let mut expr = self.parse_power()?;
1300
1301 loop {
1302 let op = match self.peek() {
1303 Token::Multiply => BinaryOp::Multiply,
1304 Token::Divide => BinaryOp::Divide,
1305 Token::Modulo => BinaryOp::Modulo,
1306 Token::MatrixMultiply => BinaryOp::MatrixMultiply,
1307 _ => break,
1308 };
1309
1310 self.advance();
1311 let right = self.parse_power()?;
1312 expr = Expression::Binary {
1313 op,
1314 left: Box::new(expr),
1315 right: Box::new(right),
1316 location: Location::unknown(),
1317 };
1318 }
1319
1320 Ok(expr)
1321 }
1322
1323 fn parse_power(&mut self) -> XdlResult<Expression> {
1325 let mut expr = self.parse_unary()?;
1326
1327 if self.check(&Token::Power) {
1328 self.advance();
1329 let right = self.parse_power()?; expr = Expression::Binary {
1331 op: BinaryOp::Power,
1332 left: Box::new(expr),
1333 right: Box::new(right),
1334 location: Location::unknown(),
1335 };
1336 }
1337
1338 Ok(expr)
1339 }
1340
1341 fn parse_unary(&mut self) -> XdlResult<Expression> {
1343 match self.peek() {
1344 Token::Not => {
1345 self.advance();
1346 let expr = self.parse_unary()?;
1347 Ok(Expression::Unary {
1348 op: UnaryOp::Not,
1349 expr: Box::new(expr),
1350 location: Location::unknown(),
1351 })
1352 }
1353 Token::Minus => {
1354 self.advance();
1355 let expr = self.parse_unary()?;
1356 Ok(Expression::Unary {
1357 op: UnaryOp::Minus,
1358 expr: Box::new(expr),
1359 location: Location::unknown(),
1360 })
1361 }
1362 Token::Plus => {
1363 self.advance();
1364 let expr = self.parse_unary()?;
1365 Ok(Expression::Unary {
1366 op: UnaryOp::Plus,
1367 expr: Box::new(expr),
1368 location: Location::unknown(),
1369 })
1370 }
1371 _ => self.parse_postfix(),
1372 }
1373 }
1374
1375 fn parse_postfix(&mut self) -> XdlResult<Expression> {
1377 let mut expr = self.parse_primary()?;
1378
1379 loop {
1381 if self.check(&Token::LeftBracket) {
1382 self.advance(); let indices = self.parse_array_indices()?;
1385 self.consume(Token::RightBracket, "Expected ']' after array indices")?;
1386
1387 expr = Expression::ArrayRef {
1388 array: Box::new(expr),
1389 indices,
1390 location: Location::unknown(),
1391 };
1392 } else if self.check(&Token::Arrow) {
1393 self.advance(); let method = match self.advance() {
1398 Token::Identifier(name) => name.clone(),
1399 _ => {
1400 return Err(XdlError::ParseError {
1401 message: "Expected method name after '->'".to_string(),
1402 line: 1, column: self.current,
1404 });
1405 }
1406 };
1407
1408 if self.check(&Token::LeftParen) {
1410 self.advance(); let mut args = Vec::new();
1412
1413 if !self.check(&Token::RightParen) {
1414 loop {
1415 args.push(self.parse_expression()?);
1416 if self.check(&Token::Comma) {
1417 self.advance();
1418 } else {
1419 break;
1420 }
1421 }
1422 }
1423
1424 self.consume(Token::RightParen, "Expected ')' after method arguments")?;
1425
1426 expr = Expression::MethodCall {
1427 object: Box::new(expr),
1428 method,
1429 args,
1430 keywords: Vec::new(), location: Location::unknown(),
1432 };
1433 } else {
1434 expr = Expression::MethodCall {
1436 object: Box::new(expr),
1437 method,
1438 args: vec![],
1439 keywords: vec![],
1440 location: Location::unknown(),
1441 };
1442 }
1443 } else if self.check(&Token::Dot) {
1444 self.advance(); let field = match self.advance() {
1449 Token::Identifier(name) => name.clone(),
1450 _ => {
1451 return Err(XdlError::ParseError {
1452 message: "Expected field name after '.'".to_string(),
1453 line: 1, column: self.current,
1455 });
1456 }
1457 };
1458
1459 expr = Expression::StructRef {
1460 object: Box::new(expr),
1461 field,
1462 location: Location::unknown(),
1463 };
1464 } else {
1465 break;
1466 }
1467 }
1468
1469 Ok(expr)
1470 }
1471
1472 fn parse_array_indices(&mut self) -> XdlResult<Vec<ArrayIndex>> {
1474 let mut indices = Vec::new();
1475
1476 loop {
1477 if self.check(&Token::Multiply) {
1479 self.advance(); indices.push(ArrayIndex::All);
1481 } else if self.check(&Token::Colon) {
1482 self.advance(); let end = if self.check(&Token::Multiply) {
1487 self.advance(); None } else if self.check(&Token::RightBracket)
1490 || self.check(&Token::Comma)
1491 || self.check(&Token::Colon)
1492 {
1493 None
1494 } else {
1495 Some(self.parse_expression()?)
1496 };
1497
1498 let step = if self.check(&Token::Colon) {
1500 self.advance();
1501 if self.check(&Token::RightBracket) || self.check(&Token::Comma) {
1502 None
1503 } else {
1504 Some(self.parse_expression()?)
1505 }
1506 } else {
1507 None
1508 };
1509
1510 indices.push(ArrayIndex::Range {
1511 start: None,
1512 end: end.map(Box::new),
1513 step: step.map(Box::new),
1514 });
1515 } else {
1516 let first_expr = self.parse_expression()?;
1518
1519 if self.check(&Token::Colon) {
1521 self.advance(); let end = if self.check(&Token::Multiply) {
1525 self.advance(); None } else if self.check(&Token::RightBracket)
1528 || self.check(&Token::Comma)
1529 || self.check(&Token::Colon)
1530 {
1531 None
1532 } else {
1533 Some(self.parse_expression()?)
1534 };
1535
1536 let step = if self.check(&Token::Colon) {
1538 self.advance();
1539 if self.check(&Token::RightBracket) || self.check(&Token::Comma) {
1540 None
1541 } else {
1542 Some(self.parse_expression()?)
1543 }
1544 } else {
1545 None
1546 };
1547
1548 indices.push(ArrayIndex::Range {
1549 start: Some(Box::new(first_expr)),
1550 end: end.map(Box::new),
1551 step: step.map(Box::new),
1552 });
1553 } else {
1554 indices.push(ArrayIndex::Single(Box::new(first_expr)));
1556 }
1557 }
1558
1559 if self.check(&Token::Comma) {
1561 self.advance();
1562 } else {
1563 break;
1564 }
1565 }
1566
1567 Ok(indices)
1568 }
1569
1570 fn parse_primary(&mut self) -> XdlResult<Expression> {
1572 match self.advance() {
1573 Token::Integer(value) => Ok(Expression::Literal {
1574 value: XdlValue::Long(*value as i32),
1575 location: Location::unknown(),
1576 }),
1577 Token::Float(value) => Ok(Expression::Literal {
1578 value: XdlValue::Double(*value),
1579 location: Location::unknown(),
1580 }),
1581 Token::String(value) => Ok(Expression::Literal {
1582 value: XdlValue::String(value.clone()),
1583 location: Location::unknown(),
1584 }),
1585 Token::Identifier(name) => {
1586 let name = name.clone();
1587 if self.check(&Token::LeftParen) {
1589 self.advance(); let mut args = Vec::new();
1591 let mut keywords = Vec::new();
1592
1593 if !self.check(&Token::RightParen) {
1594 loop {
1595 if self.check(&Token::Divide) {
1597 self.advance(); if let Token::Identifier(kw_name) = self.peek() {
1599 let kw_name = kw_name.clone();
1600 self.advance(); keywords.push(Keyword {
1602 name: kw_name,
1603 value: Some(Expression::Literal {
1604 value: XdlValue::Long(1),
1605 location: Location::unknown(),
1606 }),
1607 location: Location::unknown(),
1608 });
1609 if self.check(&Token::Comma) {
1610 self.advance();
1611 continue;
1612 } else {
1613 break;
1614 }
1615 }
1616 }
1617
1618 if let Token::Identifier(kw_name) = self.peek() {
1620 let kw_name_clone = kw_name.clone();
1621 let next_pos = self.current + 1;
1622
1623 if next_pos < self.tokens.len()
1624 && matches!(self.tokens[next_pos], Token::Assign)
1625 {
1626 self.advance(); self.advance(); let value = self.parse_expression()?;
1630 keywords.push(Keyword {
1631 name: kw_name_clone,
1632 value: Some(value),
1633 location: Location::unknown(),
1634 });
1635 if self.check(&Token::Comma) {
1636 self.advance();
1637 continue;
1638 } else {
1639 break;
1640 }
1641 }
1642 }
1643
1644 args.push(self.parse_expression()?);
1646 if self.check(&Token::Comma) {
1647 self.advance();
1648 } else {
1649 break;
1650 }
1651 }
1652 }
1653
1654 self.consume(Token::RightParen, "Expected ')' after function arguments")?;
1655
1656 if name.to_uppercase() == "OBJ_NEW" {
1658 let class_name = if !args.is_empty() {
1660 match &args[0] {
1661 Expression::Literal {
1662 value: XdlValue::String(s),
1663 ..
1664 } => s.clone(),
1665 _ => {
1666 return Err(XdlError::ParseError {
1668 message: "OBJ_NEW requires a string literal class name as first argument".to_string(),
1669 line: 1,
1670 column: self.current,
1671 });
1672 }
1673 }
1674 } else {
1675 String::new()
1677 };
1678
1679 let constructor_args = if args.len() > 1 {
1681 args[1..].to_vec()
1682 } else {
1683 Vec::new()
1684 };
1685
1686 Ok(Expression::ObjectNew {
1687 class_name,
1688 args: constructor_args,
1689 keywords: keywords.clone(), location: Location::unknown(),
1691 })
1692 } else {
1693 Ok(Expression::FunctionCall {
1694 name,
1695 args,
1696 keywords, location: Location::unknown(),
1698 })
1699 }
1700 } else {
1701 Ok(Expression::Variable {
1702 name,
1703 location: Location::unknown(),
1704 })
1705 }
1706 }
1707 Token::SystemVariable(name) => {
1708 let name = name.clone();
1709 Ok(Expression::SystemVariable {
1710 name,
1711 location: Location::unknown(),
1712 })
1713 }
1714 Token::LeftParen => {
1715 let expr = self.parse_expression()?;
1716 self.consume(Token::RightParen, "Expected ')' after expression")?;
1717 Ok(expr)
1718 }
1719 Token::LeftBracket => {
1720 let mut elements = Vec::new();
1722
1723 if !self.check(&Token::RightBracket) {
1724 loop {
1725 elements.push(self.parse_expression()?);
1726 if self.check(&Token::Comma) {
1727 self.advance();
1728 } else {
1729 break;
1730 }
1731 }
1732 }
1733
1734 self.consume(Token::RightBracket, "Expected ']' after array elements")?;
1735
1736 Ok(Expression::ArrayDef {
1737 elements,
1738 location: Location::unknown(),
1739 })
1740 }
1741 token => Err(XdlError::ParseError {
1742 message: format!("Unexpected token: {:?}", token),
1743 line: 1,
1744 column: self.current,
1745 }),
1746 }
1747 }
1748}
1749
1750pub fn parse_program(tokens: &[Token]) -> XdlResult<Program> {
1752 let mut parser = Parser::new(tokens);
1753 parser.parse_program()
1754}
1755
1756pub fn parse_expression(tokens: &[Token]) -> XdlResult<Expression> {
1757 let mut parser = Parser::new(tokens);
1758 parser.parse_expression()
1759}
1760
1761#[cfg(test)]
1762mod tests {
1763 use super::*;
1764 use crate::lexer::tokenize;
1765
1766 #[test]
1767 fn test_parse_simple_assignment() {
1768 let input = "x = 42";
1769 let tokens = tokenize(input).unwrap();
1770 let program = parse_program(&tokens).unwrap();
1771
1772 assert_eq!(program.statements.len(), 1);
1773 match &program.statements[0] {
1774 Statement::Assignment { target, value, .. } => {
1775 assert!(matches!(target, Expression::Variable { name, .. } if name == "x"));
1776 assert!(matches!(
1777 value,
1778 Expression::Literal {
1779 value: XdlValue::Long(42),
1780 ..
1781 }
1782 ));
1783 }
1784 _ => panic!("Expected assignment statement"),
1785 }
1786 }
1787
1788 #[test]
1789 fn test_parse_arithmetic_expression() {
1790 let input = "2 + 3 * 4";
1791 let tokens = tokenize(input).unwrap();
1792 let expr = parse_expression(&tokens).unwrap();
1793
1794 match expr {
1795 Expression::Binary {
1796 op: BinaryOp::Add,
1797 left,
1798 right,
1799 ..
1800 } => {
1801 assert!(matches!(
1802 left.as_ref(),
1803 Expression::Literal {
1804 value: XdlValue::Long(2),
1805 ..
1806 }
1807 ));
1808 match right.as_ref() {
1809 Expression::Binary {
1810 op: BinaryOp::Multiply,
1811 ..
1812 } => {}
1813 _ => panic!("Expected multiplication on right side"),
1814 }
1815 }
1816 _ => panic!("Expected binary addition expression"),
1817 }
1818 }
1819
1820 #[test]
1821 fn test_parse_function_call() {
1822 let input = "sin(x)";
1823 let tokens = tokenize(input).unwrap();
1824 let expr = parse_expression(&tokens).unwrap();
1825
1826 match expr {
1827 Expression::FunctionCall { name, args, .. } => {
1828 assert_eq!(name, "sin");
1829 assert_eq!(args.len(), 1);
1830 assert!(matches!(args[0], Expression::Variable { name: ref n, .. } if n == "x"));
1831 }
1832 _ => panic!("Expected function call expression"),
1833 }
1834 }
1835
1836 #[test]
1837 fn test_parse_if_statement() {
1838 let input = "if x eq 42 then\n y = 1\nendif";
1839 let tokens = tokenize(input).unwrap();
1840 let program = parse_program(&tokens).unwrap();
1841
1842 assert_eq!(program.statements.len(), 1);
1843 match &program.statements[0] {
1844 Statement::If {
1845 condition,
1846 then_block,
1847 else_block,
1848 ..
1849 } => {
1850 assert!(matches!(
1851 condition,
1852 Expression::Binary {
1853 op: BinaryOp::Equal,
1854 ..
1855 }
1856 ));
1857 assert_eq!(then_block.len(), 1);
1858 assert!(else_block.is_none());
1859 }
1860 _ => panic!("Expected if statement"),
1861 }
1862 }
1863
1864 #[test]
1865 fn test_parse_for_loop() {
1866 let input = "for i = 0, 10\n x = i\nendfor";
1867 let tokens = tokenize(input).unwrap();
1868 let program = parse_program(&tokens).unwrap();
1869
1870 assert_eq!(program.statements.len(), 1);
1871 match &program.statements[0] {
1872 Statement::For {
1873 variable,
1874 start,
1875 end,
1876 step,
1877 body,
1878 ..
1879 } => {
1880 assert_eq!(variable, "i");
1881 assert!(matches!(
1882 start,
1883 Expression::Literal {
1884 value: XdlValue::Long(0),
1885 ..
1886 }
1887 ));
1888 assert!(matches!(
1889 end,
1890 Expression::Literal {
1891 value: XdlValue::Long(10),
1892 ..
1893 }
1894 ));
1895 assert!(step.is_none());
1896 assert_eq!(body.len(), 1);
1897 }
1898 _ => panic!("Expected for statement"),
1899 }
1900 }
1901}