Initialize Rust implementation of Lox interpreter
This initial commit sets up the basic structure for a Rust implementation of the Lox interpreter, including: - Lexer for tokenizing source code - Parser for building AST - Basic interpreter functionality - Environment for variable storage The core components include source tracking, error handling, and basic expression evaluation.
This commit is contained in:
@@ -0,0 +1,304 @@
|
||||
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"
|
||||
*
|
||||
* 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>>,
|
||||
},
|
||||
}
|
||||
|
||||
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")
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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 }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user