Compare commits

...

2 Commits

Author SHA1 Message Date
bad 2171bebc08 Refactor expression module tree 2022-05-02 12:56:52 +02:00
bad e4e0eb322e Refactor statement module tree 2022-05-02 11:38:20 +02:00
21 changed files with 554 additions and 494 deletions

View File

@ -0,0 +1,103 @@
use itertools::PeekingNext;
use super::operator::Operator;
use super::{
token::{self, TokenType},
ExpressionNode, Parser, Result,
};
use std::fmt::Debug;
pub struct BinaryExpr {
pub left: Box<ExpressionNode>,
pub operator: Operator,
pub right: Box<ExpressionNode>,
}
impl BinaryExpr {
pub fn new(left: Box<ExpressionNode>, operator: Operator, right: Box<ExpressionNode>) -> Self {
Self {
left,
operator,
right,
}
}
}
impl Debug for BinaryExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({} {:?} {:?})", self.operator, self.left, self.right)
}
}
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
pub(super) fn equality(&mut self) -> Result<ExpressionNode> {
let mut node = self.comparison()?;
while let Some(o) = self
.token_iter
.peeking_next(|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)
}
pub(super) fn comparison(&mut self) -> Result<ExpressionNode> {
let mut node = self.term()?;
while let Some(o) = self.token_iter.peeking_next(|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)
}
pub(super) fn term(&mut self) -> Result<ExpressionNode> {
let mut node = self.factor()?;
while let Some(o) = self
.token_iter
.peeking_next(|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)
}
pub(super) fn factor(&mut self) -> Result<ExpressionNode> {
let mut node = self.unary()?;
while let Some(o) = self
.token_iter
.peeking_next(|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)
}
}

View File

