Refactor statement module tree
This commit is contained in:
parent
fc5a50227f
commit
e4e0eb322e
10 changed files with 151 additions and 130 deletions
|
@ -1,5 +1,5 @@
|
||||||
use super::ast_parser_iter::ParserIter;
|
use super::ast_parser_iter::ParserIter;
|
||||||
use super::statement::statement_node;
|
use super::statement;
|
||||||
use crate::error::ErrorLocationWrapper;
|
use crate::error::ErrorLocationWrapper;
|
||||||
use crate::lexer::{token, token::TokenType};
|
use crate::lexer::{token, token::TokenType};
|
||||||
use std::result::Result as StdResult;
|
use std::result::Result as StdResult;
|
||||||
|
@ -29,7 +29,7 @@ pub struct Parser<'a, T: Iterator<Item = token::Token<'a>>> {
|
||||||
pub(super) token_iter: super::ast_parser_iter::ParserIter<T>,
|
pub(super) token_iter: super::ast_parser_iter::ParserIter<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ParseAllResult = StdResult<Vec<statement_node::Statement>, Vec<ASTParsingError>>;
|
pub type ParseAllResult = StdResult<Vec<statement::Statement>, Vec<ASTParsingError>>;
|
||||||
|
|
||||||
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
|
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
|
||||||
pub fn new(iter: T) -> Parser<'a, T> {
|
pub fn new(iter: T) -> Parser<'a, T> {
|
||||||
|
|
28
src/ast/statement/expression_statement.rs
Normal file
28
src/ast/statement/expression_statement.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
use crate::{
|
||||||
|
ast::expression::expression_node::ExpressionNode,
|
||||||
|
ast::parser::{InnerASTParsingError, Parser, Result},
|
||||||
|
lexer::token::{self, TokenType},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::Statement;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ExpressionStatement(pub ExpressionNode);
|
||||||
|
impl ExpressionStatement {
|
||||||
|
pub fn new(expr: ExpressionNode) -> Self {
|
||||||
|
Self(expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
|
||||||
|
pub 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +1,37 @@
|
||||||
pub mod statement_node;
|
use crate::lexer::token;
|
||||||
mod statement_parser;
|
|
||||||
|
use super::parser::{InnerASTParsingError, Parser, Result};
|
||||||
|
|
||||||
|
mod expression_statement;
|
||||||
|
mod print_statement;
|
||||||
|
mod variable_assignment_statement;
|
||||||
|
|
||||||
|
pub use expression_statement::ExpressionStatement;
|
||||||
|
pub use print_statement::PrintStatement;
|
||||||
|
pub use variable_assignment_statement::VariableAssignmentStatement;
|
||||||
|
|
||||||
|
use from_variants::FromVariants;
|
||||||
|
|
||||||
|
#[derive(FromVariants, Debug)]
|
||||||
|
pub enum Statement {
|
||||||
|
Expression(ExpressionStatement),
|
||||||
|
Print(PrintStatement),
|
||||||
|
VariableAssignment(VariableAssignmentStatement),
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! all_variants {
|
||||||
|
($expr:expr, $val_name:ident => $expr_arm:expr) => {
|
||||||
|
{
|
||||||
|
use match_any::match_any;
|
||||||
|
use $crate::ast::statement::*;
|
||||||
|
match_any!($expr, Statement::Expression($val_name) | Statement::Print($val_name) | Statement::VariableAssignment($val_name) => $expr_arm)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub(crate) use all_variants;
|
||||||
|
|
||||||
|
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
|
||||||
|
pub fn statement(&mut self) -> Result<Statement> {
|
||||||
|
self.print_statement()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
32
src/ast/statement/print_statement.rs
Normal file
32
src/ast/statement/print_statement.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
use itertools::PeekingNext;
|
||||||
|
|
||||||
|
use super::{InnerASTParsingError, Parser, Result, Statement};
|
||||||
|
use crate::ast::expression::expression_node::ExpressionNode;
|
||||||
|
use crate::lexer::token::{self, Token};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PrintStatement(pub ExpressionNode);
|
||||||
|
impl PrintStatement {
|
||||||
|
pub fn new(expr: ExpressionNode) -> Self {
|
||||||
|
Self(expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
|
||||||
|
pub(super) 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,48 +0,0 @@
|
||||||
use crate::ast::expression::expression_node::ExpressionNode;
|
|
||||||
use from_variants::FromVariants;
|
|
||||||
|
|
||||||
#[derive(FromVariants, Debug)]
|
|
||||||
pub enum Statement {
|
|
||||||
Expression(ExpressionStatement),
|
|
||||||
Print(PrintStatement),
|
|
||||||
VariableAssignment(VariableAssignmentStatement),
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! all_variants {
|
|
||||||
($expr:expr, $val_name:ident => $expr_arm:expr) => {
|
|
||||||
{
|
|
||||||
use match_any::match_any;
|
|
||||||
use $crate::ast::statement::statement_node::*;
|
|
||||||
match_any!($expr, Statement::Expression($val_name) | Statement::Print($val_name) | Statement::VariableAssignment($val_name) => $expr_arm)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
pub(crate) use all_variants;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct ExpressionStatement(pub ExpressionNode);
|
|
||||||
impl ExpressionStatement {
|
|
||||||
pub fn new(expr: ExpressionNode) -> Self {
|
|
||||||
Self(expr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct PrintStatement(pub ExpressionNode);
|
|
||||||
impl PrintStatement {
|
|
||||||
pub fn new(expr: ExpressionNode) -> Self {
|
|
||||||
Self(expr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct VariableAssignmentStatement {
|
|
||||||
pub var_name: String,
|
|
||||||
pub node: ExpressionNode,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VariableAssignmentStatement {
|
|
||||||
pub fn new(var_name: String, node: ExpressionNode) -> Self {
|
|
||||||
Self { var_name, node }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
44
src/ast/statement/variable_assignment_statement.rs
Normal file
44
src/ast/statement/variable_assignment_statement.rs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
use super::Statement;
|
||||||
|
use super::{InnerASTParsingError, Parser, Result};
|
||||||
|
use crate::ast::expression::expression_node::ExpressionNode;
|
||||||
|
use crate::lexer::token::{self, TokenType};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct VariableAssignmentStatement {
|
||||||
|
pub var_name: String,
|
||||||
|
pub node: ExpressionNode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VariableAssignmentStatement {
|
||||||
|
pub fn new(var_name: String, node: ExpressionNode) -> Self {
|
||||||
|
Self { var_name, node }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
|
||||||
|
pub(super) 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,15 @@
|
||||||
use super::Interpret;
|
use super::Interpret;
|
||||||
use super::{types::Value, RuntimeError};
|
use super::{types::Value, RuntimeError};
|
||||||
use crate::ast::statement::statement_node;
|
use crate::ast::statement;
|
||||||
use crate::interpreter::world::World;
|
use crate::interpreter::world::World;
|
||||||
|
|
||||||
impl Interpret for statement_node::Statement {
|
impl Interpret for statement::Statement {
|
||||||
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
||||||
statement_node::all_variants!(self, n => n.interpret(w))
|
statement::all_variants!(self, n => n.interpret(w))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpret for statement_node::PrintStatement {
|
impl Interpret for statement::PrintStatement {
|
||||||
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
||||||
let res = self.0.interpret(w)?;
|
let res = self.0.interpret(w)?;
|
||||||
println!("{:?}", res);
|
println!("{:?}", res);
|
||||||
|
@ -17,13 +17,13 @@ impl Interpret for statement_node::PrintStatement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpret for statement_node::ExpressionStatement {
|
impl Interpret for statement::ExpressionStatement {
|
||||||
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
||||||
self.0.interpret(w)
|
self.0.interpret(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpret for statement_node::VariableAssignmentStatement {
|
impl Interpret for statement::VariableAssignmentStatement {
|
||||||
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
||||||
let expr_val = self.node.interpret(w)?;
|
let expr_val = self.node.interpret(w)?;
|
||||||
// Clone for now, later this will use a GC and won't need to clone
|
// Clone for now, later this will use a GC and won't need to clone
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::ast::statement::statement_node::Statement;
|
use crate::ast::statement::Statement;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
ast_walker::{Interpret, RuntimeError},
|
ast_walker::{Interpret, RuntimeError},
|
||||||
|
|
|
@ -5,7 +5,7 @@ pub mod interpreter;
|
||||||
pub mod lexer;
|
pub mod lexer;
|
||||||
|
|
||||||
use ast::parser::ParseAllResult;
|
use ast::parser::ParseAllResult;
|
||||||
use ast::statement::statement_node::Statement;
|
use ast::statement::Statement;
|
||||||
use interpreter::ast_walker::{Interpret, RuntimeError};
|
use interpreter::ast_walker::{Interpret, RuntimeError};
|
||||||
use interpreter::types::Value;
|
use interpreter::types::Value;
|
||||||
use interpreter::world::World;
|
use interpreter::world::World;
|
||||||
|
|
Loading…
Reference in a new issue