1use crate::{
2 Lexer, Program,
3 ast::{Action, Item, Statement},
4 token::{Token, TokenKind},
5};
6
7#[derive(Debug)]
8pub struct Parser<'a> {
9 lexer: Lexer<'a>,
10 current_token: Token<'a>,
11 peek_token: Token<'a>,
12}
13
14impl<'a> Parser<'a> {
15 pub fn new(mut lexer: Lexer<'a>) -> Self {
16 let current_token = lexer.next_token();
17 let peek_token = lexer.next_token();
18
19 Parser {
20 lexer,
21 current_token,
22 peek_token,
23 }
24 }
25
26 fn next_token(&mut self) {
27 self.current_token = self.peek_token.clone();
28 self.peek_token = self.lexer.next_token();
29 }
30
31 fn is_eof(&self) -> bool {
32 self.current_token.kind == TokenKind::Eof
33 }
34
35 fn parse_next_item(&mut self) -> Option<Item<'a>> {
36 match &self.current_token.kind {
37 TokenKind::Begin => {
38 self.next_token();
39 match self.parse_action() {
40 Item::Action(action) => Some(Item::Begin(action)),
41 _ => panic!("Expected action after BEGIN"),
42 }
43 }
44 TokenKind::NewLine => {
45 self.next_token();
46 self.parse_next_item()
47 }
48 TokenKind::Eof => None,
49 TokenKind::LeftCurlyBrace => Some(self.parse_action()),
50 _ => panic!(
51 "parse_next_item not yet implemented, found token: {:?}",
52 self.current_token
53 ),
54 }
55 }
56
57 fn parse_action(&mut self) -> Item<'a> {
58 self.next_token(); let pattern = None;
61
62 let mut statements = Vec::new();
63 while self.current_token.kind == TokenKind::NewLine {
64 self.next_token();
65 }
66 if self.current_token.kind == TokenKind::Print {
67 statements.push(Statement::Print(vec![]));
68 }
69
70 while self.current_token.kind != TokenKind::RightCurlyBrace
71 && self.current_token.kind != TokenKind::Eof
72 {
73 self.next_token();
74 }
75
76 if pattern.is_some() {
77 Item::PatternAction {
78 pattern,
79 action: Some(Action { statements }),
80 }
81 } else {
82 Item::Action(Action { statements })
83 }
84 }
85
86 pub fn parse_program(&mut self) -> Program<'_> {
87 let mut program = Program::new();
88
89 while !self.is_eof() {
90 match self.parse_next_item() {
91 Some(Item::Begin(action)) => program.add_begin_block(Item::Begin(action)),
92 Some(item) => program.add_item(item),
93 None => {}
94 }
95 self.next_token();
96 }
97
98 program
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn create_parser() {
108 let parser = Parser::new(Lexer::new("42 == 42"));
109
110 assert_eq!(parser.current_token.literal, "42");
111 assert_eq!(parser.peek_token.literal, "==");
112 }
113
114 #[test]
115 fn parse_empty_program() {
116 let mut parser = Parser::new(Lexer::new(""));
117
118 let program = parser.parse_program();
119
120 assert_eq!(program.len(), 0);
121 }
122
123 #[test]
124 fn parse_action_without_pattern() {
125 let mut parser = Parser::new(Lexer::new("{ print }"));
126
127 let program = parser.parse_program();
128
129 assert_eq!(program.len(), 1);
130 assert_eq!("{ print }", program.to_string());
131 }
132
133 #[test]
134 fn parse_action_with_leading_newlines() {
135 let mut parser = Parser::new(Lexer::new("\n\n{ print }"));
136
137 let program = parser.parse_program();
138
139 assert_eq!(program.len(), 1);
140 assert_eq!("{ print }", program.to_string());
141 }
142
143 #[test]
144 fn parse_begin_block() {
145 let mut parser = Parser::new(Lexer::new("BEGIN { print }"));
146
147 let program = parser.parse_program();
148
149 assert_eq!(program.len(), 1);
150 assert_eq!("BEGIN { print }", program.to_string());
151 }
152}