pub mod parsed_statement; #[cfg(test)] mod parser_tests; use super::lexer::lex_tokens::{LexToken, TokenType}; use crate::logger::messages::Message; use crate::parsing::parser::parsed_statement::ParsedStatement; use crate::span::Span; use itertools::{Itertools, MultiPeek}; struct ParseReader<'a> { tokens: MultiPeek>, } impl<'a> ParseReader<'a> { pub fn peek(&mut self) -> &LexToken { let t = self.tokens.peek(); match t { None => self.tokens.by_ref().last().unwrap(), Some(v) => { if v.token_type == TokenType::WhiteSpace { self.peek() } else { v } } } } pub fn next(&mut self) -> &LexToken { let t = self.tokens.next(); match t { None => self.tokens.by_ref().last().unwrap(), Some(v) => { if v.token_type == TokenType::WhiteSpace { self.next() } else { v } } } } pub fn consume( &mut self, expected: TokenType, log: &mut dyn FnMut(Message, Span), ) -> &LexToken { let n = self.next(); if n.token_type != expected { log( Message::UnexpectedToken { expected: vec![expected], found: n.token_type.clone(), }, n.span, ); } n } #[inline(always)] pub fn reset_peek(&mut self) { self.tokens.reset_peek(); } } pub fn parse(tokens: Vec, log: &mut dyn FnMut(Message, Span)) -> Box { let mut reader = ParseReader { tokens: tokens.iter().multipeek(), }; parse_script(&mut reader, log) } fn parse_script( reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Box { let mut vec: Vec> = Vec::new(); loop { let n = reader.peek(); match n.token_type { TokenType::NamespaceKeyword => { vec.push(parse_namespace(reader, log)); } TokenType::EndOfFile => break, _ => { // Log error? } } } Box::new(ParsedStatement::Script(vec)) } fn parse_namespace( reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Box { reader.next(); // Consume namespace let identifier_token = reader.next(); let s: String; match &identifier_token.token_type { TokenType::Identifier(i) => { s = i.to_string(); } _ => { log( Message::UnexpectedToken { found: identifier_token.token_type.clone(), expected: vec![TokenType::Identifier(String::new())], }, identifier_token.span, ); return Box::new(ParsedStatement::Invalid); } } reader.consume(TokenType::OpenCurlyBracket, log); let script = parse_script(reader, log); reader.consume(TokenType::CloseCurlyBracket, log); Box::new(ParsedStatement::Namespace(s, script)) }