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::Eof => None,
38            TokenKind::LeftCurlyBrace => Some(self.parse_action()),
39            _ => panic!(
40                "parse_next_item not yet implemented, found token: {:?}",
41                self.current_token
42            ),
43        }
44    }
45
46    fn parse_action(&mut self) -> Item<'a> {
47        self.next_token(); // consume '{'
48
49        let mut statements = Vec::new();
50        if self.current_token.kind == TokenKind::Print {
51            statements.push(Statement::Print(vec![]));
52        }
53
54        while self.current_token.kind != TokenKind::RightCurlyBrace
55            && self.current_token.kind != TokenKind::Eof
56        {
57            self.next_token();
58        }
59
60        Item::PatternAction {
61            pattern: None,
62            action: Some(Action { statements }),
63        }
64    }
65
66    pub fn parse_program(&mut self) -> Program<'_> {
67        let mut program = Program::new();
68
69        while !self.is_eof() {
70            match self.parse_next_item() {
71                Some(item) => program.add_item(item),
72                None => {}
73            }
74            self.next_token();
75        }
76
77        program
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn create_parser() {
87        let parser = Parser::new(Lexer::new("42 == 42"));
88
89        assert_eq!(parser.current_token.literal, "42");
90        assert_eq!(parser.peek_token.literal, "==");
91    }
92
93    #[test]
94    fn parse_empty_program() {
95        let mut parser = Parser::new(Lexer::new(""));
96
97        let program = parser.parse_program();
98
99        assert_eq!(program.len(), 0);
100    }
101
102    #[test]
103    fn parse_action_without_pattern() {
104        let mut parser = Parser::new(Lexer::new("{ print }"));
105
106        let program = parser.parse_program();
107
108        assert_eq!(program.len(), 1);
109        assert_eq!("{ print }", program.to_string());
110    }
111}