crftng-intrprtrs/src/ast/statement/statement_parser.rs

71 lines
2.0 KiB
Rust

use itertools::PeekingNext;
use super::statement_node::{ExpressionStatement, PrintStatement, Statement};
use crate::{
ast::{
parser::{InnerASTParsingError, Parser, Result},
statement::statement_node::VariableAssignmentStatement,
},
lexer::token::{self, Token, TokenType},
};
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
pub fn statement(&mut self) -> Result<Statement> {
self.print_statement()
}
fn print_statement(&mut self) -> Result<Statement> {
if let Some(Token { location: loc, .. }) = self
.token_iter
.peeking_next(|t| matches!(t.token_type, token::TokenType::Print))
{
let expr = self.expression()?;
if let token::TokenType::Semicolon = self.token_iter.peek().token_type {
self.token_iter.next();
Ok(PrintStatement::new(expr).into())
} else {
Err(loc.wrap(InnerASTParsingError::ExpectedSemi))
}
} else {
self.variable_assignment_statement()
}
}
fn variable_assignment_statement(&mut self) -> Result<Statement> {
if matches!(
self.token_iter.peek_nth(0).token_type,
TokenType::Identifier(_)
) && matches!(self.token_iter.peek_nth(1).token_type, TokenType::Equal)
{
let ident = if let TokenType::Identifier(ident) = self.token_iter.next().token_type {
ident
} else {
unreachable!()
};
self.token_iter.next();
let expr = self.expression()?;
let token = self.token_iter.peek();
if let token::TokenType::Semicolon = token.token_type {
self.token_iter.next();
Ok(VariableAssignmentStatement::new(ident, expr).into())
} else {
Err(token.location.wrap(InnerASTParsingError::ExpectedSemi))
}
} else {
self.expression_statement()
}
}
fn expression_statement(&mut self) -> Result<Statement> {
let expr = self.expression()?;
let token = self.token_iter.peek();
if let TokenType::Semicolon = token.token_type {
self.token_iter.next();
Ok(ExpressionStatement::new(expr).into())
} else {
Err(token.location.wrap(InnerASTParsingError::ExpectedSemi))
}
}
}