rawk_core/
parser.rs

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(); // consume '{'
59
60        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}