use super::stream::TokenStream;
use crate::core::*;
use crate::lexer::Token;
use crate::trace;
use anyhow::Result;
pub struct Parser;
impl Parser {
pub fn parse_str(source: &str) -> Result<Program> {
let tokens = crate::lexer::Lexer::tokenize(source)?;
Self::parse(tokens)
}
pub fn parse(tokens: Vec<Token>) -> Result<Program> {
let mut stream = TokenStream::new(tokens);
stream.parse(parse_program)
}
}
fn parse_program(s: &mut TokenStream) -> Result<Program> {
trace!("parse_program: starting");
let mut statements = Vec::new();
while !s.is_at_end() {
trace!(
"parse_program: parsing statement at position {} ({})",
s.position(),
s.current_token_info()
);
if let Some(stmt) = s.try_parse(try_parse_statement)? {
statements.push(stmt);
} else {
if let Some(final_expr) = s.try_parse(parse_final_expression)? {
statements.push(Statement::Expression(final_expr));
break;
} else {
return Err(parse_statement(s).unwrap_err());
}
}
}
trace!("parse_program: parsed {} statements", statements.len());
Ok(Program(statements))
}
fn parse_statement(s: &mut TokenStream) -> Result<Statement> {
super::statement::parse_statement(s)
}
fn try_parse_statement(s: &mut TokenStream) -> Result<Option<Statement>> {
match parse_statement(s) {
Ok(stmt) => Ok(Some(stmt)),
Err(_) => Ok(None),
}
}
fn parse_final_expression(s: &mut TokenStream) -> Result<Option<Expression>> {
use crate::lexer::TokenType;
let expr = match super::expression::parse_expression(s) {
Ok(expr) => expr,
Err(_) => return Ok(None),
};
if s.is_at_end() {
Ok(Some(expr))
} else if s.peek_type() == TokenType::Semicolon {
Ok(None)
} else {
Ok(None)
}
}