@ -1,218 +1 @@
use crate::lexer::token;
use from_variants::FromVariants;
use match_any::match_any;
use std::fmt::{Debug, Display};
#[derive(FromVariants)]
pub enum ExpressionNode {
BinaryExpr(BinaryExpr),
GroupingExpr(GroupingExpr),
Literal(Literal),
Variable(VariableExpr),
UnaryExpr(UnaryExpr),
}
macro_rules! all_variants {
($expr:expr, $val_name:ident => $expr_arm:expr) => {
{
use match_any::match_any;
use $crate::ast::expression::expression_node::*;
match_any!($expr,
ExpressionNode::BinaryExpr($val_name) |
ExpressionNode::GroupingExpr($val_name) |
ExpressionNode::Literal($val_name) |
ExpressionNode::Variable($val_name) |
ExpressionNode::UnaryExpr($val_name) => $expr_arm)
}
};
}
pub(crate) use all_variants;
impl Debug for ExpressionNode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
all_variants!(self, n => n.fmt(f))
}
}
pub enum UnaryOperator {
Minus,
Bang,
}
impl TryFrom<token::TokenType> for UnaryOperator {
type Error = EnumConvertError;
fn try_from(value: token::TokenType) -> Result<Self, Self::Error> {
Ok(match value {
token::TokenType::Bang => Self::Bang,
token::TokenType::Minus => Self::Minus,
_ => return Err(EnumConvertError),
})
}
}
impl Display for UnaryOperator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match *self {
UnaryOperator::Minus => "-",
UnaryOperator::Bang => "!",
}
)
}
}
pub enum Operator {
BangEqual,
Equal,
EqualEqual,
Greater,
GreaterEqual,
Less,
LessEqual,
}
#[derive(Debug)]
pub struct EnumConvertError;
impl std::fmt::Display for EnumConvertError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Couldn't convert between enums")
}
}
impl std::error::Error for EnumConvertError {}
impl TryFrom<token::TokenType> for Operator {
type Error = EnumConvertError;
fn try_from(value: token::TokenType) -> Result<Self, Self::Error> {
Ok(match value {
token::TokenType::BangEqual => Self::BangEqual,
token::TokenType::Equal => Self::Equal,
token::TokenType::EqualEqual => Self::EqualEqual,
token::TokenType::Greater => Self::Greater,
token::TokenType::GreaterEqual => Self::GreaterEqual,
token::TokenType::Less => Self::Less,
token::TokenType::LessEqual => Self::LessEqual,
_ => return Err(EnumConvertError),
})
}
}
impl Display for Operator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match *self {
Operator::Less => "<",
Operator::Equal => "=",
Operator::Greater => ">",
Operator::BangEqual => "!=",
Operator::LessEqual => "<=",
Operator::EqualEqual => "==",
Operator::GreaterEqual => ">=",
}
)
}
}
#[derive(Debug, Clone)]
pub enum Literal {
String(String),
Int(i32),
Float(f32),
Bool(bool),
Nil,
}
pub struct BinaryExpr {
pub left: Box<ExpressionNode>,
pub operator: Operator,
pub right: Box<ExpressionNode>,
}
impl BinaryExpr {
pub fn new(left: Box<ExpressionNode>, operator: Operator, right: Box<ExpressionNode>) -> Self {
Self {
left,
operator,
right,
}
}
}
pub struct GroupingExpr(pub Box<ExpressionNode>);
impl GroupingExpr {
pub(crate) fn new(expr: Box<ExpressionNode>) -> Self {
Self(expr)
}
}
pub struct UnaryExpr {
pub operator: UnaryOperator,
pub right: Box<ExpressionNode>,
}
impl UnaryExpr {
pub fn new(operator: UnaryOperator, right: Box<ExpressionNode>) -> Self {
Self { operator, right }
}
}
impl Debug for BinaryExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({} {:?} {:?})", self.operator, self.left, self.right)
}
}
impl Debug for GroupingExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({:?})", self.0)
}
}
impl Debug for UnaryExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({} {:?})", self.operator, self.right)
}
}
pub struct VariableExpr {
pub var_name: String,
}
impl Debug for VariableExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "(variable({}))", self.var_name)
}
}
impl VariableExpr {
pub fn new(var_name: String) -> Self {
Self { var_name }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn expression_node_ast_printer() {
let ast = ExpressionNode::BinaryExpr(BinaryExpr {
left: Box::new(ExpressionNode::UnaryExpr(UnaryExpr {
operator: UnaryOperator::Bang,
right: Box::new(ExpressionNode::Literal(Literal::Int(1))),
})),
operator: Operator::EqualEqual,
right: Box::new(ExpressionNode::Literal(Literal::Int(0))),
});
let formated = format!("{:?}", ast);
assert_eq!("(== (! Int(1)) Int(0))", formated);
}
}

View File

@ -1,124 +0,0 @@
use itertools::PeekingNext;
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
.peeking_next(|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.peeking_next(|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
.peeking_next(|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
.peeking_next(|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
.peeking_next(|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 token = self.token_iter.next();
let node = 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::Nil => ExpressionNode::Literal(Literal::Nil),
TokenType::LeftParen => {
let expr = self.expression()?;
let group = GroupingExpr::new(Box::new(expr));
match self
.token_iter
.peeking_next(|v| matches!(v.token_type, TokenType::RightParen))
{
Some(_) => return Ok(group.into()),
None => return Err(token.location.wrap(InnerASTParsingError::UnmatchedBrace)),
}
}
TokenType::Identifier(var_name) => VariableExpr::new(var_name).into(),
a => return Err(token.location.wrap(InnerASTParsingError::IncorrectToken(a))),
};
Ok(node)
}
}

View File

@ -0,0 +1,16 @@
use super::ExpressionNode;
use std::fmt::Debug;
pub struct GroupingExpr(pub Box<ExpressionNode>);
impl GroupingExpr {
pub(crate) fn new(expr: Box<ExpressionNode>) -> Self {
Self(expr)
}
}
impl Debug for GroupingExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({:?})", self.0)
}
}

View File

@ -0,0 +1,10 @@
use std::fmt::Debug;
#[derive(Debug, Clone)]
pub enum Literal {
String(String),
Int(i32),
Float(f32),
Bool(bool),
Nil,
}

View File

@ -1,2 +1,103 @@
mod binary_expr;
pub mod expression_node;
mod expression_parser;
mod grouping_expr;
mod literal_expr;
pub mod operator;
mod unary_expr;
mod variable_expr;
pub use binary_expr::BinaryExpr;
pub use grouping_expr::GroupingExpr;
use itertools::PeekingNext;
pub use literal_expr::Literal;
pub use unary_expr::UnaryExpr;
pub use variable_expr::VariableExpr;
use super::parser::{InnerASTParsingError, Parser, Result};
use crate::lexer::token::{self, TokenType};
use from_variants::FromVariants;
use match_any::match_any;
use std::fmt::Debug;
#[derive(FromVariants)]
pub enum ExpressionNode {
BinaryExpr(BinaryExpr),
GroupingExpr(GroupingExpr),
Literal(Literal),
Variable(VariableExpr),
UnaryExpr(UnaryExpr),
}
macro_rules! all_variants {
($expr:expr, $val_name:ident => $expr_arm:expr) => {
{
use match_any::match_any;
use $crate::ast::expression::*;
match_any!($expr,
ExpressionNode::BinaryExpr($val_name) |
ExpressionNode::GroupingExpr($val_name) |
ExpressionNode::Literal($val_name) |
ExpressionNode::Variable($val_name) |
ExpressionNode::UnaryExpr($val_name) => $expr_arm)
}
};
}
pub(crate) use all_variants;
impl Debug for ExpressionNode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
all_variants!(self, n => n.fmt(f))
}
}
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
pub fn expression(&mut self) -> Result<ExpressionNode> {
self.equality()
}
pub(super) fn primary(&mut self) -> Result<ExpressionNode> {
let token = self.token_iter.next();
let node = 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::Nil => ExpressionNode::Literal(Literal::Nil),
TokenType::LeftParen => {
let expr = self.expression()?;
let group = GroupingExpr::new(Box::new(expr));
match self
.token_iter
.peeking_next(|v| matches!(v.token_type, TokenType::RightParen))
{
Some(_) => return Ok(group.into()),
None => return Err(token.location.wrap(InnerASTParsingError::UnmatchedBrace)),
}
}
TokenType::Identifier(var_name) => VariableExpr::new(var_name).into(),
a => return Err(token.location.wrap(InnerASTParsingError::IncorrectToken(a))),
};
Ok(node)
}
}
#[cfg(test)]
mod tests {
use super::*;
use operator::{Operator, UnaryOperator};
#[test]
fn expression_node_ast_printer() {
let ast = ExpressionNode::BinaryExpr(BinaryExpr {
left: Box::new(ExpressionNode::UnaryExpr(UnaryExpr {
operator: UnaryOperator::Bang,
right: Box::new(ExpressionNode::Literal(Literal::Int(1))),
})),
operator: Operator::EqualEqual,
right: Box::new(ExpressionNode::Literal(Literal::Int(0))),
});
let formated = format!("{:?}", ast);
assert_eq!("(== (! Int(1)) Int(0))", formated);
}
}

