Statement parsing

This commit is contained in:
bad 2022-04-23 16:27:11 +02:00
parent 91f2a945c5
commit 3a5d81c8fb
13 changed files with 122 additions and 47 deletions

View File

View File

@ -1,2 +1,3 @@
pub mod expression;
pub mod statement;
pub mod parser;

View File

@ -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
View File

@ -0,0 +1,2 @@
pub mod statement_node;
mod statement_parser;

View 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)
}
}

View 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!();
}
}
}

View File

@ -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> {

View 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
View 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 {}

View File

@ -1,2 +1,3 @@
pub mod ast_walker;
pub mod types;
pub mod error;

View File

@ -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> {

View File

@ -47,4 +47,5 @@ pub enum TokenType {
True,
Let,
While,
Eof,
}

View File

@ -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> {