Statement parsing
This commit is contained in:
parent
91f2a945c5
commit
3a5d81c8fb
13 changed files with 122 additions and 47 deletions
|
@ -1,2 +1,3 @@
|
|||
pub mod expression;
|
||||
pub mod statement;
|
||||
pub mod parser;
|
||||
|
|
|
@ -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<Item = token::Token<'a>>> {
|
|||
pub(super) token_iter: iter::Peekable<T>,
|
||||
}
|
||||
|
||||
pub type ParseAllResult = StdResult<Vec<statement_node::Statement>, Vec<ASTParsingError>>;
|
||||
|
||||
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
|
||||
pub fn new(iter: T) -> Parser<'a, T> {
|
||||
Parser {
|
||||
token_iter: iter.peekable(),
|
||||
}
|
||||
}
|
||||
pub fn parse_all(
|
||||
&mut self,
|
||||
) -> StdResult<Vec<expression_node::ExpressionNode>, Vec<ASTParsingError>> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
2
src/ast/statement/mod.rs
Normal file
2
src/ast/statement/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod statement_node;
|
||||
mod statement_parser;
|
24
src/ast/statement/statement_node.rs
Normal file
24
src/ast/statement/statement_node.rs
Normal file
|
@ -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)
|
||||
}
|
||||
}
|
37
src/ast/statement/statement_parser.rs
Normal file
37
src/ast/statement/statement_parser.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
use super::statement_node::{ExpressionStatement, Statement, PrintStatement};
|
||||
use crate::{
|
||||
ast::parser::{ASTParsingError, Parser, Result},
|
||||
lexer::token,
|
||||
};
|
||||
|
||||
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
|
||||
pub fn statement(&mut self) -> Result<Statement> {
|
||||
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<Statement> {
|
||||
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<Statement> {
|
||||
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!();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<Value, RuntimeError>;
|
||||
}
|
||||
|
||||
impl Interpret for expression_node::ExpressionNode {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
7
src/interpreter/ast_walker/mod.rs
Normal file
7
src/interpreter/ast_walker/mod.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
mod expression_interpreter;
|
||||
pub use super::{error::RuntimeError, types};
|
||||
use super::types::Value;
|
||||
|
||||
pub trait Interpret {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError>;
|
||||
}
|
11
src/interpreter/error.rs
Normal file
11
src/interpreter/error.rs
Normal file
|
@ -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 {}
|
|
@ -1,2 +1,3 @@
|
|||
pub mod ast_walker;
|
||||
pub mod types;
|
||||
pub mod error;
|
||||
|
|
|
@ -25,26 +25,26 @@ impl<'a, 'b> Lexer<'a, 'b> {
|
|||
}
|
||||
|
||||
pub fn scan_tokens(&mut self) -> Result<Vec<token::Token<'b>>, Vec<LexingError>> {
|
||||
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> {
|
||||
|
|
|
@ -47,4 +47,5 @@ pub enum TokenType {
|
|||
True,
|
||||
Let,
|
||||
While,
|
||||
Eof,
|
||||
}
|
||||
|
|
15
src/lib.rs
15
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<Token>) -> Result<Vec<ExpressionNode>, Vec<ASTParsingError>> {
|
||||
pub fn parse(tokens: Vec<Token>) -> ParseAllResult {
|
||||
let mut parser = crate::ast::parser::Parser::new(tokens.into_iter());
|
||||
parser.parse_all()
|
||||
}
|
||||
|
||||
pub fn exec(nodes: Vec<ExpressionNode>) -> Result<Value, RuntimeError> {
|
||||
nodes[0].interpret()
|
||||
pub fn exec(nodes: Vec<Statement>) -> Result<Value, RuntimeError> {
|
||||
todo!();
|
||||
/*
|
||||
for statement in nodes {
|
||||
//statement.interpret()?;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
pub fn run(code: &str) -> Result<Value, run::Error> {
|
||||
|
|
Loading…
Reference in a new issue