Compare commits
2 Commits
ede0ca3993
...
3a5d81c8fb
Author | SHA1 | Date |
---|---|---|
bad | 3a5d81c8fb | |
bad | 91f2a945c5 |
|
@ -4,7 +4,7 @@ use match_any::match_any;
|
|||
use std::fmt::{Debug, Display};
|
||||
|
||||
#[derive(FromVariants)]
|
||||
pub enum ASTNode {
|
||||
pub enum ExpressionNode {
|
||||
BinaryExpr(BinaryExpr),
|
||||
GroupingExpr(GroupingExpr),
|
||||
Literal(Literal),
|
||||
|
@ -15,15 +15,14 @@ macro_rules! all_variants {
|
|||
($expr:expr, $val_name:ident => $expr_arm:expr) => {
|
||||
{
|
||||
use match_any::match_any;
|
||||
use $crate::ast::astnode::*;
|
||||
match_any!($expr, ASTNode::BinaryExpr($val_name) | ASTNode::GroupingExpr($val_name) | ASTNode::Literal($val_name) | ASTNode::UnaryExpr($val_name) => $expr_arm)
|
||||
use $crate::ast::expression::expression_node::*;
|
||||
match_any!($expr, ExpressionNode::BinaryExpr($val_name) | ExpressionNode::GroupingExpr($val_name) | ExpressionNode::Literal($val_name) | ExpressionNode::UnaryExpr($val_name) => $expr_arm)
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
pub(crate) use all_variants;
|
||||
|
||||
impl Debug for ASTNode {
|
||||
impl Debug for ExpressionNode {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
all_variants!(self, n => n.fmt(f))
|
||||
}
|
||||
|
@ -124,13 +123,13 @@ pub enum Literal {
|
|||
}
|
||||
|
||||
pub struct BinaryExpr {
|
||||
pub left: Box<ASTNode>,
|
||||
pub left: Box<ExpressionNode>,
|
||||
pub operator: Operator,
|
||||
pub right: Box<ASTNode>,
|
||||
pub right: Box<ExpressionNode>,
|
||||
}
|
||||
|
||||
impl BinaryExpr {
|
||||
pub fn new(left: Box<ASTNode>, operator: Operator, right: Box<ASTNode>) -> Self {
|
||||
pub fn new(left: Box<ExpressionNode>, operator: Operator, right: Box<ExpressionNode>) -> Self {
|
||||
Self {
|
||||
left,
|
||||
operator,
|
||||
|
@ -139,21 +138,21 @@ impl BinaryExpr {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct GroupingExpr(pub Box<ASTNode>);
|
||||
pub struct GroupingExpr(pub Box<ExpressionNode>);
|
||||
|
||||
impl GroupingExpr {
|
||||
pub(crate) fn new(expr: Box<ASTNode>) -> Self {
|
||||
pub(crate) fn new(expr: Box<ExpressionNode>) -> Self {
|
||||
Self(expr)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UnaryExpr {
|
||||
pub operator: UnaryOperator,
|
||||
pub right: Box<ASTNode>,
|
||||
pub right: Box<ExpressionNode>,
|
||||
}
|
||||
|
||||
impl UnaryExpr {
|
||||
pub fn new(operator: UnaryOperator, right: Box<ASTNode>) -> Self {
|
||||
pub fn new(operator: UnaryOperator, right: Box<ExpressionNode>) -> Self {
|
||||
Self { operator, right }
|
||||
}
|
||||
}
|
||||
|
@ -181,14 +180,14 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn ast_printer() {
|
||||
let ast = ASTNode::BinaryExpr(BinaryExpr {
|
||||
left: Box::new(ASTNode::UnaryExpr(UnaryExpr {
|
||||
fn expression_node_ast_printer() {
|
||||
let ast = ExpressionNode::BinaryExpr(BinaryExpr {
|
||||
left: Box::new(ExpressionNode::UnaryExpr(UnaryExpr {
|
||||
operator: UnaryOperator::Bang,
|
||||
right: Box::new(ASTNode::Literal(Literal::Int(1))),
|
||||
right: Box::new(ExpressionNode::Literal(Literal::Int(1))),
|
||||
})),
|
||||
operator: Operator::EqualEqual,
|
||||
right: Box::new(ASTNode::Literal(Literal::Int(0))),
|
||||
right: Box::new(ExpressionNode::Literal(Literal::Int(0))),
|
||||
});
|
||||
let formated = format!("{:?}", ast);
|
||||
assert_eq!("(== (! Int(1)) Int(0))", formated);
|
|
@ -0,0 +1,124 @@
|
|||
use crate::lexer::token::{self, TokenType};
|
||||
|
||||
use super::super::parser::{InnerASTParsingError, Parser, Result};
|
||||
use super::expression_node::*;
|
||||
|
||||
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
|
||||
pub fn expression(&mut self) -> Result<ExpressionNode> {
|
||||
self.equality()
|
||||
}
|
||||
|
||||
fn equality(&mut self) -> Result<ExpressionNode> {
|
||||
let mut node = self.comparison()?;
|
||||
while let Some(o) = self
|
||||
.token_iter
|
||||
.next_if(|t| matches!(t.token_type, TokenType::EqualEqual | TokenType::BangEqual))
|
||||
{
|
||||
node = BinaryExpr::new(
|
||||
Box::new(node),
|
||||
o.token_type.try_into().unwrap(),
|
||||
Box::new(self.comparison()?),
|
||||
)
|
||||
.into();
|
||||
}
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
fn comparison(&mut self) -> Result<ExpressionNode> {
|
||||
let mut node = self.term()?;
|
||||
|
||||
while let Some(o) = self.token_iter.next_if(|t| {
|
||||
matches!(
|
||||
t.token_type,
|
||||
TokenType::Greater
|
||||
| TokenType::GreaterEqual
|
||||
| TokenType::Less | TokenType::LessEqual
|
||||
)
|
||||
}) {
|
||||
node = BinaryExpr::new(
|
||||
Box::new(node),
|
||||
o.token_type.try_into().unwrap(),
|
||||
Box::new(self.comparison()?),
|
||||
)
|
||||
.into();
|
||||
}
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
fn term(&mut self) -> Result<ExpressionNode> {
|
||||
let mut node = self.factor()?;
|
||||
|
||||
while let Some(o) = self
|
||||
.token_iter
|
||||
.next_if(|t| matches!(t.token_type, TokenType::Minus | TokenType::Plus))
|
||||
{
|
||||
node = BinaryExpr::new(
|
||||
Box::new(node),
|
||||
o.token_type.try_into().unwrap(),
|
||||
Box::new(self.comparison()?),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
fn factor(&mut self) -> Result<ExpressionNode> {
|
||||
let mut node = self.unary()?;
|
||||
|
||||
while let Some(o) = self
|
||||
.token_iter
|
||||
.next_if(|t| matches!(t.token_type, TokenType::Star | TokenType::Slash))
|
||||
{
|
||||
node = BinaryExpr::new(
|
||||
Box::new(node),
|
||||
o.token_type.try_into().unwrap(),
|
||||
Box::new(self.comparison()?),
|
||||
)
|
||||
.into();
|
||||
}
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
fn unary(&mut self) -> Result<ExpressionNode> {
|
||||
if let Some(op) = self
|
||||
.token_iter
|
||||
.next_if(|t| matches!(t.token_type, TokenType::Bang | TokenType::Minus))
|
||||
{
|
||||
let right = Box::new(self.unary()?);
|
||||
Ok(ExpressionNode::UnaryExpr(UnaryExpr::new(
|
||||
op.token_type.try_into().unwrap(),
|
||||
right,
|
||||
)))
|
||||
} else {
|
||||
self.primary()
|
||||
}
|
||||
}
|
||||
|
||||
fn primary(&mut self) -> Result<ExpressionNode> {
|
||||
let node = match self.token_iter.next() {
|
||||
Some(token) => match token.token_type {
|
||||
TokenType::False => ExpressionNode::Literal(Literal::Bool(false)),
|
||||
TokenType::True => ExpressionNode::Literal(Literal::Bool(true)),
|
||||
TokenType::Int(i) => ExpressionNode::Literal(Literal::Int(i)),
|
||||
TokenType::String(i) => ExpressionNode::Literal(Literal::String(i)),
|
||||
TokenType::Float(f) => ExpressionNode::Literal(Literal::Float(f)),
|
||||
TokenType::LeftParen => {
|
||||
let expr = self.expression()?;
|
||||
let group = GroupingExpr::new(Box::new(expr));
|
||||
match self
|
||||
.token_iter
|
||||
.next_if(|v| matches!(v.token_type, TokenType::RightParen))
|
||||
{
|
||||
Some(_) => return Ok(group.into()),
|
||||
None => {
|
||||
return Err(token.location.wrap(InnerASTParsingError::UnmatchedBrace))
|
||||
}
|
||||
}
|
||||
}
|
||||
a => return Err(token.location.wrap(InnerASTParsingError::IncorrectToken(a))),
|
||||
},
|
||||
None => todo!(),
|
||||
};
|
||||
Ok(node)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
pub mod expression_node;
|
||||
mod expression_parser;
|
|
@ -1,2 +1,3 @@
|
|||
pub mod astnode;
|
||||
pub mod expression;
|
||||
pub mod statement;
|
||||
pub mod parser;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::astnode;
|
||||
use super::astnode::{ASTNode, BinaryExpr};
|
||||
use super::expression::expression_node;
|
||||
use super::statement::statement_node;
|
||||
use crate::error::ErrorLocationWrapper;
|
||||
use crate::lexer::{token, token::TokenType};
|
||||
|
||||
|
@ -23,154 +23,36 @@ impl std::fmt::Display for InnerASTParsingError {
|
|||
impl std::error::Error for InnerASTParsingError {}
|
||||
|
||||
pub type ASTParsingError = ErrorLocationWrapper<InnerASTParsingError>;
|
||||
type Result<T> = StdResult<T, ASTParsingError>;
|
||||
pub(super) type Result<T> = StdResult<T, ASTParsingError>;
|
||||
|
||||
pub struct Parser<'a, T: Iterator<Item = token::Token<'a>>> {
|
||||
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> {
|
||||
pub fn new(iter: T) -> Parser<'a, T> {
|
||||
Parser {
|
||||
token_iter: iter.peekable(),
|
||||
}
|
||||
}
|
||||
pub fn scan_expressions(&mut self) -> StdResult<Vec<ASTNode>, 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)
|
||||
}
|
||||
}
|
||||
|
||||
fn expression(&mut self) -> Result<ASTNode> {
|
||||
self.equality()
|
||||
}
|
||||
|
||||
fn equality(&mut self) -> Result<ASTNode> {
|
||||
let mut node = self.comparison()?;
|
||||
while let Some(o) = self
|
||||
.token_iter
|
||||
.next_if(|t| matches!(t.token_type, TokenType::EqualEqual | TokenType::BangEqual))
|
||||
{
|
||||
node = BinaryExpr::new(
|
||||
Box::new(node),
|
||||
o.token_type.try_into().unwrap(),
|
||||
Box::new(self.comparison()?),
|
||||
)
|
||||
.into();
|
||||
}
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
fn comparison(&mut self) -> Result<ASTNode> {
|
||||
let mut node = self.term()?;
|
||||
|
||||
while let Some(o) = self.token_iter.next_if(|t| {
|
||||
matches!(
|
||||
t.token_type,
|
||||
TokenType::Greater
|
||||
| TokenType::GreaterEqual
|
||||
| TokenType::Less | TokenType::LessEqual
|
||||
)
|
||||
}) {
|
||||
node = BinaryExpr::new(
|
||||
Box::new(node),
|
||||
o.token_type.try_into().unwrap(),
|
||||
Box::new(self.comparison()?),
|
||||
)
|
||||
.into();
|
||||
}
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
fn term(&mut self) -> Result<ASTNode> {
|
||||
let mut node = self.factor()?;
|
||||
|
||||
while let Some(o) = self
|
||||
.token_iter
|
||||
.next_if(|t| matches!(t.token_type, TokenType::Minus | TokenType::Plus))
|
||||
{
|
||||
node = BinaryExpr::new(
|
||||
Box::new(node),
|
||||
o.token_type.try_into().unwrap(),
|
||||
Box::new(self.comparison()?),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
fn factor(&mut self) -> Result<ASTNode> {
|
||||
let mut node = self.unary()?;
|
||||
|
||||
while let Some(o) = self
|
||||
.token_iter
|
||||
.next_if(|t| matches!(t.token_type, TokenType::Star | TokenType::Slash))
|
||||
{
|
||||
node = BinaryExpr::new(
|
||||
Box::new(node),
|
||||
o.token_type.try_into().unwrap(),
|
||||
Box::new(self.comparison()?),
|
||||
)
|
||||
.into();
|
||||
}
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
fn unary(&mut self) -> Result<ASTNode> {
|
||||
if let Some(op) = self
|
||||
.token_iter
|
||||
.next_if(|t| matches!(t.token_type, TokenType::Bang | TokenType::Minus))
|
||||
{
|
||||
let right = Box::new(self.unary()?);
|
||||
Ok(ASTNode::UnaryExpr(astnode::UnaryExpr::new(
|
||||
op.token_type.try_into().unwrap(),
|
||||
right,
|
||||
)))
|
||||
} else {
|
||||
self.primary()
|
||||
}
|
||||
}
|
||||
|
||||
fn primary(&mut self) -> Result<ASTNode> {
|
||||
let node = match self.token_iter.next() {
|
||||
Some(token) => match token.token_type {
|
||||
TokenType::False => ASTNode::Literal(astnode::Literal::Bool(false)),
|
||||
TokenType::True => ASTNode::Literal(astnode::Literal::Bool(true)),
|
||||
TokenType::Int(i) => ASTNode::Literal(astnode::Literal::Int(i)),
|
||||
TokenType::String(i) => ASTNode::Literal(astnode::Literal::String(i)),
|
||||
TokenType::Float(f) => ASTNode::Literal(astnode::Literal::Float(f)),
|
||||
TokenType::LeftParen => {
|
||||
let expr = self.expression()?;
|
||||
let group = astnode::GroupingExpr::new(Box::new(expr));
|
||||
match self
|
||||
.token_iter
|
||||
.next_if(|v| matches!(v.token_type, TokenType::RightParen))
|
||||
{
|
||||
Some(_) => return Ok(group.into()),
|
||||
None => {
|
||||
return Err(token.location.wrap(InnerASTParsingError::UnmatchedBrace))
|
||||
}
|
||||
}
|
||||
}
|
||||
a => return Err(token.location.wrap(InnerASTParsingError::IncorrectToken(a))),
|
||||
},
|
||||
None => todo!(),
|
||||
};
|
||||
Ok(node)
|
||||
res
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
pub mod statement_node;
|
||||
mod statement_parser;
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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,66 +0,0 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use super::types::Value;
|
||||
use crate::ast::astnode::{self, UnaryOperator};
|
||||
|
||||
#[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 astnode::ASTNode {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
astnode::all_variants!(self, n => n.interpret())
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret for astnode::Literal {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
Ok(self.clone().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret for astnode::BinaryExpr {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
let left_val = self.left.interpret().expect("expected lval");
|
||||
let right_val = self.right.interpret().expect("expected rval");
|
||||
match self.operator {
|
||||
astnode::Operator::BangEqual => Ok((left_val != right_val).into()),
|
||||
astnode::Operator::Less => Ok((left_val < right_val).into()),
|
||||
astnode::Operator::LessEqual => Ok((left_val <= right_val).into()),
|
||||
astnode::Operator::Greater => Ok((left_val > right_val).into()),
|
||||
astnode::Operator::GreaterEqual => Ok((left_val >= right_val).into()),
|
||||
astnode::Operator::EqualEqual => Ok((left_val == right_val).into()),
|
||||
astnode::Operator::Equal => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret for astnode::UnaryExpr {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
let val = self.right.interpret()?;
|
||||
match self.operator {
|
||||
UnaryOperator::Bang => Ok(Value::Bool(!val.truthy())),
|
||||
UnaryOperator::Minus => match val {
|
||||
Value::Int(i) => Ok(Value::Int(-i)),
|
||||
Value::Float(f) => Ok(Value::Float(-f)),
|
||||
_ => Err(RuntimeError),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret for astnode::GroupingExpr {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
self.0.interpret()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
use super::{RuntimeError, types::Value};
|
||||
use super::Interpret;
|
||||
use crate::ast::expression::expression_node;
|
||||
|
||||
|
||||
|
||||
impl Interpret for expression_node::ExpressionNode {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
expression_node::all_variants!(self, n => n.interpret())
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret for expression_node::Literal {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
Ok(self.clone().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret for expression_node::BinaryExpr {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
let left_val = self.left.interpret().expect("expected lval");
|
||||
let right_val = self.right.interpret().expect("expected rval");
|
||||
match self.operator {
|
||||
expression_node::Operator::BangEqual => Ok((left_val != right_val).into()),
|
||||
expression_node::Operator::Less => Ok((left_val < right_val).into()),
|
||||
expression_node::Operator::LessEqual => Ok((left_val <= right_val).into()),
|
||||
expression_node::Operator::Greater => Ok((left_val > right_val).into()),
|
||||
expression_node::Operator::GreaterEqual => Ok((left_val >= right_val).into()),
|
||||
expression_node::Operator::EqualEqual => Ok((left_val == right_val).into()),
|
||||
expression_node::Operator::Equal => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret for expression_node::UnaryExpr {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
let val = self.right.interpret()?;
|
||||
match self.operator {
|
||||
expression_node::UnaryOperator::Bang => Ok(Value::Bool(!val.truthy())),
|
||||
expression_node::UnaryOperator::Minus => match val {
|
||||
Value::Int(i) => Ok(Value::Int(-i)),
|
||||
Value::Float(f) => Ok(Value::Float(-f)),
|
||||
_ => Err(RuntimeError),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret for expression_node::GroupingExpr {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
self.0.interpret()
|
||||
}
|
||||
}
|
|
@ -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>;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::ast::astnode;
|
||||
use crate::ast::expression::expression_node;
|
||||
use from_variants::FromVariants;
|
||||
|
||||
#[derive(Debug, PartialEq, PartialOrd, FromVariants)]
|
||||
|
@ -11,10 +11,10 @@ pub enum Value {
|
|||
String(String),
|
||||
}
|
||||
|
||||
impl From<astnode::Literal> for Value {
|
||||
fn from(l: astnode::Literal) -> Self {
|
||||
impl From<expression_node::Literal> for Value {
|
||||
fn from(l: expression_node::Literal) -> Self {
|
||||
match_any::match_any!(l,
|
||||
astnode::Literal::Int(v) | astnode::Literal::Bool(v) | astnode::Literal::Float(v) | astnode::Literal::String(v) => v.into()
|
||||
expression_node::Literal::Int(v) | expression_node::Literal::Bool(v) | expression_node::Literal::Float(v) | expression_node::Literal::String(v) => v.into()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
16
src/lib.rs
16
src/lib.rs
|
@ -3,7 +3,8 @@ pub mod error;
|
|||
pub mod interpreter;
|
||||
pub mod lexer;
|
||||
|
||||
use ast::{astnode::ASTNode, 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};
|
||||
|
@ -16,13 +17,18 @@ pub fn lex<'a, 'b>(
|
|||
lexer.scan_tokens()
|
||||
}
|
||||
|
||||
pub fn parse(tokens: Vec<Token>) -> Result<Vec<ASTNode>, Vec<ASTParsingError>> {
|
||||
pub fn parse(tokens: Vec<Token>) -> ParseAllResult {
|
||||
let mut parser = crate::ast::parser::Parser::new(tokens.into_iter());
|
||||
parser.scan_expressions()
|
||||
parser.parse_all()
|
||||
}
|
||||
|
||||
pub fn exec(nodes: Vec<ASTNode>) -> 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 New Issue