1use crate::ast::*;
2use crate::error::{Error, Result, SourceLocation};
3use crate::lexer::{Token, TokenKind};
4
5pub struct Parser {
7 tokens: Vec<Token>,
8 current: usize,
9}
10
11impl Parser {
12 pub fn new(tokens: Vec<Token>) -> Self {
13 Self { tokens, current: 0 }
14 }
15
16 pub fn parse(&mut self) -> Result<Program> {
18 let mut program = Program::new();
19
20 self.skip_newlines();
21
22 while !self.is_at_end() {
23 if self.check(&TokenKind::Function) {
25 program.functions.push(self.parse_function()?);
26 } else {
27 program.rules.push(self.parse_rule()?);
28 }
29 self.skip_newlines();
30 }
31
32 Ok(program)
33 }
34
35 fn parse_function(&mut self) -> Result<FunctionDef> {
37 let location = self.current_location();
38 self.expect(&TokenKind::Function)?;
39
40 let name = self.expect_identifier()?;
41 self.expect(&TokenKind::LeftParen)?;
42
43 let mut params = Vec::new();
44 if !self.check(&TokenKind::RightParen) {
45 params.push(self.expect_identifier()?);
46 while self.match_token(&TokenKind::Comma) {
47 params.push(self.expect_identifier()?);
48 }
49 }
50 self.expect(&TokenKind::RightParen)?;
51 self.skip_newlines();
52
53 let body = self.parse_block()?;
54
55 Ok(FunctionDef {
56 name,
57 params,
58 body,
59 location,
60 })
61 }
62
63 fn parse_rule(&mut self) -> Result<Rule> {
65 let location = self.current_location();
66
67 if self.check(&TokenKind::Begin) {
69 self.advance();
70 self.skip_newlines();
71 let action = Some(self.parse_block()?);
72 return Ok(Rule {
73 pattern: Some(Pattern::Begin),
74 action,
75 location,
76 });
77 }
78
79 if self.check(&TokenKind::End) {
80 self.advance();
81 self.skip_newlines();
82 let action = Some(self.parse_block()?);
83 return Ok(Rule {
84 pattern: Some(Pattern::End),
85 action,
86 location,
87 });
88 }
89
90 if self.check(&TokenKind::BeginFile) {
91 self.advance();
92 self.skip_newlines();
93 let action = Some(self.parse_block()?);
94 return Ok(Rule {
95 pattern: Some(Pattern::BeginFile),
96 action,
97 location,
98 });
99 }
100
101 if self.check(&TokenKind::EndFile) {
102 self.advance();
103 self.skip_newlines();
104 let action = Some(self.parse_block()?);
105 return Ok(Rule {
106 pattern: Some(Pattern::EndFile),
107 action,
108 location,
109 });
110 }
111
112 if self.check(&TokenKind::LeftBrace) {
114 let action = Some(self.parse_block()?);
115 return Ok(Rule {
116 pattern: None,
117 action,
118 location,
119 });
120 }
121
122 let pattern = Some(self.parse_pattern()?);
124 self.skip_newlines();
125
126 let action = if self.check(&TokenKind::LeftBrace) {
128 Some(self.parse_block()?)
129 } else {
130 None
131 };
132
133 Ok(Rule {
134 pattern,
135 action,
136 location,
137 })
138 }
139
140 fn parse_pattern(&mut self) -> Result<Pattern> {
142 if let Some(TokenKind::Regex(pattern)) = self.peek_kind() {
144 let pattern = pattern.clone();
145 self.advance();
146
147 if self.match_token(&TokenKind::Comma) {
149 self.skip_newlines();
150 let end = self.parse_pattern()?;
151 return Ok(Pattern::Range {
152 start: Box::new(Pattern::Regex(pattern)),
153 end: Box::new(end),
154 });
155 }
156
157 return Ok(Pattern::Regex(pattern));
158 }
159
160 let expr = self.parse_expression()?;
162
163 if self.match_token(&TokenKind::Comma) {
165 self.skip_newlines();
166 let end = self.parse_pattern()?;
167 return Ok(Pattern::Range {
168 start: Box::new(Pattern::Expr(expr)),
169 end: Box::new(end),
170 });
171 }
172
173 Ok(Pattern::Expr(expr))
174 }
175
176 fn parse_block(&mut self) -> Result<Block> {
178 let location = self.current_location();
179 self.expect(&TokenKind::LeftBrace)?;
180 self.skip_newlines();
181
182 let mut statements = Vec::new();
183
184 while !self.check(&TokenKind::RightBrace) && !self.is_at_end() {
185 statements.push(self.parse_statement()?);
186 self.skip_terminators();
187 }
188
189 self.expect(&TokenKind::RightBrace)?;
190
191 Ok(Block::new(statements, location))
192 }
193
194 fn parse_statement(&mut self) -> Result<Stmt> {
196 self.skip_newlines();
197
198 let location = self.current_location();
199
200 if self.check(&TokenKind::Semicolon) {
202 self.advance();
203 return Ok(Stmt::Empty);
204 }
205
206 if self.check(&TokenKind::LeftBrace) {
208 return Ok(Stmt::Block(self.parse_block()?));
209 }
210
211 if self.match_token(&TokenKind::If) {
213 return self.parse_if_statement(location);
214 }
215
216 if self.match_token(&TokenKind::While) {
218 return self.parse_while_statement(location);
219 }
220
221 if self.match_token(&TokenKind::For) {
223 return self.parse_for_statement(location);
224 }
225
226 if self.match_token(&TokenKind::Do) {
228 return self.parse_do_while_statement(location);
229 }
230
231 if self.match_token(&TokenKind::Break) {
233 return Ok(Stmt::Break { location });
234 }
235
236 if self.match_token(&TokenKind::Continue) {
238 return Ok(Stmt::Continue { location });
239 }
240
241 if self.match_token(&TokenKind::Next) {
243 return Ok(Stmt::Next { location });
244 }
245
246 if self.match_token(&TokenKind::Nextfile) {
248 return Ok(Stmt::Nextfile { location });
249 }
250
251 if self.match_token(&TokenKind::Exit) {
253 let code = if self.can_start_expression() {
254 Some(self.parse_expression()?)
255 } else {
256 None
257 };
258 return Ok(Stmt::Exit { code, location });
259 }
260
261 if self.match_token(&TokenKind::Return) {
263 let value = if self.can_start_expression() {
264 Some(self.parse_expression()?)
265 } else {
266 None
267 };
268 return Ok(Stmt::Return { value, location });
269 }
270
271 if self.match_token(&TokenKind::Delete) {
273 let name = self.expect_identifier()?;
274
275 let indices = if self.match_token(&TokenKind::LeftBracket) {
277 let mut indices = vec![self.parse_expression()?];
278 while self.match_token(&TokenKind::Comma) {
279 indices.push(self.parse_expression()?);
280 }
281 self.expect(&TokenKind::RightBracket)?;
282 indices
283 } else {
284 Vec::new()
286 };
287
288 return Ok(Stmt::Delete {
289 array: name,
290 index: indices,
291 location,
292 });
293 }
294
295 if self.match_token(&TokenKind::Print) {
297 return self.parse_print_statement(location);
298 }
299
300 if self.match_token(&TokenKind::Printf) {
302 return self.parse_printf_statement(location);
303 }
304
305 let expr = self.parse_expression()?;
307 Ok(Stmt::Expr(expr))
308 }
309
310 fn parse_if_statement(&mut self, location: SourceLocation) -> Result<Stmt> {
311 self.expect(&TokenKind::LeftParen)?;
312 let condition = self.parse_expression()?;
313 self.expect(&TokenKind::RightParen)?;
314 self.skip_newlines();
315
316 let then_branch = Box::new(self.parse_statement()?);
317
318 self.skip_terminators();
320 let else_branch = if self.match_token(&TokenKind::Else) {
321 self.skip_newlines();
322 Some(Box::new(self.parse_statement()?))
323 } else {
324 None
325 };
326
327 Ok(Stmt::If {
328 condition,
329 then_branch,
330 else_branch,
331 location,
332 })
333 }
334
335 fn parse_while_statement(&mut self, location: SourceLocation) -> Result<Stmt> {
336 self.expect(&TokenKind::LeftParen)?;
337 let condition = self.parse_expression()?;
338 self.expect(&TokenKind::RightParen)?;
339 self.skip_newlines();
340
341 let body = Box::new(self.parse_statement()?);
342
343 Ok(Stmt::While {
344 condition,
345 body,
346 location,
347 })
348 }
349
350 fn parse_for_statement(&mut self, location: SourceLocation) -> Result<Stmt> {
351 self.expect(&TokenKind::LeftParen)?;
352
353 if let Some(TokenKind::Identifier(name)) = self.peek_kind() {
355 let name = name.clone();
356 let saved_pos = self.current;
357 self.advance();
358
359 if self.match_token(&TokenKind::In) {
360 let array = self.expect_identifier()?;
361 self.expect(&TokenKind::RightParen)?;
362 self.skip_newlines();
363 let body = Box::new(self.parse_statement()?);
364
365 return Ok(Stmt::ForIn {
366 var: name,
367 array,
368 body,
369 location,
370 });
371 }
372
373 self.current = saved_pos;
375 }
376
377 let init = if !self.check(&TokenKind::Semicolon) {
379 Some(Box::new(self.parse_statement()?))
380 } else {
381 None
382 };
383 self.expect(&TokenKind::Semicolon)?;
384
385 let condition = if !self.check(&TokenKind::Semicolon) {
386 Some(self.parse_expression()?)
387 } else {
388 None
389 };
390 self.expect(&TokenKind::Semicolon)?;
391
392 let update = if !self.check(&TokenKind::RightParen) {
393 Some(self.parse_expression()?)
394 } else {
395 None
396 };
397 self.expect(&TokenKind::RightParen)?;
398 self.skip_newlines();
399
400 let body = Box::new(self.parse_statement()?);
401
402 Ok(Stmt::For {
403 init,
404 condition,
405 update,
406 body,
407 location,
408 })
409 }
410
411 fn parse_do_while_statement(&mut self, location: SourceLocation) -> Result<Stmt> {
412 self.skip_newlines();
413 let body = Box::new(self.parse_statement()?);
414 self.skip_newlines();
415 self.expect(&TokenKind::While)?;
416 self.expect(&TokenKind::LeftParen)?;
417 let condition = self.parse_expression()?;
418 self.expect(&TokenKind::RightParen)?;
419
420 Ok(Stmt::DoWhile {
421 body,
422 condition,
423 location,
424 })
425 }
426
427 fn parse_print_statement(&mut self, location: SourceLocation) -> Result<Stmt> {
428 let mut args = Vec::new();
429
430 if self.can_start_expression()
432 && !self.check(&TokenKind::Greater)
433 && !self.check(&TokenKind::Append)
434 && !self.check(&TokenKind::Pipe)
435 {
436 args.push(self.parse_print_arg()?);
437 while self.match_token(&TokenKind::Comma) {
438 args.push(self.parse_print_arg()?);
439 }
440 }
441
442 let output = self.parse_output_redirect()?;
444
445 Ok(Stmt::Print {
446 args,
447 output,
448 location,
449 })
450 }
451
452 fn parse_printf_statement(&mut self, location: SourceLocation) -> Result<Stmt> {
453 let format = self.parse_print_arg()?;
454 let mut args = Vec::new();
455
456 while self.match_token(&TokenKind::Comma) {
457 args.push(self.parse_print_arg()?);
458 }
459
460 let output = self.parse_output_redirect()?;
461
462 Ok(Stmt::Printf {
463 format,
464 args,
465 output,
466 location,
467 })
468 }
469
470 fn parse_print_arg(&mut self) -> Result<Expr> {
471 self.parse_print_ternary()
474 }
475
476 fn parse_print_ternary(&mut self) -> Result<Expr> {
477 let expr = self.parse_print_or()?;
478
479 if self.match_token(&TokenKind::Question) {
480 let location = self.current_location();
481 let then_expr = self.parse_print_ternary()?;
482 self.expect(&TokenKind::Colon)?;
483 let else_expr = self.parse_print_ternary()?;
484 return Ok(Expr::Ternary {
485 condition: Box::new(expr),
486 then_expr: Box::new(then_expr),
487 else_expr: Box::new(else_expr),
488 location,
489 });
490 }
491
492 Ok(expr)
493 }
494
495 fn parse_print_or(&mut self) -> Result<Expr> {
496 let mut expr = self.parse_print_and()?;
497
498 while self.match_token(&TokenKind::Or) {
499 let location = self.current_location();
500 let right = self.parse_print_and()?;
501 expr = Expr::Binary {
502 left: Box::new(expr),
503 op: BinaryOp::Or,
504 right: Box::new(right),
505 location,
506 };
507 }
508
509 Ok(expr)
510 }
511
512 fn parse_print_and(&mut self) -> Result<Expr> {
513 let mut expr = self.parse_print_in()?;
514
515 while self.match_token(&TokenKind::And) {
516 let location = self.current_location();
517 let right = self.parse_print_in()?;
518 expr = Expr::Binary {
519 left: Box::new(expr),
520 op: BinaryOp::And,
521 right: Box::new(right),
522 location,
523 };
524 }
525
526 Ok(expr)
527 }
528
529 fn parse_print_in(&mut self) -> Result<Expr> {
530 let expr = self.parse_print_match()?;
531
532 if self.match_token(&TokenKind::In) {
533 let location = self.current_location();
534 let array = self.expect_identifier()?;
535 return Ok(Expr::InArray {
536 key: vec![expr],
537 array,
538 location,
539 });
540 }
541
542 Ok(expr)
543 }
544
545 fn parse_print_match(&mut self) -> Result<Expr> {
546 let expr = self.parse_print_comparison()?;
547
548 let location = self.current_location();
549 if self.match_token(&TokenKind::Match) {
550 let pattern = self.parse_print_comparison()?;
551 return Ok(Expr::Match {
552 expr: Box::new(expr),
553 pattern: Box::new(pattern),
554 negated: false,
555 location,
556 });
557 }
558
559 if self.match_token(&TokenKind::NotMatch) {
560 let pattern = self.parse_print_comparison()?;
561 return Ok(Expr::Match {
562 expr: Box::new(expr),
563 pattern: Box::new(pattern),
564 negated: true,
565 location,
566 });
567 }
568
569 Ok(expr)
570 }
571
572 fn parse_print_comparison(&mut self) -> Result<Expr> {
573 let mut expr = self.parse_concat()?;
574
575 loop {
578 let location = self.current_location();
579 let op = if self.match_token(&TokenKind::Less) {
580 BinaryOp::Lt
581 } else if self.match_token(&TokenKind::LessEqual) {
582 BinaryOp::Le
583 } else if self.match_token(&TokenKind::GreaterEqual) {
584 BinaryOp::Ge
585 } else if self.match_token(&TokenKind::Equal) {
586 BinaryOp::Eq
587 } else if self.match_token(&TokenKind::NotEqual) {
588 BinaryOp::Ne
589 } else {
590 break;
592 };
593
594 let right = self.parse_concat()?;
595 expr = Expr::Binary {
596 left: Box::new(expr),
597 op,
598 right: Box::new(right),
599 location,
600 };
601 }
602
603 Ok(expr)
604 }
605
606 fn parse_output_redirect(&mut self) -> Result<Option<OutputRedirect>> {
607 if self.match_token(&TokenKind::Greater) {
608 let target = self.parse_print_arg()?;
609 Ok(Some(OutputRedirect::Truncate(target)))
610 } else if self.match_token(&TokenKind::Append) {
611 let target = self.parse_print_arg()?;
612 Ok(Some(OutputRedirect::Append(target)))
613 } else if self.match_token(&TokenKind::Pipe) {
614 let target = self.parse_print_arg()?;
615 Ok(Some(OutputRedirect::Pipe(target)))
616 } else {
617 Ok(None)
618 }
619 }
620
621 fn parse_expression(&mut self) -> Result<Expr> {
623 self.parse_assignment()
624 }
625
626 fn parse_assignment(&mut self) -> Result<Expr> {
627 let expr = self.parse_ternary()?;
628
629 let location = self.current_location();
631 let op = if self.match_token(&TokenKind::Assign) {
632 Some(AssignOp::Assign)
633 } else if self.match_token(&TokenKind::PlusAssign) {
634 Some(AssignOp::AddAssign)
635 } else if self.match_token(&TokenKind::MinusAssign) {
636 Some(AssignOp::SubAssign)
637 } else if self.match_token(&TokenKind::StarAssign) {
638 Some(AssignOp::MulAssign)
639 } else if self.match_token(&TokenKind::SlashAssign) {
640 Some(AssignOp::DivAssign)
641 } else if self.match_token(&TokenKind::PercentAssign) {
642 Some(AssignOp::ModAssign)
643 } else if self.match_token(&TokenKind::CaretAssign) {
644 Some(AssignOp::PowAssign)
645 } else {
646 None
647 };
648
649 if let Some(op) = op {
650 let value = self.parse_assignment()?;
651 return Ok(Expr::Assign {
652 target: Box::new(expr),
653 op,
654 value: Box::new(value),
655 location,
656 });
657 }
658
659 Ok(expr)
660 }
661
662 fn parse_ternary(&mut self) -> Result<Expr> {
663 let expr = self.parse_or()?;
664
665 if self.match_token(&TokenKind::Question) {
666 let location = self.current_location();
667 let then_expr = self.parse_expression()?;
668 self.expect(&TokenKind::Colon)?;
669 let else_expr = self.parse_ternary()?;
670 return Ok(Expr::Ternary {
671 condition: Box::new(expr),
672 then_expr: Box::new(then_expr),
673 else_expr: Box::new(else_expr),
674 location,
675 });
676 }
677
678 Ok(expr)
679 }
680
681 fn parse_or(&mut self) -> Result<Expr> {
682 let mut expr = self.parse_and()?;
683
684 while self.match_token(&TokenKind::Or) {
685 let location = self.current_location();
686 let right = self.parse_and()?;
687 expr = Expr::Binary {
688 left: Box::new(expr),
689 op: BinaryOp::Or,
690 right: Box::new(right),
691 location,
692 };
693 }
694
695 Ok(expr)
696 }
697
698 fn parse_and(&mut self) -> Result<Expr> {
699 let mut expr = self.parse_in()?;
700
701 while self.match_token(&TokenKind::And) {
702 let location = self.current_location();
703 let right = self.parse_in()?;
704 expr = Expr::Binary {
705 left: Box::new(expr),
706 op: BinaryOp::And,
707 right: Box::new(right),
708 location,
709 };
710 }
711
712 Ok(expr)
713 }
714
715 fn parse_in(&mut self) -> Result<Expr> {
716 let expr = self.parse_pipe_getline()?;
717
718 if self.match_token(&TokenKind::In) {
721 let location = self.current_location();
722 let array = self.expect_identifier()?;
723 return Ok(Expr::InArray {
724 key: vec![expr],
725 array,
726 location,
727 });
728 }
729
730 Ok(expr)
731 }
732
733 fn parse_getline_target(&mut self) -> Result<Option<Box<Expr>>> {
739 let location = self.current_location();
740
741 if self.check(&TokenKind::Dollar) {
742 return Ok(Some(Box::new(self.parse_field()?)));
743 }
744
745 let Some(TokenKind::Identifier(name)) = self.peek_kind() else {
746 return Ok(None);
747 };
748 let name = name.clone();
749 self.advance();
750
751 if self.match_token(&TokenKind::LeftBracket) {
752 let mut indices = vec![self.parse_expression()?];
753 while self.match_token(&TokenKind::Comma) {
754 indices.push(self.parse_expression()?);
755 }
756 self.expect(&TokenKind::RightBracket)?;
757 return Ok(Some(Box::new(Expr::ArrayAccess {
758 array: name,
759 indices,
760 location,
761 })));
762 }
763
764 Ok(Some(Box::new(Expr::Var(name, location))))
765 }
766
767 fn parse_pipe_getline(&mut self) -> Result<Expr> {
769 let expr = self.parse_match()?;
770
771 if self.check(&TokenKind::Pipe) {
773 let saved_pos = self.current;
775 self.advance(); if self.check(&TokenKind::Getline) {
778 let location = self.current_location();
779 self.advance(); let var = self.parse_getline_target()?;
783
784 return Ok(Expr::Getline {
785 var,
786 input: Some(GetlineInput::Pipe(Box::new(expr))),
787 location,
788 });
789 } else {
790 self.current = saved_pos;
792 }
793 }
794
795 Ok(expr)
796 }
797
798 fn parse_match(&mut self) -> Result<Expr> {
799 let expr = self.parse_comparison()?;
800
801 let location = self.current_location();
802 if self.match_token(&TokenKind::Match) {
803 let pattern = self.parse_comparison()?;
804 return Ok(Expr::Match {
805 expr: Box::new(expr),
806 pattern: Box::new(pattern),
807 negated: false,
808 location,
809 });
810 }
811
812 if self.match_token(&TokenKind::NotMatch) {
813 let pattern = self.parse_comparison()?;
814 return Ok(Expr::Match {
815 expr: Box::new(expr),
816 pattern: Box::new(pattern),
817 negated: true,
818 location,
819 });
820 }
821
822 Ok(expr)
823 }
824
825 fn parse_comparison(&mut self) -> Result<Expr> {
826 let mut expr = self.parse_concat()?;
827
828 loop {
829 let location = self.current_location();
830 let op = if self.match_token(&TokenKind::Less) {
831 BinaryOp::Lt
832 } else if self.match_token(&TokenKind::LessEqual) {
833 BinaryOp::Le
834 } else if self.match_token(&TokenKind::Greater) {
835 BinaryOp::Gt
836 } else if self.match_token(&TokenKind::GreaterEqual) {
837 BinaryOp::Ge
838 } else if self.match_token(&TokenKind::Equal) {
839 BinaryOp::Eq
840 } else if self.match_token(&TokenKind::NotEqual) {
841 BinaryOp::Ne
842 } else {
843 break;
844 };
845
846 let right = self.parse_concat()?;
847 expr = Expr::Binary {
848 left: Box::new(expr),
849 op,
850 right: Box::new(right),
851 location,
852 };
853 }
854
855 Ok(expr)
856 }
857
858 fn parse_concat(&mut self) -> Result<Expr> {
859 let mut expr = self.parse_additive()?;
860
861 while self.can_start_concat_operand() {
864 let right = self.parse_additive()?;
865 let location = expr.location();
866 expr = Expr::Binary {
867 left: Box::new(expr),
868 op: BinaryOp::Concat,
869 right: Box::new(right),
870 location,
871 };
872 }
873
874 Ok(expr)
875 }
876
877 fn can_start_concat_operand(&mut self) -> bool {
878 if let Some(kind) = self.peek_kind() {
879 matches!(
880 kind,
881 TokenKind::Number(_)
882 | TokenKind::String(_)
883 | TokenKind::Identifier(_)
884 | TokenKind::Dollar
885 | TokenKind::LeftParen
886 | TokenKind::Not
887 | TokenKind::Increment
888 | TokenKind::Decrement
889 )
890 } else {
891 false
892 }
893 }
894
895 fn parse_additive(&mut self) -> Result<Expr> {
896 let mut expr = self.parse_multiplicative()?;
897
898 loop {
899 let location = self.current_location();
900 let op = if self.match_token(&TokenKind::Plus) {
901 BinaryOp::Add
902 } else if self.match_token(&TokenKind::Minus) {
903 BinaryOp::Sub
904 } else {
905 break;
906 };
907
908 let right = self.parse_multiplicative()?;
909 expr = Expr::Binary {
910 left: Box::new(expr),
911 op,
912 right: Box::new(right),
913 location,
914 };
915 }
916
917 Ok(expr)
918 }
919
920 fn parse_multiplicative(&mut self) -> Result<Expr> {
921 let mut expr = self.parse_power()?;
922
923 loop {
924 let location = self.current_location();
925 let op = if self.match_token(&TokenKind::Star) {
926 BinaryOp::Mul
927 } else if self.match_token(&TokenKind::Slash) {
928 BinaryOp::Div
929 } else if self.match_token(&TokenKind::Percent) {
930 BinaryOp::Mod
931 } else {
932 break;
933 };
934
935 let right = self.parse_power()?;
936 expr = Expr::Binary {
937 left: Box::new(expr),
938 op,
939 right: Box::new(right),
940 location,
941 };
942 }
943
944 Ok(expr)
945 }
946
947 fn parse_power(&mut self) -> Result<Expr> {
948 let expr = self.parse_unary()?;
949
950 if self.match_token(&TokenKind::Caret) {
952 let location = self.current_location();
953 let right = self.parse_power()?;
954 return Ok(Expr::Binary {
955 left: Box::new(expr),
956 op: BinaryOp::Pow,
957 right: Box::new(right),
958 location,
959 });
960 }
961
962 Ok(expr)
963 }
964
965 fn parse_unary(&mut self) -> Result<Expr> {
966 let location = self.current_location();
967
968 if self.match_token(&TokenKind::Not) {
969 let operand = self.parse_unary()?;
970 return Ok(Expr::Unary {
971 op: UnaryOp::Not,
972 operand: Box::new(operand),
973 location,
974 });
975 }
976
977 if self.match_token(&TokenKind::Minus) {
978 let operand = self.parse_unary()?;
979 return Ok(Expr::Unary {
980 op: UnaryOp::Neg,
981 operand: Box::new(operand),
982 location,
983 });
984 }
985
986 if self.match_token(&TokenKind::Plus) {
987 let operand = self.parse_unary()?;
988 return Ok(Expr::Unary {
989 op: UnaryOp::Pos,
990 operand: Box::new(operand),
991 location,
992 });
993 }
994
995 if self.match_token(&TokenKind::Increment) {
996 let operand = self.parse_unary()?;
997 return Ok(Expr::PreIncrement(Box::new(operand), location));
998 }
999
1000 if self.match_token(&TokenKind::Decrement) {
1001 let operand = self.parse_unary()?;
1002 return Ok(Expr::PreDecrement(Box::new(operand), location));
1003 }
1004
1005 self.parse_postfix()
1006 }
1007
1008 fn parse_postfix(&mut self) -> Result<Expr> {
1009 let mut expr = self.parse_field()?;
1010
1011 loop {
1012 let location = self.current_location();
1013
1014 if self.match_token(&TokenKind::Increment) {
1015 expr = Expr::PostIncrement(Box::new(expr), location);
1016 } else if self.match_token(&TokenKind::Decrement) {
1017 expr = Expr::PostDecrement(Box::new(expr), location);
1018 } else if self.match_token(&TokenKind::LeftBracket) {
1019 if let Expr::Var(name, _) = expr {
1021 let mut indices = vec![self.parse_expression()?];
1022 while self.match_token(&TokenKind::Comma) {
1023 indices.push(self.parse_expression()?);
1024 }
1025 self.expect(&TokenKind::RightBracket)?;
1026 expr = Expr::ArrayAccess {
1027 array: name,
1028 indices,
1029 location,
1030 };
1031 } else {
1032 return Err(Error::parser(
1033 "array access requires variable name",
1034 location.line,
1035 location.column,
1036 ));
1037 }
1038 } else {
1039 break;
1040 }
1041 }
1042
1043 Ok(expr)
1044 }
1045
1046 fn parse_field(&mut self) -> Result<Expr> {
1047 if self.match_token(&TokenKind::Dollar) {
1048 let location = self.current_location();
1049 let expr = self.parse_field_operand()?;
1050 return Ok(Expr::Field(Box::new(expr), location));
1051 }
1052
1053 self.parse_primary()
1054 }
1055
1056 fn parse_field_operand(&mut self) -> Result<Expr> {
1066 let location = self.current_location();
1067
1068 if self.match_token(&TokenKind::Not) {
1069 let operand = self.parse_field_operand()?;
1070 return Ok(Expr::Unary {
1071 op: UnaryOp::Not,
1072 operand: Box::new(operand),
1073 location,
1074 });
1075 }
1076
1077 if self.match_token(&TokenKind::Minus) {
1078 let operand = self.parse_field_operand()?;
1079 return Ok(Expr::Unary {
1080 op: UnaryOp::Neg,
1081 operand: Box::new(operand),
1082 location,
1083 });
1084 }
1085
1086 if self.match_token(&TokenKind::Plus) {
1087 let operand = self.parse_field_operand()?;
1088 return Ok(Expr::Unary {
1089 op: UnaryOp::Pos,
1090 operand: Box::new(operand),
1091 location,
1092 });
1093 }
1094
1095 if self.match_token(&TokenKind::Increment) {
1096 let operand = self.parse_field_operand()?;
1097 return Ok(Expr::PreIncrement(Box::new(operand), location));
1098 }
1099
1100 if self.match_token(&TokenKind::Decrement) {
1101 let operand = self.parse_field_operand()?;
1102 return Ok(Expr::PreDecrement(Box::new(operand), location));
1103 }
1104
1105 self.parse_field()
1106 }
1107
1108 fn parse_primary(&mut self) -> Result<Expr> {
1109 let location = self.current_location();
1110
1111 if let Some(TokenKind::Number(n)) = self.peek_kind() {
1113 let n = *n;
1114 self.advance();
1115 return Ok(Expr::Number(n, location));
1116 }
1117
1118 if let Some(TokenKind::String(s)) = self.peek_kind() {
1120 let s = s.clone();
1121 self.advance();
1122 return Ok(Expr::String(s, location));
1123 }
1124
1125 if let Some(TokenKind::Regex(r)) = self.peek_kind() {
1127 let r = r.clone();
1128 self.advance();
1129 return Ok(Expr::Regex(r, location));
1130 }
1131
1132 if let Some(TokenKind::Identifier(name)) = self.peek_kind() {
1134 let name = name.clone();
1135 self.advance();
1136
1137 if self.match_token(&TokenKind::LeftParen) {
1139 let mut args = Vec::new();
1140 if !self.check(&TokenKind::RightParen) {
1141 args.push(self.parse_expression()?);
1142 while self.match_token(&TokenKind::Comma) {
1143 args.push(self.parse_expression()?);
1144 }
1145 }
1146 self.expect(&TokenKind::RightParen)?;
1147 return Ok(Expr::Call {
1148 name,
1149 args,
1150 location,
1151 });
1152 }
1153
1154 return Ok(Expr::Var(name, location));
1155 }
1156
1157 if self.match_token(&TokenKind::Getline) {
1159 let var = self.parse_getline_target()?;
1160
1161 let input = if self.match_token(&TokenKind::Less) {
1162 Some(GetlineInput::File(Box::new(self.parse_primary()?)))
1163 } else {
1164 None
1165 };
1166
1167 return Ok(Expr::Getline {
1168 var,
1169 input,
1170 location,
1171 });
1172 }
1173
1174 if self.match_token(&TokenKind::LeftParen) {
1176 let expr = self.parse_expression()?;
1177 self.expect(&TokenKind::RightParen)?;
1178 return Ok(Expr::Group(Box::new(expr), location));
1179 }
1180
1181 Err(Error::parser(
1182 format!("unexpected token {:?}", self.peek_kind()),
1183 location.line,
1184 location.column,
1185 ))
1186 }
1187
1188 fn peek_kind(&self) -> Option<&TokenKind> {
1191 self.tokens.get(self.current).map(|t| &t.kind)
1192 }
1193
1194 fn current_location(&self) -> SourceLocation {
1195 self.tokens
1196 .get(self.current)
1197 .map(|t| t.location)
1198 .unwrap_or(SourceLocation::new(0, 0))
1199 }
1200
1201 fn is_at_end(&self) -> bool {
1202 matches!(self.peek_kind(), None | Some(TokenKind::Eof))
1203 }
1204
1205 fn check(&self, kind: &TokenKind) -> bool {
1206 self.peek_kind()
1207 .map(|k| std::mem::discriminant(k) == std::mem::discriminant(kind))
1208 .unwrap_or(false)
1209 }
1210
1211 fn advance(&mut self) -> Option<&Token> {
1212 if !self.is_at_end() {
1213 self.current += 1;
1214 }
1215 self.tokens.get(self.current - 1)
1216 }
1217
1218 fn match_token(&mut self, kind: &TokenKind) -> bool {
1219 if self.check(kind) {
1220 self.advance();
1221 true
1222 } else {
1223 false
1224 }
1225 }
1226
1227 fn expect(&mut self, kind: &TokenKind) -> Result<&Token> {
1228 if self.check(kind) {
1229 Ok(self.advance().unwrap())
1230 } else {
1231 let loc = self.current_location();
1232 Err(Error::parser(
1233 format!("expected {:?}, found {:?}", kind, self.peek_kind()),
1234 loc.line,
1235 loc.column,
1236 ))
1237 }
1238 }
1239
1240 fn expect_identifier(&mut self) -> Result<String> {
1241 if let Some(TokenKind::Identifier(name)) = self.peek_kind() {
1242 let name = name.clone();
1243 self.advance();
1244 Ok(name)
1245 } else {
1246 let loc = self.current_location();
1247 Err(Error::parser(
1248 format!("expected identifier, found {:?}", self.peek_kind()),
1249 loc.line,
1250 loc.column,
1251 ))
1252 }
1253 }
1254
1255 fn skip_newlines(&mut self) {
1256 while self.match_token(&TokenKind::Newline) {}
1257 }
1258
1259 fn skip_terminators(&mut self) {
1260 while self.match_token(&TokenKind::Newline) || self.match_token(&TokenKind::Semicolon) {}
1261 }
1262
1263 fn can_start_expression(&self) -> bool {
1264 self.peek_kind()
1265 .map(|k| k.can_start_expression())
1266 .unwrap_or(false)
1267 }
1268}
1269
1270#[cfg(test)]
1271mod tests {
1272 use super::*;
1273 use crate::lexer::Lexer;
1274
1275 fn parse(source: &str) -> Result<Program> {
1276 let mut lexer = Lexer::new(source);
1277 let tokens = lexer.tokenize()?;
1278 let mut parser = Parser::new(tokens);
1279 parser.parse()
1280 }
1281
1282 #[test]
1283 fn test_simple_print() {
1284 let program = parse(r#"{ print "hello" }"#).unwrap();
1285 assert_eq!(program.rules.len(), 1);
1286 }
1287
1288 #[test]
1289 fn test_begin_end() {
1290 let program = parse(r#"BEGIN { x = 1 } END { print x }"#).unwrap();
1291 assert_eq!(program.rules.len(), 2);
1292 assert!(matches!(program.rules[0].pattern, Some(Pattern::Begin)));
1293 assert!(matches!(program.rules[1].pattern, Some(Pattern::End)));
1294 }
1295
1296 #[test]
1297 fn test_regex_pattern() {
1298 let program = parse(r#"/foo/ { print }"#).unwrap();
1299 assert_eq!(program.rules.len(), 1);
1300 assert!(matches!(
1301 &program.rules[0].pattern,
1302 Some(Pattern::Regex(r)) if r == "foo"
1303 ));
1304 }
1305
1306 #[test]
1307 fn test_arithmetic() {
1308 let program = parse(r#"{ x = 1 + 2 * 3 }"#).unwrap();
1309 assert_eq!(program.rules.len(), 1);
1310 }
1311
1312 #[test]
1313 fn test_function_def() {
1314 let program = parse(r#"function add(a, b) { return a + b }"#).unwrap();
1315 assert_eq!(program.functions.len(), 1);
1316 assert_eq!(program.functions[0].name, "add");
1317 assert_eq!(program.functions[0].params, vec!["a", "b"]);
1318 }
1319
1320 #[test]
1321 fn test_if_else() {
1322 let program = parse(r#"{ if (x) print 1; else print 2 }"#).unwrap();
1323 assert_eq!(program.rules.len(), 1);
1324 }
1325
1326 #[test]
1327 fn test_while_loop() {
1328 let program = parse(r#"{ while (x < 10) x++ }"#).unwrap();
1329 assert_eq!(program.rules.len(), 1);
1330 }
1331
1332 #[test]
1333 fn test_for_loop() {
1334 let program = parse(r#"{ for (i=0; i<10; i++) print i }"#).unwrap();
1335 assert_eq!(program.rules.len(), 1);
1336 }
1337
1338 #[test]
1339 fn test_for_in_loop() {
1340 let program = parse(r#"{ for (k in a) print k }"#).unwrap();
1341 assert_eq!(program.rules.len(), 1);
1342 }
1343
1344 #[test]
1345 fn test_do_while() {
1346 let program = parse(r#"{ do { x++ } while (x < 10) }"#).unwrap();
1347 assert_eq!(program.rules.len(), 1);
1348 }
1349
1350 #[test]
1351 fn test_delete() {
1352 let program = parse(r#"{ delete a[1] }"#).unwrap();
1353 assert_eq!(program.rules.len(), 1);
1354 }
1355
1356 #[test]
1357 fn test_delete_array() {
1358 let program = parse(r#"{ delete a }"#).unwrap();
1359 assert_eq!(program.rules.len(), 1);
1360 }
1361
1362 #[test]
1363 fn test_break_continue() {
1364 let program = parse(r#"{ break; continue }"#).unwrap();
1365 assert_eq!(program.rules.len(), 1);
1366 }
1367
1368 #[test]
1369 fn test_next_nextfile() {
1370 let program = parse(r#"{ next } { nextfile }"#).unwrap();
1371 assert_eq!(program.rules.len(), 2);
1372 }
1373
1374 #[test]
1375 fn test_exit() {
1376 let program = parse(r#"{ exit 0 }"#).unwrap();
1377 assert_eq!(program.rules.len(), 1);
1378 }
1379
1380 #[test]
1381 fn test_return() {
1382 let program = parse(r#"function f() { return 42 }"#).unwrap();
1383 assert_eq!(program.functions.len(), 1);
1384 }
1385
1386 #[test]
1387 fn test_printf() {
1388 let program = parse(r#"{ printf "%d", x }"#).unwrap();
1389 assert_eq!(program.rules.len(), 1);
1390 }
1391
1392 #[test]
1393 fn test_getline() {
1394 let program = parse(r#"{ getline x < "file" }"#).unwrap();
1395 assert_eq!(program.rules.len(), 1);
1396 }
1397
1398 #[test]
1399 fn test_pipe_getline() {
1400 let program = parse(r#"{ "cmd" | getline x }"#).unwrap();
1401 assert_eq!(program.rules.len(), 1);
1402 }
1403
1404 #[test]
1405 fn test_output_redirect() {
1406 let program = parse(r#"{ print "x" > "file" }"#).unwrap();
1407 assert_eq!(program.rules.len(), 1);
1408 }
1409
1410 #[test]
1411 fn test_output_append() {
1412 let program = parse(r#"{ print "x" >> "file" }"#).unwrap();
1413 assert_eq!(program.rules.len(), 1);
1414 }
1415
1416 #[test]
1417 fn test_output_pipe() {
1418 let program = parse(r#"{ print "x" | "cmd" }"#).unwrap();
1419 assert_eq!(program.rules.len(), 1);
1420 }
1421
1422 #[test]
1423 fn test_ternary() {
1424 let program = parse(r#"{ x = a ? b : c }"#).unwrap();
1425 assert_eq!(program.rules.len(), 1);
1426 }
1427
1428 #[test]
1429 fn test_logical_and_or() {
1430 let program = parse(r#"{ x = a && b || c }"#).unwrap();
1431 assert_eq!(program.rules.len(), 1);
1432 }
1433
1434 #[test]
1435 fn test_array_in() {
1436 let program = parse(r#"{ x = (1 in a) }"#).unwrap();
1437 assert_eq!(program.rules.len(), 1);
1438 }
1439
1440 #[test]
1441 fn test_regex_match() {
1442 let program = parse(r#"{ x = ($0 ~ /foo/) }"#).unwrap();
1443 assert_eq!(program.rules.len(), 1);
1444 }
1445
1446 #[test]
1447 fn test_concatenation() {
1448 let program = parse(r#"{ x = a b c }"#).unwrap();
1449 assert_eq!(program.rules.len(), 1);
1450 }
1451
1452 #[test]
1453 fn test_field_access() {
1454 let program = parse(r#"{ print $1, $NF, $(2+1) }"#).unwrap();
1455 assert_eq!(program.rules.len(), 1);
1456 }
1457
1458 #[test]
1459 fn test_field_unary_operand() {
1460 let program = parse(r#"{ print $-1 }"#).unwrap();
1463 assert_eq!(program.rules.len(), 1);
1464
1465 let program = parse(r#"{ print $+x }"#).unwrap();
1466 assert_eq!(program.rules.len(), 1);
1467
1468 let program = parse(r#"{ print $!x }"#).unwrap();
1469 assert_eq!(program.rules.len(), 1);
1470 }
1471
1472 #[test]
1473 fn test_field_pre_increment_operand() {
1474 let program = parse(r#"{ print $++i }"#).unwrap();
1476 assert_eq!(program.rules.len(), 1);
1477
1478 let program = parse(r#"{ print $--i }"#).unwrap();
1479 assert_eq!(program.rules.len(), 1);
1480 }
1481
1482 #[test]
1483 fn test_nested_field_dollar() {
1484 let program = parse(r#"{ print $$1 }"#).unwrap();
1486 assert_eq!(program.rules.len(), 1);
1487 }
1488
1489 #[test]
1490 fn test_field_post_increment_precedence() {
1491 let program = parse(r#"{ $1++ }"#).unwrap();
1493 let stmt = &program.rules[0].action.as_ref().unwrap().statements[0];
1494 match stmt {
1495 Stmt::Expr(Expr::PostIncrement(inner, _)) => {
1496 assert!(matches!(**inner, Expr::Field(_, _)));
1497 }
1498 other => panic!("expected PostIncrement(Field(..)), got {other:?}"),
1499 }
1500 }
1501
1502 #[test]
1503 fn test_field_binary_precedence() {
1504 let program = parse(r#"{ x = $a + b }"#).unwrap();
1506 assert_eq!(program.rules.len(), 1);
1507 }
1508
1509 #[test]
1510 fn test_array_multi_index() {
1511 let program = parse(r#"{ a[1,2,3] = x }"#).unwrap();
1512 assert_eq!(program.rules.len(), 1);
1513 }
1514
1515 #[test]
1516 fn test_function_call() {
1517 let program = parse(r#"{ x = substr(s, 1, 5) }"#).unwrap();
1518 assert_eq!(program.rules.len(), 1);
1519 }
1520
1521 #[test]
1522 fn test_pre_increment() {
1523 let program = parse(r#"{ ++x; --y }"#).unwrap();
1524 assert_eq!(program.rules.len(), 1);
1525 }
1526
1527 #[test]
1528 fn test_post_increment() {
1529 let program = parse(r#"{ x++; y-- }"#).unwrap();
1530 assert_eq!(program.rules.len(), 1);
1531 }
1532
1533 #[test]
1534 fn test_compound_assign() {
1535 let program = parse(r#"{ x += 1; y -= 1; z *= 2; w /= 2; v %= 3; p ^= 2 }"#).unwrap();
1536 assert_eq!(program.rules.len(), 1);
1537 }
1538
1539 #[test]
1540 fn test_range_pattern() {
1541 let program = parse(r#"/start/,/end/ { print }"#).unwrap();
1542 assert_eq!(program.rules.len(), 1);
1543 assert!(matches!(
1544 &program.rules[0].pattern,
1545 Some(Pattern::Range { .. })
1546 ));
1547 }
1548
1549 #[test]
1550 fn test_expression_pattern() {
1551 let program = parse(r#"NR > 5 { print }"#).unwrap();
1552 assert_eq!(program.rules.len(), 1);
1553 }
1554
1555 #[test]
1556 fn test_beginfile_endfile() {
1557 let program = parse(r#"BEGINFILE { x = 1 } ENDFILE { print }"#).unwrap();
1558 assert_eq!(program.rules.len(), 2);
1559 assert!(matches!(program.rules[0].pattern, Some(Pattern::BeginFile)));
1560 assert!(matches!(program.rules[1].pattern, Some(Pattern::EndFile)));
1561 }
1562
1563 #[test]
1564 fn test_empty_statement() {
1565 let program = parse(r#"{ ; ; ; }"#).unwrap();
1566 assert_eq!(program.rules.len(), 1);
1567 }
1568
1569 #[test]
1570 fn test_block_statement() {
1571 let program = parse(r#"{ { { x = 1 } } }"#).unwrap();
1572 assert_eq!(program.rules.len(), 1);
1573 }
1574
1575 #[test]
1576 fn test_multiple_rules() {
1577 let program = parse(r#"BEGIN { } { } END { }"#).unwrap();
1578 assert_eq!(program.rules.len(), 3);
1579 }
1580
1581 #[test]
1582 fn test_parenthesized_expression() {
1583 let program = parse(r#"{ x = (1 + 2) * 3 }"#).unwrap();
1584 assert_eq!(program.rules.len(), 1);
1585 }
1586
1587 #[test]
1588 fn test_unary_ops() {
1589 let program = parse(r#"{ x = -a + +b }"#).unwrap();
1590 assert_eq!(program.rules.len(), 1);
1591 }
1592
1593 #[test]
1594 fn test_not_operator() {
1595 let program = parse(r#"{ x = !a }"#).unwrap();
1596 assert_eq!(program.rules.len(), 1);
1597 }
1598
1599 #[test]
1600 fn test_comparison_ops() {
1601 let program =
1602 parse(r#"{ x = a < b && b <= c && c > d && d >= e && e == f && f != g }"#).unwrap();
1603 assert_eq!(program.rules.len(), 1);
1604 }
1605
1606 #[test]
1607 fn test_exponentiation() {
1608 let program = parse(r#"{ x = 2^3^4 }"#).unwrap(); assert_eq!(program.rules.len(), 1);
1610 }
1611}