Affectation de variable
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use crate::expr::{Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable};
|
||||
use crate::expr::{Assign, Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable};
|
||||
use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor, VarStatement};
|
||||
|
||||
pub struct ASTPrinter {
|
||||
@@ -59,12 +59,21 @@ impl ExprVisitor<()> for ASTPrinter {
|
||||
Expr::LiteralExpr(l) => { self.visit_literal(l); }
|
||||
Expr::UnaryExpr(u) => { self.visit_unary(u); }
|
||||
Expr::VariableExpr(v) => { self.visit_variable(v); }
|
||||
Expr::AssignExpr(a) => { self.visit_assign(a); }
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_variable(&mut self, v: &Variable) -> () {
|
||||
println!("{}VARIABLE(name={})", self.ast_tab(), v.name.literal);
|
||||
}
|
||||
|
||||
fn visit_assign(&mut self, a: &Assign) -> () {
|
||||
println!("{}ASSIGN(var={}", self.ast_tab(), a.name);
|
||||
self.depth+=1;
|
||||
self.visit_expr(&a.value);
|
||||
self.depth-=1;
|
||||
print!(") ");
|
||||
}
|
||||
}
|
||||
|
||||
impl StatementVisitor<()> for ASTPrinter {
|
||||
|
||||
@@ -23,4 +23,13 @@ impl Environment {
|
||||
None => { Err(RuntimeError { message: format!("Variable {} non définie", name) } ) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assign(&mut self, name: String, value: Literal) -> Result<(), RuntimeError> {
|
||||
if self.values.contains_key(&name) {
|
||||
self.values.insert(name, value);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(RuntimeError { message: String::from("Undefined variable")})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,11 @@
|
||||
use crate::token::Token;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Assign {
|
||||
pub name: Token,
|
||||
pub value: Box<Expr>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Binary {
|
||||
pub left: Box<Expr>,
|
||||
@@ -38,6 +44,7 @@ pub enum Expr {
|
||||
LiteralExpr(Literal),
|
||||
UnaryExpr(Unary),
|
||||
VariableExpr(Variable),
|
||||
AssignExpr(Assign),
|
||||
}
|
||||
|
||||
pub trait ExprVisitor<T> {
|
||||
@@ -47,5 +54,6 @@ pub trait ExprVisitor<T> {
|
||||
fn visit_unary(&mut self, u: &Unary) -> T;
|
||||
fn visit_expr(&mut self, e: &Expr) -> T;
|
||||
fn visit_variable(&mut self, v: &Variable) -> T;
|
||||
fn visit_assign(&mut self, a: &Assign) -> T;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
use crate::environment::Environment;
|
||||
use crate::expr::Expr::UnaryExpr;
|
||||
use crate::expr::Expr::LiteralExpr;
|
||||
use crate::expr::Expr::GroupingExpr;
|
||||
use crate::expr::Expr::BinaryExpr;
|
||||
use crate::expr::Expr::VariableExpr;
|
||||
use crate::expr::Literal::LiteralString;
|
||||
use crate::expr::Literal::LiteralNumber;
|
||||
use crate::expr::Literal::LiteralBool;
|
||||
use crate::expr::Literal::LiteralNil;
|
||||
use crate::expr::{Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable};
|
||||
use crate::expr::{Assign, Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable};
|
||||
use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor, VarStatement};
|
||||
use crate::token_type::TokenType;
|
||||
|
||||
@@ -153,14 +148,22 @@ impl ExprVisitor<Result<Literal, RuntimeError>> for Interpreter {
|
||||
|
||||
fn visit_expr(&mut self, e: &Expr) -> Result<Literal, RuntimeError> {
|
||||
match e {
|
||||
BinaryExpr(b) => { Ok(self.visit_binary(&b)?) }
|
||||
GroupingExpr(g) => { Ok(self.visit_grouping(&g)?) }
|
||||
LiteralExpr(l) => { Ok(self.visit_literal(&l)?) }
|
||||
UnaryExpr(u) => { Ok(self.visit_unary(&u)?) }
|
||||
VariableExpr(v) => { Ok(self.visit_variable(&v)? )}
|
||||
Expr::BinaryExpr(b) => { Ok(self.visit_binary(&b)?) }
|
||||
Expr::GroupingExpr(g) => { Ok(self.visit_grouping(&g)?) }
|
||||
Expr::LiteralExpr(l) => { Ok(self.visit_literal(&l)?) }
|
||||
Expr::UnaryExpr(u) => { Ok(self.visit_unary(&u)?) }
|
||||
Expr::VariableExpr(v) => { Ok(self.visit_variable(&v)?) }
|
||||
Expr::AssignExpr(a) => { Ok(self.visit_assign(&a)?) }
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_assign(&mut self, a: &Assign) -> Result<Literal, RuntimeError> {
|
||||
let value = self.visit_expr(&a.value)?;
|
||||
self.environment.assign(a.name.literal.clone(), value.clone())?;
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn visit_variable(&mut self, v: &Variable) -> Result<Literal, RuntimeError> {
|
||||
self.environment.get(&v.name.literal)
|
||||
}
|
||||
|
||||
@@ -103,4 +103,4 @@ fn run(src: String) -> i32 {
|
||||
// https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations#rust
|
||||
|
||||
// Pause :
|
||||
// http://www.craftinginterpreters.com/statements-and-state.html#global-variables
|
||||
// http://www.craftinginterpreters.com/statements-and-state.html#assignment
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::expr::{Binary, Expr, Grouping, Unary, Variable};
|
||||
use crate::expr::{Assign, Binary, Expr, Grouping, Unary, Variable};
|
||||
use crate::expr::Literal::{LiteralBool, LiteralNumber, LiteralString};
|
||||
use crate::token::Token;
|
||||
use crate::token_type::TokenType;
|
||||
@@ -93,7 +93,24 @@ impl Parser {
|
||||
}
|
||||
|
||||
fn expression(&mut self) -> Result<Expr, ParseError> {
|
||||
self.equality()
|
||||
self.assignment()
|
||||
}
|
||||
|
||||
fn assignment(&mut self) -> Result<Expr, ParseError> {
|
||||
let expr = self.equality()?;
|
||||
|
||||
if self.match_token(&[TokenType::Equal]) {
|
||||
let value = Box::new(self.assignment()?); // l'assignation a une associativité par la droite
|
||||
|
||||
match expr {
|
||||
Expr::VariableExpr(v) => {
|
||||
Ok( Expr::AssignExpr(Assign { name: v.name, value }))
|
||||
}
|
||||
_ => Err(ParseError { message: String::from("Invalid assignment target") })
|
||||
}
|
||||
} else {
|
||||
Ok(expr)
|
||||
}
|
||||
}
|
||||
|
||||
fn equality(&mut self) -> Result<Expr, ParseError> {
|
||||
|
||||
Reference in New Issue
Block a user