mod expression; mod macros; use crate::{ ast, expect_any_keyword, expect_identifier, expect_keyword, expect_token, match_token, peek_keyword, peek_match, token::{KeywordKind, Token, TokenKind}, }; pub struct Parser { tokens: Vec, current: usize, } impl Parser { pub fn new(tokens: Vec) -> Parser { let tokens = tokens .into_iter() .filter(|t| !matches!(t.kind, TokenKind::NewLine)) .collect::>(); Self { tokens, current: 0 } } pub fn module(&mut self) -> ast::Module { let mut statements = Vec::new(); while !match_token!(self, TokenKind::EndOfFile) { let s = self.statement(); println!("Parsed Statement {s:?}"); statements.push(s); } ast::Module { statements } } fn statement(&mut self) -> ast::Statement { if peek_keyword!(self, KeywordKind::function) { return self.function_declaration(); } self.expression_statement() } fn function_declaration(&mut self) -> ast::Statement { expect_keyword!(self, KeywordKind::function); let id = expect_identifier!(self); expect_token!(self, TokenKind::LeftParen, "LeftParen"); let mut parameters = Vec::new(); while peek_match!(self, TokenKind::Identifier(_)) { let name = expect_identifier!(self); expect_token!(self, TokenKind::Colon, "Colon"); let typename = expect_any_keyword!(self); let parameter = ast::ParameterDeclaration { name: name.clone(), typename: typename.clone(), }; parameters.push(parameter); } expect_token!(self, TokenKind::RightParen, "RightParen"); expect_token!(self, TokenKind::LeftCurly, "LeftCurly"); let mut statements = Vec::new(); while !peek_match!(self, TokenKind::RightCurly) { let statement = self.statement(); statements.push(statement); } expect_token!(self, TokenKind::RightCurly, "RightCurly"); ast::Statement::FunctionDeclaration { name: id.clone(), parameters, statements, } } fn expression_statement(&mut self) -> ast::Statement { let e = self.expression(); expect_token!(self, TokenKind::Semicolon, "Semicolon"); ast::Statement::Expression(e) } } impl Parser { fn peek(&self) -> Option<&Token> { self.tokens.get(self.current) } fn consume(&mut self) -> Option { let token = self.peek().cloned(); self.current += 1; token } }