View File

@ -0,0 +1,89 @@
use std::fmt::Display;
use crate::lexer::token;
pub enum UnaryOperator {
Minus,
Bang,
}
impl TryFrom<token::TokenType> for UnaryOperator {
type Error = EnumConvertError;
fn try_from(value: token::TokenType) -> Result<Self, Self::Error> {
Ok(match value {
token::TokenType::Bang => Self::Bang,
token::TokenType::Minus => Self::Minus,
_ => return Err(EnumConvertError),
})
}
}
impl Display for UnaryOperator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match *self {
UnaryOperator::Minus => "-",
UnaryOperator::Bang => "!",
}
)
}
}
pub enum Operator {
BangEqual,
Equal,
EqualEqual,
Greater,
GreaterEqual,
Less,
LessEqual,
}
#[derive(Debug)]
pub struct EnumConvertError;
impl std::fmt::Display for EnumConvertError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Couldn't convert between enums")
}
}
impl std::error::Error for EnumConvertError {}
impl TryFrom<token::TokenType> for Operator {
type Error = EnumConvertError;
fn try_from(value: token::TokenType) -> Result<Self, Self::Error> {
Ok(match value {
token::TokenType::BangEqual => Self::BangEqual,
token::TokenType::Equal => Self::Equal,
token::TokenType::EqualEqual => Self::EqualEqual,
token::TokenType::Greater => Self::Greater,
token::TokenType::GreaterEqual => Self::GreaterEqual,
token::TokenType::Less => Self::Less,
token::TokenType::LessEqual => Self::LessEqual,
_ => return Err(EnumConvertError),
})
}
}
impl Display for Operator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match *self {
Operator::Less => "<",
Operator::Equal => "=",
Operator::Greater => ">",
Operator::BangEqual => "!=",
Operator::LessEqual => "<=",
Operator::EqualEqual => "==",
Operator::GreaterEqual => ">=",
}
)
}
}

