123 lines
3.2 KiB
Rust
123 lines
3.2 KiB
Rust
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<core::slice::Iter<'a, LexToken>>,
|
|
}
|
|
|
|
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<LexToken>, log: &mut dyn FnMut(Message, Span)) -> Box<ParsedStatement> {
|
|
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<ParsedStatement> {
|
|
let mut vec: Vec<Box<ParsedStatement>> = 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<ParsedStatement> {
|
|
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))
|
|
}
|