The commit adds while loop statements and improves token display formatting: - Implements while loop syntax and evaluation - Adds a new token pretty printing module with configurable formatting - Improves token display with colors and different output modes
333 lines
10 KiB
Rust
333 lines
10 KiB
Rust
use crate::frontend::{
|
|
source_registry::{SourceId, SourcePosition, SourceSlice},
|
|
tokens::{LiteralValue, TokenType},
|
|
};
|
|
use std::fmt::{Debug, Display};
|
|
/*
|
|
* grammar:
|
|
* program -> statement* EOF
|
|
* statement -> expression_statement
|
|
* | print_statement
|
|
* | var_statement
|
|
* | block_statement
|
|
* | assignment_statement
|
|
* | if_statement
|
|
*
|
|
* expression_statement -> expression ";"
|
|
* print_statement -> "print" expression ";"
|
|
* var_statement -> "var" IDENTIFIER ("=" expression)? ";"
|
|
* assignment_statement -> IDENTIFIER "=" expression ";"
|
|
* block_statement -> "do" statement* "end"
|
|
* if_statement -> "if" expression "then" statement ("elif" expression "then" statement)* ("else" statement)? "end"
|
|
* while_statement -> "while" expression "do" statement "end"
|
|
*
|
|
* expression -> assignment
|
|
* assignment -> IDENTIFIER "=" assignment | logical_or
|
|
* logical_or -> logical_and (("or" logical_and)*
|
|
* logical_and -> equality (("and" equality)*
|
|
* equality -> comparison (("==" | "!=") comparison)*
|
|
* comparison -> term ((">" | ">=" | "<" | "<=") term)*
|
|
* term -> factor (("+" | "-") factor)*
|
|
* factor -> unary (("*" | "/") unary)*
|
|
* unary -> ("!" | "-") unary | primary
|
|
* primary -> NUMBER | STRING | "true" | "false" | "nil" | "(" expression ")" | IDENTIFIER
|
|
*/
|
|
#[derive(Clone)]
|
|
pub enum Expr {
|
|
Literal {
|
|
value: LiteralValue,
|
|
},
|
|
Binary {
|
|
left: Box<Expr>,
|
|
operator: TokenType,
|
|
right: Box<Expr>,
|
|
},
|
|
Unary {
|
|
operator: TokenType,
|
|
operand: Box<Expr>,
|
|
},
|
|
Grouping {
|
|
expression: Box<Expr>,
|
|
},
|
|
Variable {
|
|
name: String,
|
|
},
|
|
}
|
|
|
|
pub trait ExprPrint {
|
|
fn print(&self) -> String;
|
|
}
|
|
|
|
impl ExprPrint for Expr {
|
|
fn print(&self) -> String {
|
|
match self {
|
|
Expr::Literal { value } => format!("Literal {}", value),
|
|
Expr::Binary {
|
|
left,
|
|
operator,
|
|
right,
|
|
} => {
|
|
format!("Binary ({} {} {})", left, operator, right)
|
|
}
|
|
Expr::Unary { operator, operand } => {
|
|
format!("Unary ({} {})", operator, operand)
|
|
}
|
|
Expr::Grouping { expression } => {
|
|
format!("Grouping (group {})", expression)
|
|
}
|
|
Expr::Variable { name } => {
|
|
format!("Variable (variable {})", name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Implementazione Display per Expr (per debugging)
|
|
impl std::fmt::Display for Expr {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Expr::Literal { value } => write!(f, "Literal {}", value),
|
|
Expr::Binary {
|
|
left,
|
|
operator,
|
|
right,
|
|
} => write!(f, "Binary ({} {} {})", left, operator, right),
|
|
Expr::Unary { operator, operand } => write!(f, "Unary ({} {})", operator, operand),
|
|
Expr::Grouping { expression } => write!(f, "Grouping (group {})", expression),
|
|
Expr::Variable { name } => write!(f, "Variable (variable {})", name),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Debug for Expr {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Expr::Literal { value } => write!(f, "{:?}", value),
|
|
Expr::Binary {
|
|
left,
|
|
operator,
|
|
right,
|
|
} => write!(f, "({:?} {:?} {:?})", operator, left, right),
|
|
Expr::Unary { operator, operand } => write!(f, "({:?} {:?})", operator, operand),
|
|
Expr::Grouping { expression } => write!(f, "(group {:?})", expression),
|
|
Expr::Variable { name } => write!(f, "(variable {:?})", name),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub enum Stmt {
|
|
Expression {
|
|
expression: Box<Expr>,
|
|
},
|
|
Print {
|
|
expression: Box<Expr>,
|
|
},
|
|
Stmt {
|
|
expression: Box<Expr>,
|
|
},
|
|
Var {
|
|
name: String,
|
|
initializer: Option<Box<Expr>>,
|
|
},
|
|
Assign {
|
|
name: String,
|
|
value: Box<Expr>,
|
|
},
|
|
Return {
|
|
expression: Box<Expr>,
|
|
},
|
|
Block {
|
|
statements: Box<Vec<Stmt>>,
|
|
},
|
|
If {
|
|
condition: Box<Expr>,
|
|
then_branch: Box<Stmt>,
|
|
elif_branch: Vec<(Box<Expr>, Box<Stmt>)>,
|
|
else_branch: Option<Box<Stmt>>,
|
|
},
|
|
While {
|
|
condition: Box<Expr>,
|
|
body: Box<Stmt>,
|
|
},
|
|
For {
|
|
variable: Box<Expr>,
|
|
iterable: Box<Expr>,
|
|
body: Box<Stmt>,
|
|
},
|
|
}
|
|
|
|
impl Display for Stmt {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Stmt::Expression { expression } => write!(f, "Expression ({})", expression),
|
|
Stmt::If {
|
|
condition,
|
|
then_branch,
|
|
elif_branch,
|
|
else_branch,
|
|
} => {
|
|
let mut result = format!("IF ({}) {{\n{}\n}}", condition, then_branch);
|
|
for (condition, branch) in elif_branch {
|
|
result.push_str(&format!(" ELIF ({}) {{\n{}\n}}", condition, branch));
|
|
}
|
|
if let Some(else_branch) = else_branch {
|
|
result.push_str(&format!(" ELSE {{\n{}\n}}", else_branch));
|
|
}
|
|
write!(f, "IfStmt {}", result)
|
|
}
|
|
Stmt::Print { expression } => write!(f, "Print({});", expression),
|
|
Stmt::Stmt { expression } => write!(f, "Stmt({});", expression),
|
|
Stmt::Var { name, initializer } => {
|
|
write!(f, "Var({} = {:?});", name, initializer)
|
|
}
|
|
Stmt::Assign { name, value } => write!(f, "Assign({} = {});", name, value),
|
|
Stmt::Return { expression } => write!(f, "Return({});", expression),
|
|
Stmt::Block { statements } => write!(
|
|
f,
|
|
"Block([\n{}\n])",
|
|
statements
|
|
.iter()
|
|
.map(|stmt| format!("\t \t{}", stmt))
|
|
.collect::<Vec<_>>()
|
|
.join("\n")
|
|
),
|
|
Stmt::While { condition, body } => todo!(),
|
|
Stmt::For {
|
|
variable,
|
|
iterable,
|
|
body,
|
|
} => todo!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Debug for Stmt {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Stmt::Expression { expression } => write!(f, " Expression ({:?})", expression),
|
|
Stmt::If {
|
|
condition,
|
|
then_branch,
|
|
elif_branch,
|
|
else_branch,
|
|
} => {
|
|
let mut result = format!("IF ({:?}) {{\n{:?}\n}}", condition, then_branch);
|
|
for (condition, branch) in elif_branch {
|
|
result.push_str(&format!(" ELIF ({:?}) {{\n{:?}\n}}", condition, branch));
|
|
}
|
|
if let Some(else_branch) = else_branch {
|
|
result.push_str(&format!(" ELSE {{\n{:?}\n}}", else_branch));
|
|
}
|
|
write!(f, "IfStmt {:?}", result)
|
|
}
|
|
Stmt::Print { expression } => write!(f, "Print({:?});", expression),
|
|
Stmt::Stmt { expression } => write!(f, "Stmt({:?});", expression),
|
|
Stmt::Var { name, initializer } => {
|
|
write!(f, "Var({:?} = {:?});", name, initializer)
|
|
}
|
|
Stmt::Assign { name, value } => write!(f, "Assign({:?} = {:?});", name, value),
|
|
Stmt::Return { expression } => write!(f, "Return({:?});", expression),
|
|
Stmt::Block { statements } => write!(
|
|
f,
|
|
"Block([\n{:?}\n])",
|
|
statements
|
|
.iter()
|
|
.map(|stmt| format!("{:?}", stmt))
|
|
.collect::<Vec<_>>()
|
|
.join("\t\t\n")
|
|
),
|
|
Stmt::While { condition, body } => todo!(),
|
|
Stmt::For {
|
|
variable,
|
|
iterable,
|
|
body,
|
|
} => todo!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub trait AstNodeKind {
|
|
fn kind(&self) -> &'static str;
|
|
}
|
|
|
|
impl AstNodeKind for Expr {
|
|
fn kind(&self) -> &'static str {
|
|
match self {
|
|
Expr::Literal { value: _ } => "literal",
|
|
Expr::Binary {
|
|
left: _,
|
|
operator: _,
|
|
right: _,
|
|
} => "binary expression",
|
|
Expr::Unary {
|
|
operator: _,
|
|
operand: _,
|
|
} => "unary expression",
|
|
Expr::Grouping { expression: _ } => "grouping expression",
|
|
Expr::Variable { name: _ } => "variable expression",
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AstNodeKind for Stmt {
|
|
fn kind(&self) -> &'static str {
|
|
match self {
|
|
Stmt::Expression { expression: _ } => "expression",
|
|
Stmt::Var {
|
|
name: _,
|
|
initializer: _,
|
|
} => "variable declaration",
|
|
Stmt::Assign { name: _, value: _ } => "assignment",
|
|
Stmt::Return { expression: _ } => "return statement",
|
|
Stmt::Block { statements: _ } => "block statement",
|
|
Stmt::If {
|
|
condition: _,
|
|
then_branch: _,
|
|
elif_branch: _,
|
|
else_branch: _,
|
|
} => "if statement",
|
|
Stmt::Print { expression: _ } => "print statement",
|
|
Stmt::Stmt { expression: _ } => "statement",
|
|
Stmt::While { condition, body } => todo!(),
|
|
Stmt::For {
|
|
variable,
|
|
iterable,
|
|
body,
|
|
} => todo!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, PartialEq)]
|
|
pub struct AstNode<T: AstNodeKind + Debug + Display> {
|
|
pub node: T,
|
|
pub source_slice: SourceSlice,
|
|
}
|
|
|
|
impl<T: AstNodeKind + Debug + Display> Display for AstNode<T> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"AstNode \n{{ \n\tnode: {},\n\tsource_slice: {}, \n}}",
|
|
self.node, self.source_slice
|
|
)
|
|
}
|
|
}
|
|
|
|
impl<T: AstNodeKind + Debug + Display> Debug for AstNode<T> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"AstNode \n{{ \n\tnode: {:?},\n\tsource_slice: {:?}, \n}}",
|
|
self.node, self.source_slice
|
|
)
|
|
}
|
|
}
|
|
|
|
impl<T: AstNodeKind + Debug + Display> AstNode<T> {
|
|
pub fn new(node: T, source_slice: SourceSlice) -> Self {
|
|
AstNode { node, source_slice }
|
|
}
|
|
}
|