View File

@ -0,0 +1,41 @@
use super::operator::UnaryOperator;
use super::{
token::{self, TokenType},
ExpressionNode, Parser, Result,
};
use itertools::PeekingNext;
use std::fmt::Debug;
pub struct UnaryExpr {
pub operator: UnaryOperator,
pub right: Box<ExpressionNode>,
}
impl UnaryExpr {
pub fn new(operator: UnaryOperator, right: Box<ExpressionNode>) -> Self {
Self { operator, right }
}
}
impl Debug for UnaryExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({} {:?})", self.operator, self.right)
}
}
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
pub(super) fn unary(&mut self) -> Result<ExpressionNode> {
if let Some(op) = self
.token_iter
.peeking_next(|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()
}
}
}

View File

@ -0,0 +1,17 @@
use std::fmt::Debug;
pub struct VariableExpr {
pub var_name: String,
}
impl Debug for VariableExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "(variable({}))", self.var_name)
}
}
impl VariableExpr {
pub fn new(var_name: String) -> Self {
Self { var_name }
}
}

View File

@ -1,5 +1,5 @@
use super::ast_parser_iter::ParserIter;
use super::statement::statement_node;
use super::statement;
use crate::error::ErrorLocationWrapper;
use crate::lexer::{token, token::TokenType};
use std::result::Result as StdResult;
@ -29,7 +29,7 @@ pub struct Parser<'a, T: Iterator<Item = token::Token<'a>>> {
pub(super) token_iter: super::ast_parser_iter::ParserIter<T>,
}
pub type ParseAllResult = StdResult<Vec<statement_node::Statement>, Vec<ASTParsingError>>;
pub type ParseAllResult = StdResult<Vec<statement::Statement>, Vec<ASTParsingError>>;
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
pub fn new(iter: T) -> Parser<'a, T> {

View File

@ -0,0 +1,28 @@
use crate::{
ast::expression::ExpressionNode,
ast::parser::{InnerASTParsingError, Parser, Result},
lexer::token::{self, TokenType},
};
use super::Statement;
#[derive(Debug)]
pub struct ExpressionStatement(pub ExpressionNode);
impl ExpressionStatement {
pub fn new(expr: ExpressionNode) -> Self {
Self(expr)
}
}
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
pub fn expression_statement(&mut self) -> Result<Statement> {
let expr = self.expression()?;
let token = self.token_iter.peek();
if let TokenType::Semicolon = token.token_type {
self.token_iter.next();
Ok(ExpressionStatement::new(expr).into())
} else {
Err(token.location.wrap(InnerASTParsingError::ExpectedSemi))
}
}
}

