rust-crafting-interpreters-.../src/ast.rs

153 lines
4.3 KiB
Rust
Raw Normal View History

use crate::tokens::Token;
2022-12-30 23:50:02 +01:00
2022-12-31 14:36:01 +01:00
/* --------- *
* AST nodes *
* --------- */
/// The AST node for the program
#[derive(Default, Debug, Clone)]
pub struct ProgramNode(pub Vec<StmtNode>);
2022-12-31 14:36:01 +01:00
/// An AST node that represents a statement.
#[derive(Debug, Clone)]
pub enum StmtNode {
2022-12-31 15:30:53 +01:00
/// A variable declaration
VarDecl(Token, Option<ExprNode>),
2022-12-31 14:36:01 +01:00
/// An single expression
Expression(ExprNode),
/// The print statement
Print(ExprNode),
2022-12-31 16:58:48 +01:00
/// A block containing multiple statements.
Block(Vec<Box<StmtNode>>),
2023-01-01 10:58:45 +01:00
/// A conditional statement.
IfStmt {
condition: ExprNode,
then_branch: Box<StmtNode>,
else_branch: Option<Box<StmtNode>>,
},
2023-01-01 18:33:45 +01:00
/// While loop statement.
WhileStmt {
condition: ExprNode,
body: Box<StmtNode>,
},
2022-12-31 14:36:01 +01:00
}
2022-12-30 23:50:02 +01:00
/// An AST node that represents an expression.
#[derive(Debug, Clone)]
pub enum ExprNode {
2022-12-31 16:16:12 +01:00
/// Assignment to a variable.
Assignment { name: Token, value: Box<ExprNode> },
2023-01-01 11:13:41 +01:00
/// Logical binary expression.
Logical {
left: Box<ExprNode>,
operator: Token,
right: Box<ExprNode>,
},
2022-12-30 23:50:02 +01:00
/// Binary expression.
Binary {
left: Box<ExprNode>,
operator: Token,
right: Box<ExprNode>,
},
/// Unary expression.
Unary {
operator: Token,
right: Box<ExprNode>,
},
/// Grouping expression, containing a sub-expression.
Grouping { expression: Box<ExprNode> },
/// A litteral value, represented by the corresponding token.
Litteral { value: Token },
2022-12-31 15:42:10 +01:00
/// A reference to a variable.
Variable { name: Token },
2022-12-30 23:50:02 +01:00
}
/* -------------------------------- *
* Dumper trait and implementations *
* -------------------------------- */
/// This trait should be implemented by nodes to allow AST dumps.
pub trait AstDumper {
/// Dump the node as a string.
fn dump(&self) -> String;
}
2022-12-31 14:36:01 +01:00
impl AstDumper for ProgramNode {
fn dump(&self) -> String {
self.0
.iter()
.map(|node| node.dump())
.collect::<Vec<String>>()
.join(" ")
}
}
impl AstDumper for StmtNode {
fn dump(&self) -> String {
match self {
Self::VarDecl(name, Some(expr)) => format!("( var {} {} )", name.lexeme, expr.dump()),
Self::VarDecl(name, None) => format!("( var {} nil )", name.lexeme),
2022-12-31 14:36:01 +01:00
Self::Expression(expr) => format!("( {} )", expr.dump()),
Self::Print(expr) => format!("(print {})", expr.dump()),
2023-01-01 10:58:45 +01:00
2022-12-31 16:58:48 +01:00
Self::Block(stmts) => stmts
.iter()
.map(|s| s.dump())
.collect::<Vec<String>>()
.join(" "),
2023-01-01 10:58:45 +01:00
Self::IfStmt {
condition,
then_branch,
else_branch,
} => match else_branch {
None => format!("( if {} {} () )", condition.dump(), then_branch.dump()),
Some(stmt) => format!(
"( if {} {} {} )",
condition.dump(),
then_branch.dump(),
stmt.dump()
),
},
2023-01-01 18:33:45 +01:00
Self::WhileStmt { condition, body } => {
format!("( while {} {} )", condition.dump(), body.dump())
}
2022-12-31 14:36:01 +01:00
}
}
}
2022-12-30 23:50:02 +01:00
impl AstDumper for ExprNode {
fn dump(&self) -> String {
match self {
2022-12-31 16:16:12 +01:00
Self::Assignment { name, value } => format!("( = {} {} )", name.lexeme, value.dump()),
2023-01-01 11:13:41 +01:00
Self::Logical {
left,
operator,
right,
} => format!("( {} {} {} )", operator.lexeme, left.dump(), right.dump()),
2022-12-30 23:50:02 +01:00
Self::Binary {
left,
operator,
right,
2022-12-31 15:42:10 +01:00
} => format!("( {} {} {} )", operator.lexeme, left.dump(), right.dump()),
Self::Unary { operator, right } => format!("( {} {} )", operator.lexeme, right.dump()),
Self::Grouping { expression } => format!("( {} )", expression.dump()),
Self::Variable { name } => name.lexeme.clone(),
Self::Litteral { value } => {
if value.is_litteral() {
value.lexeme.clone()
} else {
panic!("Unexpected token type for token {:#?}", value)
}
}
2022-12-30 23:50:02 +01:00
}
}
}