2022-04-23 15:39:37 +02:00
|
|
|
pub mod expression_node;
|
2022-05-05 19:29:50 +02:00
|
|
|
pub mod operator;
|
|
|
|
|
|
|
|
mod binary_expr;
|
|
|
|
mod block_expr;
|
2022-05-02 12:56:52 +02:00
|
|
|
mod grouping_expr;
|
|
|
|
mod literal_expr;
|
|
|
|
mod unary_expr;
|
|
|
|
mod variable_expr;
|
|
|
|
|
|
|
|
pub use binary_expr::BinaryExpr;
|
2022-05-05 19:29:50 +02:00
|
|
|
pub use block_expr::BlockExpr;
|
2022-05-02 12:56:52 +02:00
|
|
|
pub use grouping_expr::GroupingExpr;
|
|
|
|
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};
|
2022-05-05 19:29:50 +02:00
|
|
|
use itertools::PeekingNext;
|
2022-05-02 12:56:52 +02:00
|
|
|
|
|
|
|
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),
|
2022-05-05 19:29:50 +02:00
|
|
|
BlockExpr(BlockExpr),
|
2022-05-02 12:56:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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) |
|
2022-05-05 19:29:50 +02:00
|
|
|
ExpressionNode::BlockExpr($val_name) |
|
2022-05-02 12:56:52 +02:00
|
|
|
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> {
|
2022-05-05 19:29:50 +02:00
|
|
|
self.block_expr()
|
2022-05-02 12:56:52 +02:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|