View File

@ -1,2 +1,37 @@
pub mod statement_node;
mod statement_parser;
use crate::lexer::token;
use super::parser::{InnerASTParsingError, Parser, Result};
mod expression_statement;
mod print_statement;
mod variable_assignment_statement;
pub use expression_statement::ExpressionStatement;
pub use print_statement::PrintStatement;
pub use variable_assignment_statement::VariableAssignmentStatement;
use from_variants::FromVariants;
#[derive(FromVariants, Debug)]
pub enum Statement {
Expression(ExpressionStatement),
Print(PrintStatement),
VariableAssignment(VariableAssignmentStatement),
}
macro_rules! all_variants {
($expr:expr, $val_name:ident => $expr_arm:expr) => {
{
use match_any::match_any;
use $crate::ast::statement::*;
match_any!($expr, Statement::Expression($val_name) | Statement::Print($val_name) | Statement::VariableAssignment($val_name) => $expr_arm)
}
};
}
pub(crate) use all_variants;
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
pub fn statement(&mut self) -> Result<Statement> {
self.print_statement()
}
}

View File

@ -0,0 +1,32 @@
use itertools::PeekingNext;
use super::{InnerASTParsingError, Parser, Result, Statement};
use crate::ast::expression::ExpressionNode;
use crate::lexer::token::{self, Token};
#[derive(Debug)]
pub struct PrintStatement(pub ExpressionNode);
impl PrintStatement {
pub fn new(expr: ExpressionNode) -> Self {
Self(expr)
}
}
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
pub(super) fn print_statement(&mut self) -> Result<Statement> {
if let Some(Token { location: loc, .. }) = self
.token_iter
.peeking_next(|t| matches!(t.token_type, token::TokenType::Print))
{
let expr = self.expression()?;
if let token::TokenType::Semicolon = self.token_iter.peek().token_type {
self.token_iter.next();
Ok(PrintStatement::new(expr).into())
} else {
Err(loc.wrap(InnerASTParsingError::ExpectedSemi))
}
} else {
self.variable_assignment_statement()
}
}
}

View File

@ -1,48 +0,0 @@
use crate::ast::expression::expression_node::ExpressionNode;
use from_variants::FromVariants;
#[derive(FromVariants, Debug)]
pub enum Statement {
Expression(ExpressionStatement),
Print(PrintStatement),
VariableAssignment(VariableAssignmentStatement),
}
macro_rules! all_variants {
($expr:expr, $val_name:ident => $expr_arm:expr) => {
{
use match_any::match_any;
use $crate::ast::statement::statement_node::*;
match_any!($expr, Statement::Expression($val_name) | Statement::Print($val_name) | Statement::VariableAssignment($val_name) => $expr_arm)
}
};
}
pub(crate) use all_variants;
#[derive(Debug)]
pub struct ExpressionStatement(pub ExpressionNode);
impl ExpressionStatement {
pub fn new(expr: ExpressionNode) -> Self {
Self(expr)
}
}
#[derive(Debug)]
pub struct PrintStatement(pub ExpressionNode);
impl PrintStatement {
pub fn new(expr: ExpressionNode) -> Self {
Self(expr)
}
}
#[derive(Debug)]
pub struct VariableAssignmentStatement {
pub var_name: String,
pub node: ExpressionNode,
}
impl VariableAssignmentStatement {
pub fn new(var_name: String, node: ExpressionNode) -> Self {
Self { var_name, node }
}
}

View File

@ -1,70 +0,0 @@
use itertools::PeekingNext;
use super::statement_node::{ExpressionStatement, PrintStatement, Statement};
use crate::{
ast::{
parser::{InnerASTParsingError, Parser, Result},
statement::statement_node::VariableAssignmentStatement,
},
lexer::token::{self, Token, TokenType},
};
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
pub fn statement(&mut self) -> Result<Statement> {
self.print_statement()
}
fn print_statement(&mut self) -> Result<Statement> {
if let Some(Token { location: loc, .. }) = self
.token_iter
.peeking_next(|t| matches!(t.token_type, token::TokenType::Print))
{
let expr = self.expression()?;
if let token::TokenType::Semicolon = self.token_iter.peek().token_type {
self.token_iter.next();
Ok(PrintStatement::new(expr).into())
} else {
Err(loc.wrap(InnerASTParsingError::ExpectedSemi))
}
} else {
self.variable_assignment_statement()
}
}
fn variable_assignment_statement(&mut self) -> Result<Statement> {
if matches!(
self.token_iter.peek_nth(0).token_type,
TokenType::Identifier(_)
) && matches!(self.token_iter.peek_nth(1).token_type, TokenType::Equal)
{
let ident = if let TokenType::Identifier(ident) = self.token_iter.next().token_type {
ident
} else {
unreachable!()
};
self.token_iter.next();
let expr = self.expression()?;
let token = self.token_iter.peek();
if let token::TokenType::Semicolon = token.token_type {
self.token_iter.next();
Ok(VariableAssignmentStatement::new(ident, expr).into())
} else {
Err(token.location.wrap(InnerASTParsingError::ExpectedSemi))
}
} else {
self.expression_statement()
}
}
fn expression_statement(&mut self) -> Result<Statement> {
let expr = self.expression()?;
let token = self.token_iter.peek();
if let TokenType::Semicolon = token.token_type {
self.token_iter.next();
Ok(ExpressionStatement::new(expr).into())
} else {
Err(token.location.wrap(InnerASTParsingError::ExpectedSemi))
}
}
}

View File

@ -0,0 +1,44 @@
use super::Statement;
use super::{InnerASTParsingError, Parser, Result};
use crate::ast::expression::ExpressionNode;
use crate::lexer::token::{self, TokenType};
#[derive(Debug)]
pub struct VariableAssignmentStatement {
pub var_name: String,
pub node: ExpressionNode,
}
impl VariableAssignmentStatement {
pub fn new(var_name: String, node: ExpressionNode) -> Self {
Self { var_name, node }
}
}
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
pub(super) fn variable_assignment_statement(&mut self) -> Result<Statement> {
if matches!(
self.token_iter.peek_nth(0).token_type,
TokenType::Identifier(_)
) && matches!(self.token_iter.peek_nth(1).token_type, TokenType::Equal)
{
let ident = if let TokenType::Identifier(ident) = self.token_iter.next().token_type {
ident
} else {
unreachable!()
};
self.token_iter.next();
let expr = self.expression()?;
let token = self.token_iter.peek();
if let token::TokenType::Semicolon = token.token_type {
self.token_iter.next();
Ok(VariableAssignmentStatement::new(ident, expr).into())
} else {
Err(token.location.wrap(InnerASTParsingError::ExpectedSemi))
}
} else {
self.expression_statement()
}
}
}

View File

