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 expression;
|
||||||
|
pub mod statement;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::expression::expression_node;
|
use super::expression::expression_node;
|
||||||
|
use super::statement::statement_node;
|
||||||
use crate::error::ErrorLocationWrapper;
|
use crate::error::ErrorLocationWrapper;
|
||||||
use crate::lexer::{token, token::TokenType};
|
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(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> {
|
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> {
|
||||||
Parser {
|
Parser {
|
||||||
token_iter: iter.peekable(),
|
token_iter: iter.peekable(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn parse_all(
|
pub fn parse_all(&mut self) -> ParseAllResult {
|
||||||
&mut self,
|
let mut res = Ok(Vec::new());
|
||||||
) -> StdResult<Vec<expression_node::ExpressionNode>, Vec<ASTParsingError>> {
|
|
||||||
let mut tokens = Vec::new();
|
|
||||||
let mut errors = Vec::new();
|
|
||||||
|
|
||||||
while self.token_iter.peek().is_some() {
|
while !matches!(self.token_iter.peek().unwrap().token_type, token::TokenType::Eof) {
|
||||||
match self.expression() {
|
match self.statement() {
|
||||||
Ok(token) => {
|
Ok(s) => {
|
||||||
if errors.is_empty() {
|
if let Ok(ref mut v) = res {
|
||||||
tokens.push(token)
|
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() {
|
res
|
||||||
Ok(tokens)
|
|
||||||
} else {
|
|
||||||
Err(errors)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
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::{RuntimeError, types::Value};
|
||||||
|
use super::Interpret;
|
||||||
use super::types::Value;
|
|
||||||
use crate::ast::expression::expression_node;
|
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 {
|
impl Interpret for expression_node::ExpressionNode {
|
||||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
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 ast_walker;
|
||||||
pub mod types;
|
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>> {
|
pub fn scan_tokens(&mut self) -> Result<Vec<token::Token<'b>>, Vec<LexingError>> {
|
||||||
let mut tokens = Vec::new();
|
let mut res = Ok(Vec::new());
|
||||||
let mut errors = Vec::new();
|
|
||||||
|
|
||||||
while self.source_iter.peek().is_some() {
|
while self.source_iter.peek().is_some() {
|
||||||
match self.scan_token() {
|
match self.scan_token() {
|
||||||
Ok(Some(token)) => {
|
Ok(Some(token)) => if let Ok(ref mut v) = res {
|
||||||
if errors.is_empty() {
|
v.push(token)
|
||||||
tokens.push(token)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(None) => (),
|
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() {
|
if let Ok(ref mut v) = res {
|
||||||
Ok(tokens)
|
v.push(self.get_token(token::TokenType::Eof));
|
||||||
} else {
|
|
||||||
Err(errors)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_token(&self, token_type: token::TokenType) -> token::Token<'b> {
|
fn get_token(&self, token_type: token::TokenType) -> token::Token<'b> {
|
||||||
|
|
|
@ -47,4 +47,5 @@ pub enum TokenType {
|
||||||
True,
|
True,
|
||||||
Let,
|
Let,
|
||||||
While,
|
While,
|
||||||
|
Eof,
|
||||||
}
|
}
|
||||||
|
|
15
src/lib.rs
15
src/lib.rs
|
@ -3,8 +3,8 @@ pub mod error;
|
||||||
pub mod interpreter;
|
pub mod interpreter;
|
||||||
pub mod lexer;
|
pub mod lexer;
|
||||||
|
|
||||||
use ast::expression::expression_node::ExpressionNode;
|
use ast::parser::ParseAllResult;
|
||||||
use ast::parser::ASTParsingError;
|
use ast::statement::statement_node::Statement;
|
||||||
use interpreter::ast_walker::{Interpret, RuntimeError};
|
use interpreter::ast_walker::{Interpret, RuntimeError};
|
||||||
use interpreter::types::Value;
|
use interpreter::types::Value;
|
||||||
use lexer::{token::Token, Lexer, LexingError};
|
use lexer::{token::Token, Lexer, LexingError};
|
||||||
|
@ -17,13 +17,18 @@ pub fn lex<'a, 'b>(
|
||||||
lexer.scan_tokens()
|
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());
|
let mut parser = crate::ast::parser::Parser::new(tokens.into_iter());
|
||||||
parser.parse_all()
|
parser.parse_all()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exec(nodes: Vec<ExpressionNode>) -> Result<Value, RuntimeError> {
|
pub fn exec(nodes: Vec<Statement>) -> Result<Value, RuntimeError> {
|
||||||
nodes[0].interpret()
|
todo!();
|
||||||
|
/*
|
||||||
|
for statement in nodes {
|
||||||
|
//statement.interpret()?;
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(code: &str) -> Result<Value, run::Error> {
|
pub fn run(code: &str) -> Result<Value, run::Error> {
|
||||||
|
|
Loading…
Reference in a new issue