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};
|
use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor, VarStatement};
|
||||||
|
|
||||||
pub struct ASTPrinter {
|
pub struct ASTPrinter {
|
||||||
@@ -59,12 +59,21 @@ impl ExprVisitor<()> for ASTPrinter {
|
|||||||
Expr::LiteralExpr(l) => { self.visit_literal(l); }
|
Expr::LiteralExpr(l) => { self.visit_literal(l); }
|
||||||
Expr::UnaryExpr(u) => { self.visit_unary(u); }
|
Expr::UnaryExpr(u) => { self.visit_unary(u); }
|
||||||
Expr::VariableExpr(v) => { self.visit_variable(v); }
|
Expr::VariableExpr(v) => { self.visit_variable(v); }
|
||||||
|
Expr::AssignExpr(a) => { self.visit_assign(a); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_variable(&mut self, v: &Variable) -> () {
|
fn visit_variable(&mut self, v: &Variable) -> () {
|
||||||
println!("{}VARIABLE(name={})", self.ast_tab(), v.name.literal);
|
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 {
|
impl StatementVisitor<()> for ASTPrinter {
|
||||||
|
|||||||
@@ -23,4 +23,13 @@ impl Environment {
|
|||||||
None => { Err(RuntimeError { message: format!("Variable {} non définie", name) } ) }
|
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;
|
use crate::token::Token;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Assign {
|
||||||
|
pub name: Token,
|
||||||
|
pub value: Box<Expr>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Binary {
|
pub struct Binary {
|
||||||
pub left: Box<Expr>,
|
pub left: Box<Expr>,
|
||||||
@@ -38,6 +44,7 @@ pub enum Expr {
|
|||||||
LiteralExpr(Literal),
|
LiteralExpr(Literal),
|
||||||
UnaryExpr(Unary),
|
UnaryExpr(Unary),
|
||||||
VariableExpr(Variable),
|
VariableExpr(Variable),
|
||||||
|
AssignExpr(Assign),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ExprVisitor<T> {
|
pub trait ExprVisitor<T> {
|
||||||
@@ -47,5 +54,6 @@ pub trait ExprVisitor<T> {
|
|||||||
fn visit_unary(&mut self, u: &Unary) -> T;
|
fn visit_unary(&mut self, u: &Unary) -> T;
|
||||||
fn visit_expr(&mut self, e: &Expr) -> T;
|
fn visit_expr(&mut self, e: &Expr) -> T;
|
||||||
fn visit_variable(&mut self, v: &Variable) -> 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::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::LiteralString;
|
||||||
use crate::expr::Literal::LiteralNumber;
|
use crate::expr::Literal::LiteralNumber;
|
||||||
use crate::expr::Literal::LiteralBool;
|
use crate::expr::Literal::LiteralBool;
|
||||||
use crate::expr::Literal::LiteralNil;
|
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::stmt::{ExpressionStatement, PrintStatement, StatementVisitor, VarStatement};
|
||||||
use crate::token_type::TokenType;
|
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> {
|
fn visit_expr(&mut self, e: &Expr) -> Result<Literal, RuntimeError> {
|
||||||
match e {
|
match e {
|
||||||
BinaryExpr(b) => { Ok(self.visit_binary(&b)?) }
|
Expr::BinaryExpr(b) => { Ok(self.visit_binary(&b)?) }
|
||||||
GroupingExpr(g) => { Ok(self.visit_grouping(&g)?) }
|
Expr::GroupingExpr(g) => { Ok(self.visit_grouping(&g)?) }
|
||||||
LiteralExpr(l) => { Ok(self.visit_literal(&l)?) }
|
Expr::LiteralExpr(l) => { Ok(self.visit_literal(&l)?) }
|
||||||
UnaryExpr(u) => { Ok(self.visit_unary(&u)?) }
|
Expr::UnaryExpr(u) => { Ok(self.visit_unary(&u)?) }
|
||||||
VariableExpr(v) => { Ok(self.visit_variable(&v)? )}
|
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> {
|
fn visit_variable(&mut self, v: &Variable) -> Result<Literal, RuntimeError> {
|
||||||
self.environment.get(&v.name.literal)
|
self.environment.get(&v.name.literal)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,4 +103,4 @@ fn run(src: String) -> i32 {
|
|||||||
// https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations#rust
|
// https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations#rust
|
||||||
|
|
||||||
// Pause :
|
// 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::expr::Literal::{LiteralBool, LiteralNumber, LiteralString};
|
||||||
use crate::token::Token;
|
use crate::token::Token;
|
||||||
use crate::token_type::TokenType;
|
use crate::token_type::TokenType;
|
||||||
@@ -93,7 +93,24 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn expression(&mut self) -> Result<Expr, ParseError> {
|
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> {
|
fn equality(&mut self) -> Result<Expr, ParseError> {
|
||||||
|
|||||||
Reference in New Issue
Block a user