@ -1,42 +1,45 @@
use super::Interpret;
use super::{types::Value, RuntimeError};
use crate::ast::expression::expression_node;
use crate::ast::expression::{
self,
operator::{Operator, UnaryOperator},
};
use crate::interpreter::world::World;
impl Interpret for expression_node::ExpressionNode {
impl Interpret for expression::ExpressionNode {
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
expression_node::all_variants!(self, n => n.interpret(w))
expression::all_variants!(self, n => n.interpret(w))
}
}
impl Interpret for expression_node::Literal {
impl Interpret for expression::Literal {
fn interpret(&self, _: &mut World) -> Result<Value, RuntimeError> {
Ok(self.clone().into())
}
}
impl Interpret for expression_node::BinaryExpr {
impl Interpret for expression::BinaryExpr {
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
let left_val = self.left.interpret(w).expect("expected lval");
let right_val = self.right.interpret(w).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!(),
Operator::BangEqual => Ok((left_val != right_val).into()),
Operator::Less => Ok((left_val < right_val).into()),
Operator::LessEqual => Ok((left_val <= right_val).into()),
Operator::Greater => Ok((left_val > right_val).into()),
Operator::GreaterEqual => Ok((left_val >= right_val).into()),
Operator::EqualEqual => Ok((left_val == right_val).into()),
Operator::Equal => todo!(),
}
}
}
impl Interpret for expression_node::UnaryExpr {
impl Interpret for expression::UnaryExpr {
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
let val = self.right.interpret(w)?;
match self.operator {
expression_node::UnaryOperator::Bang => Ok(Value::Bool(!val.truthy())),
expression_node::UnaryOperator::Minus => match val {
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),
@ -45,13 +48,13 @@ impl Interpret for expression_node::UnaryExpr {
}
}
impl Interpret for expression_node::GroupingExpr {
impl Interpret for expression::GroupingExpr {
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
self.0.interpret(w)
}
}
impl Interpret for expression_node::VariableExpr {
impl Interpret for expression::VariableExpr {
fn interpret(&self, world: &mut World) -> Result<Value, RuntimeError> {
match world.get_var(&self.var_name) {
Some(v) => Ok(v.clone()),

View File

@ -1,15 +1,15 @@
use super::Interpret;
use super::{types::Value, RuntimeError};
use crate::ast::statement::statement_node;
use crate::ast::statement;
use crate::interpreter::world::World;
impl Interpret for statement_node::Statement {
impl Interpret for statement::Statement {
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
statement_node::all_variants!(self, n => n.interpret(w))
statement::all_variants!(self, n => n.interpret(w))
}
}
impl Interpret for statement_node::PrintStatement {
impl Interpret for statement::PrintStatement {
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
let res = self.0.interpret(w)?;
println!("{:?}", res);
@ -17,13 +17,13 @@ impl Interpret for statement_node::PrintStatement {
}
}
impl Interpret for statement_node::ExpressionStatement {
impl Interpret for statement::ExpressionStatement {
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
self.0.interpret(w)
}
}
impl Interpret for statement_node::VariableAssignmentStatement {
impl Interpret for statement::VariableAssignmentStatement {
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
let expr_val = self.node.interpret(w)?;
// Clone for now, later this will use a GC and won't need to clone

View File

@ -1,4 +1,4 @@
use crate::ast::expression::expression_node;
use crate::ast::expression;
use from_variants::FromVariants;
#[derive(Debug, PartialEq, PartialOrd, Clone, FromVariants)]
@ -11,11 +11,11 @@ pub enum Value {
String(String),
}
impl From<expression_node::Literal> for Value {
fn from(l: expression_node::Literal) -> Self {
impl From<expression::Literal> for Value {
fn from(l: expression::Literal) -> Self {
match_any::match_any!(l,
expression_node::Literal::Int(v) | expression_node::Literal::Bool(v) | expression_node::Literal::Float(v) | expression_node::Literal::String(v) => v.into(),
expression_node::Literal::Nil => Self::Nil
expression::Literal::Int(v) | expression::Literal::Bool(v) | expression::Literal::Float(v) | expression::Literal::String(v) => v.into(),
expression::Literal::Nil => Self::Nil
)
}
}

View File

@ -1,6 +1,6 @@
use std::collections::HashMap;
use crate::ast::statement::statement_node::Statement;
use crate::ast::statement::Statement;
use super::{
ast_walker::{Interpret, RuntimeError},

View File

@ -5,7 +5,7 @@ pub mod interpreter;
pub mod lexer;
use ast::parser::ParseAllResult;
use ast::statement::statement_node::Statement;
use ast::statement::Statement;
use interpreter::ast_walker::{Interpret, RuntimeError};
use interpreter::types::Value;
use interpreter::world::World;