From 3a5d81c8fba159386ce3599763e50eaed967a77a Mon Sep 17 00:00:00 2001 From: bad Date: Sat, 23 Apr 2022 16:27:11 +0200 Subject: [PATCH] Statement parsing --- src/ast/astnode.rs | 0 src/ast/mod.rs | 1 + src/ast/parser.rs | 31 ++++++++-------- src/ast/statement/mod.rs | 2 + src/ast/statement/statement_node.rs | 24 ++++++++++++ src/ast/statement/statement_parser.rs | 37 +++++++++++++++++++ .../expression_interpreter.rs} | 17 +-------- src/interpreter/ast_walker/mod.rs | 7 ++++ src/interpreter/error.rs | 11 ++++++ src/interpreter/mod.rs | 1 + src/lexer/mod.rs | 22 +++++------ src/lexer/token.rs | 1 + src/lib.rs | 15 +++++--- 13 files changed, 122 insertions(+), 47 deletions(-) delete mode 100644 src/ast/astnode.rs create mode 100644 src/ast/statement/mod.rs create mode 100644 src/ast/statement/statement_node.rs create mode 100644 src/ast/statement/statement_parser.rs rename src/interpreter/{ast_walker.rs => ast_walker/expression_interpreter.rs} (82%) create mode 100644 src/interpreter/ast_walker/mod.rs create mode 100644 src/interpreter/error.rs diff --git a/src/ast/astnode.rs b/src/ast/astnode.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 19d7ea5..38850b6 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1,2 +1,3 @@ pub mod expression; +pub mod statement; pub mod parser; diff --git a/src/ast/parser.rs b/src/ast/parser.rs index ba879a2..4e0337b 100644 --- a/src/ast/parser.rs +++ b/src/ast/parser.rs @@ -1,4 +1,5 @@ use super::expression::expression_node; +use super::statement::statement_node; use crate::error::ErrorLocationWrapper; use crate::lexer::{token, token::TokenType}; @@ -28,32 +29,30 @@ pub struct Parser<'a, T: Iterator>> { pub(super) token_iter: iter::Peekable, } +pub type ParseAllResult = StdResult, Vec>; + impl<'a, T: Iterator>> Parser<'a, T> { pub fn new(iter: T) -> Parser<'a, T> { Parser { token_iter: iter.peekable(), } } - pub fn parse_all( - &mut self, - ) -> StdResult, Vec> { - let mut tokens = Vec::new(); - let mut errors = Vec::new(); + pub fn parse_all(&mut self) -> ParseAllResult { + let mut res = Ok(Vec::new()); - while self.token_iter.peek().is_some() { - match self.expression() { - Ok(token) => { - if errors.is_empty() { - tokens.push(token) + while !matches!(self.token_iter.peek().unwrap().token_type, token::TokenType::Eof) { + match self.statement() { + Ok(s) => { + if let Ok(ref mut v) = res { + v.push(s) } } - Err(e) => errors.push(e), + Err(e) => match res { + Ok(_) => res = Err(vec![e]), + Err(ref mut v) => v.push(e), + }, } } - if errors.is_empty() { - Ok(tokens) - } else { - Err(errors) - } + res } } diff --git a/src/ast/statement/mod.rs b/src/ast/statement/mod.rs new file mode 100644 index 0000000..0306a3d --- /dev/null +++ b/src/ast/statement/mod.rs @@ -0,0 +1,2 @@ +pub mod statement_node; +mod statement_parser; diff --git a/src/ast/statement/statement_node.rs b/src/ast/statement/statement_node.rs new file mode 100644 index 0000000..41b9450 --- /dev/null +++ b/src/ast/statement/statement_node.rs @@ -0,0 +1,24 @@ +use crate::ast::expression::expression_node::ExpressionNode; +use from_variants::FromVariants; + +#[derive(FromVariants, Debug)] +pub enum Statement { + Expression(ExpressionStatement), + Print(PrintStatement), +} + +#[derive(Debug)] +pub struct ExpressionStatement(ExpressionNode); +impl ExpressionStatement { + pub fn new(expr: ExpressionNode) -> Self { + Self(expr) + } +} + +#[derive(Debug)] +pub struct PrintStatement(ExpressionNode); +impl PrintStatement { + pub fn new(expr: ExpressionNode) -> Self { + Self(expr) + } +} diff --git a/src/ast/statement/statement_parser.rs b/src/ast/statement/statement_parser.rs new file mode 100644 index 0000000..cbacce9 --- /dev/null +++ b/src/ast/statement/statement_parser.rs @@ -0,0 +1,37 @@ +use super::statement_node::{ExpressionStatement, Statement, PrintStatement}; +use crate::{ + ast::parser::{ASTParsingError, Parser, Result}, + lexer::token, +}; + +impl<'a, T: Iterator>> Parser<'a, T> { + pub fn statement(&mut self) -> Result { + if let Some(_) = self + .token_iter + .next_if(|t| matches!(t.token_type, token::TokenType::Print)) + { + self.print_statement() + } else { + self.expression_statement() + } + } + fn print_statement(&mut self) -> Result { + let expr = self.expression()?; + if let token::TokenType::Semicolon = self.token_iter.peek().unwrap().token_type { + self.token_iter.next(); + Ok(PrintStatement::new(expr).into()) + } else { + panic!(); + } + } + + fn expression_statement(&mut self) -> Result { + let expr = self.expression()?; + if let token::TokenType::Semicolon = self.token_iter.peek().unwrap().token_type { + self.token_iter.next(); + Ok(ExpressionStatement::new(expr).into()) + } else { + panic!(); + } + } +} diff --git a/src/interpreter/ast_walker.rs b/src/interpreter/ast_walker/expression_interpreter.rs similarity index 82% rename from src/interpreter/ast_walker.rs rename to src/interpreter/ast_walker/expression_interpreter.rs index 3a44cb4..cbc4193 100644 --- a/src/interpreter/ast_walker.rs +++ b/src/interpreter/ast_walker/expression_interpreter.rs @@ -1,21 +1,8 @@ -use std::fmt::Display; - -use super::types::Value; +use super::{RuntimeError, types::Value}; +use super::Interpret; use crate::ast::expression::expression_node; -#[derive(Debug)] -pub struct RuntimeError; -impl Display for RuntimeError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "A runtime error occured") - } -} -impl std::error::Error for RuntimeError {} - -pub trait Interpret { - fn interpret(&self) -> Result; -} impl Interpret for expression_node::ExpressionNode { fn interpret(&self) -> Result { diff --git a/src/interpreter/ast_walker/mod.rs b/src/interpreter/ast_walker/mod.rs new file mode 100644 index 0000000..d3e147d --- /dev/null +++ b/src/interpreter/ast_walker/mod.rs @@ -0,0 +1,7 @@ +mod expression_interpreter; +pub use super::{error::RuntimeError, types}; +use super::types::Value; + +pub trait Interpret { + fn interpret(&self) -> Result; +} diff --git a/src/interpreter/error.rs b/src/interpreter/error.rs new file mode 100644 index 0000000..fcde548 --- /dev/null +++ b/src/interpreter/error.rs @@ -0,0 +1,11 @@ +use std::fmt::Display; + +#[derive(Debug)] +pub struct RuntimeError; + +impl Display for RuntimeError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "A runtime error occured") + } +} +impl std::error::Error for RuntimeError {} diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 4c63f96..8764f40 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -1,2 +1,3 @@ pub mod ast_walker; pub mod types; +pub mod error; diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index f50abfb..c8a9e96 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -25,26 +25,26 @@ impl<'a, 'b> Lexer<'a, 'b> { } pub fn scan_tokens(&mut self) -> Result>, Vec> { - let mut tokens = Vec::new(); - let mut errors = Vec::new(); + let mut res = Ok(Vec::new()); while self.source_iter.peek().is_some() { match self.scan_token() { - Ok(Some(token)) => { - if errors.is_empty() { - tokens.push(token) - } + Ok(Some(token)) => if let Ok(ref mut v) = res { + v.push(token) } Ok(None) => (), - Err(e) => errors.push(e), + Err(e) => match res { + Ok(_) => res = Err(vec![e]), + Err(ref mut v) => v.push(e) + } } } - if errors.is_empty() { - Ok(tokens) - } else { - Err(errors) + if let Ok(ref mut v) = res { + v.push(self.get_token(token::TokenType::Eof)); } + + res } fn get_token(&self, token_type: token::TokenType) -> token::Token<'b> { diff --git a/src/lexer/token.rs b/src/lexer/token.rs index 7aa7479..ca834d2 100644 --- a/src/lexer/token.rs +++ b/src/lexer/token.rs @@ -47,4 +47,5 @@ pub enum TokenType { True, Let, While, + Eof, } diff --git a/src/lib.rs b/src/lib.rs index e02453f..f917a99 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,8 +3,8 @@ pub mod error; pub mod interpreter; pub mod lexer; -use ast::expression::expression_node::ExpressionNode; -use ast::parser::ASTParsingError; +use ast::parser::ParseAllResult; +use ast::statement::statement_node::Statement; use interpreter::ast_walker::{Interpret, RuntimeError}; use interpreter::types::Value; use lexer::{token::Token, Lexer, LexingError}; @@ -17,13 +17,18 @@ pub fn lex<'a, 'b>( lexer.scan_tokens() } -pub fn parse(tokens: Vec) -> Result, Vec> { +pub fn parse(tokens: Vec) -> ParseAllResult { let mut parser = crate::ast::parser::Parser::new(tokens.into_iter()); parser.parse_all() } -pub fn exec(nodes: Vec) -> Result { - nodes[0].interpret() +pub fn exec(nodes: Vec) -> Result { + todo!(); + /* + for statement in nodes { + //statement.interpret()?; + } + */ } pub fn run(code: &str) -> Result {