Refactor expression module tree
This commit is contained in:
parent
e4e0eb322e
commit
2171bebc08
14 changed files with 406 additions and 367 deletions
103
src/ast/expression/binary_expr.rs
Normal file
103
src/ast/expression/binary_expr.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
16
src/ast/expression/grouping_expr.rs
Normal file
16
src/ast/expression/grouping_expr.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
10
src/ast/expression/literal_expr.rs
Normal file
10
src/ast/expression/literal_expr.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Literal {
|
||||||
|
String(String),
|
||||||
|
Int(i32),
|
||||||
|
Float(f32),
|
||||||
|
Bool(bool),
|
||||||
|
Nil,
|
||||||
|
}
|
|
@ -1,2 +1,103 @@
|
||||||
|
mod binary_expr;
|
||||||
pub mod expression_node;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
89
src/ast/expression/operator.rs
Normal file
89
src/ast/expression/operator.rs
Normal 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 => ">=",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
41
src/ast/expression/unary_expr.rs
Normal file
41
src/ast/expression/unary_expr.rs
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/ast/expression/variable_expr.rs
Normal file
17
src/ast/expression/variable_expr.rs
Normal 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 }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::expression::expression_node::ExpressionNode,
|
ast::expression::ExpressionNode,
|
||||||
ast::parser::{InnerASTParsingError, Parser, Result},
|
ast::parser::{InnerASTParsingError, Parser, Result},
|
||||||
lexer::token::{self, TokenType},
|
lexer::token::{self, TokenType},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use itertools::PeekingNext;
|
use itertools::PeekingNext;
|
||||||
|
|
||||||
use super::{InnerASTParsingError, Parser, Result, Statement};
|
use super::{InnerASTParsingError, Parser, Result, Statement};
|
||||||
use crate::ast::expression::expression_node::ExpressionNode;
|
use crate::ast::expression::ExpressionNode;
|
||||||
use crate::lexer::token::{self, Token};
|
use crate::lexer::token::{self, Token};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::Statement;
|
use super::Statement;
|
||||||
use super::{InnerASTParsingError, Parser, Result};
|
use super::{InnerASTParsingError, Parser, Result};
|
||||||
use crate::ast::expression::expression_node::ExpressionNode;
|
use crate::ast::expression::ExpressionNode;
|
||||||
use crate::lexer::token::{self, TokenType};
|
use crate::lexer::token::{self, TokenType};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -1,42 +1,45 @@
|
||||||
use super::Interpret;
|
use super::Interpret;
|
||||||
use super::{types::Value, RuntimeError};
|
use super::{types::Value, RuntimeError};
|
||||||
use crate::ast::expression::expression_node;
|
use crate::ast::expression::{
|
||||||
|
self,
|
||||||
|
operator::{Operator, UnaryOperator},
|
||||||
|
};
|
||||||
use crate::interpreter::world::World;
|
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> {
|
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> {
|
fn interpret(&self, _: &mut World) -> Result<Value, RuntimeError> {
|
||||||
Ok(self.clone().into())
|
Ok(self.clone().into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpret for expression_node::BinaryExpr {
|
impl Interpret for expression::BinaryExpr {
|
||||||
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
||||||
let left_val = self.left.interpret(w).expect("expected lval");
|
let left_val = self.left.interpret(w).expect("expected lval");
|
||||||
let right_val = self.right.interpret(w).expect("expected rval");
|
let right_val = self.right.interpret(w).expect("expected rval");
|
||||||
match self.operator {
|
match self.operator {
|
||||||
expression_node::Operator::BangEqual => Ok((left_val != right_val).into()),
|
Operator::BangEqual => Ok((left_val != right_val).into()),
|
||||||
expression_node::Operator::Less => Ok((left_val < right_val).into()),
|
Operator::Less => Ok((left_val < right_val).into()),
|
||||||
expression_node::Operator::LessEqual => Ok((left_val <= right_val).into()),
|
Operator::LessEqual => Ok((left_val <= right_val).into()),
|
||||||
expression_node::Operator::Greater => Ok((left_val > right_val).into()),
|
Operator::Greater => Ok((left_val > right_val).into()),
|
||||||
expression_node::Operator::GreaterEqual => Ok((left_val >= right_val).into()),
|
Operator::GreaterEqual => Ok((left_val >= right_val).into()),
|
||||||
expression_node::Operator::EqualEqual => Ok((left_val == right_val).into()),
|
Operator::EqualEqual => Ok((left_val == right_val).into()),
|
||||||
expression_node::Operator::Equal => todo!(),
|
Operator::Equal => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpret for expression_node::UnaryExpr {
|
impl Interpret for expression::UnaryExpr {
|
||||||
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
||||||
let val = self.right.interpret(w)?;
|
let val = self.right.interpret(w)?;
|
||||||
match self.operator {
|
match self.operator {
|
||||||
expression_node::UnaryOperator::Bang => Ok(Value::Bool(!val.truthy())),
|
UnaryOperator::Bang => Ok(Value::Bool(!val.truthy())),
|
||||||
expression_node::UnaryOperator::Minus => match val {
|
UnaryOperator::Minus => match val {
|
||||||
Value::Int(i) => Ok(Value::Int(-i)),
|
Value::Int(i) => Ok(Value::Int(-i)),
|
||||||
Value::Float(f) => Ok(Value::Float(-f)),
|
Value::Float(f) => Ok(Value::Float(-f)),
|
||||||
_ => Err(RuntimeError),
|
_ => 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> {
|
fn interpret(&self, w: &mut World) -> Result<Value, RuntimeError> {
|
||||||
self.0.interpret(w)
|
self.0.interpret(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpret for expression_node::VariableExpr {
|
impl Interpret for expression::VariableExpr {
|
||||||
fn interpret(&self, world: &mut World) -> Result<Value, RuntimeError> {
|
fn interpret(&self, world: &mut World) -> Result<Value, RuntimeError> {
|
||||||
match world.get_var(&self.var_name) {
|
match world.get_var(&self.var_name) {
|
||||||
Some(v) => Ok(v.clone()),
|
Some(v) => Ok(v.clone()),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::ast::expression::expression_node;
|
use crate::ast::expression;
|
||||||
use from_variants::FromVariants;
|
use from_variants::FromVariants;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, PartialOrd, Clone, FromVariants)]
|
#[derive(Debug, PartialEq, PartialOrd, Clone, FromVariants)]
|
||||||
|
@ -11,11 +11,11 @@ pub enum Value {
|
||||||
String(String),
|
String(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<expression_node::Literal> for Value {
|
impl From<expression::Literal> for Value {
|
||||||
fn from(l: expression_node::Literal) -> Self {
|
fn from(l: expression::Literal) -> Self {
|
||||||
match_any::match_any!(l,
|
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::Literal::Int(v) | expression::Literal::Bool(v) | expression::Literal::Float(v) | expression::Literal::String(v) => v.into(),
|
||||||
expression_node::Literal::Nil => Self::Nil
|
expression::Literal::Nil => Self::Nil
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue