Ajout des If, des opérateurs logiques et des boucles While
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::expr::{Assign, Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable};
|
||||
use crate::stmt::{BlockStatement, ExpressionStatement, PrintStatement, Statement, StatementVisitor, VarStatement};
|
||||
use crate::expr::{Assign, Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable, Logical};
|
||||
use crate::stmt::{BlockStatement, ExpressionStatement, PrintStatement, Statement, StatementVisitor, VarStatement, IfStatement, WhileStatement};
|
||||
|
||||
pub struct ASTPrinter {
|
||||
pub(crate) depth: u32
|
||||
@@ -60,6 +60,7 @@ impl ExprVisitor<()> for ASTPrinter {
|
||||
Expr::UnaryExpr(u) => { self.visit_unary(u); }
|
||||
Expr::VariableExpr(v) => { self.visit_variable(v); }
|
||||
Expr::AssignExpr(a) => { self.visit_assign(a); }
|
||||
Expr::LogicalExpr(l) => { self.visit_logical(l); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +75,21 @@ impl ExprVisitor<()> for ASTPrinter {
|
||||
self.depth-=1;
|
||||
print!(") ");
|
||||
}
|
||||
|
||||
fn visit_logical(&mut self, l: &Logical) {
|
||||
println!("{}LOGICAL",self.ast_tab());
|
||||
println!("{}op='{}'", self.ast_tab(), l.operator.lexeme);
|
||||
println!("{}left=(", self.ast_tab());
|
||||
self.depth+=1;
|
||||
self.visit_expr(&*l.left);
|
||||
self.depth-=1;
|
||||
println!("{})", self.ast_tab());
|
||||
println!("{}right=(", self.ast_tab());
|
||||
self.depth+=1;
|
||||
self.visit_expr(&*l.right);
|
||||
self.depth-=1;
|
||||
println!("{})", self.ast_tab());
|
||||
}
|
||||
}
|
||||
|
||||
impl StatementVisitor<()> for ASTPrinter {
|
||||
@@ -117,12 +133,63 @@ impl StatementVisitor<()> for ASTPrinter {
|
||||
print!(") ");
|
||||
}
|
||||
|
||||
fn visit_if_stmt(&mut self, i: &IfStatement) -> () {
|
||||
println!("{} IF_STMT(", self.ast_tab());
|
||||
self.depth+=1;
|
||||
|
||||
println!("{} IF_EXPR(", self.ast_tab());
|
||||
self.depth+=1;
|
||||
self.visit_expr(&i.expr);
|
||||
self.depth-=1;
|
||||
println!("{} )", self.ast_tab());
|
||||
|
||||
println!("{} IF_THEN(", self.ast_tab());
|
||||
self.depth+=1;
|
||||
self.visit_stmt(&i.statement_then);
|
||||
self.depth-=1;
|
||||
println!("{} )", self.ast_tab());
|
||||
|
||||
match i.statement_else.clone() {
|
||||
Some(s) => {
|
||||
println!("{} IF_ELSE(", self.ast_tab());
|
||||
self.depth+=1;
|
||||
self.visit_stmt(&s);
|
||||
self.depth-=1;
|
||||
println!("{} )", self.ast_tab());
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
self.depth-=1;
|
||||
print!(") ");
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, s: &Statement) -> () {
|
||||
match s {
|
||||
Statement::Expression(e) => { self.visit_expr_stmt(&e) }
|
||||
Statement::Print(p) => { self.visit_print(&p) }
|
||||
Statement::Var(v) => { self.visit_var_stmt(&v) }
|
||||
Statement::Block(b) => { self.visit_block_stmt(&b) }
|
||||
Statement::If(i) => { self.visit_if_stmt(&i) }
|
||||
Statement::While(w) => { self.visit_while_stmt(&w) }
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_while_stmt(&mut self, w: &WhileStatement) -> () {
|
||||
println!("{} WHILE_STMT(", self.ast_tab());
|
||||
self.depth+=1;
|
||||
|
||||
println!("{} WHILE_COND(", self.ast_tab());
|
||||
self.depth+=1;
|
||||
self.visit_expr(&w.condition);
|
||||
self.depth-=1;
|
||||
println!("{} )", self.ast_tab());
|
||||
|
||||
println!("{} WHILE_BODY(", self.ast_tab());
|
||||
self.depth+=1;
|
||||
self.visit_stmt(&w.body);
|
||||
self.depth-=1;
|
||||
println!("{} )", self.ast_tab());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -37,11 +37,19 @@ pub struct Variable {
|
||||
pub name: Token,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Logical {
|
||||
pub left: Box<Expr>,
|
||||
pub operator: Token,
|
||||
pub right: Box<Expr>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Expr {
|
||||
BinaryExpr(Binary),
|
||||
GroupingExpr(Grouping),
|
||||
LiteralExpr(Literal),
|
||||
LogicalExpr(Logical),
|
||||
UnaryExpr(Unary),
|
||||
VariableExpr(Variable),
|
||||
AssignExpr(Assign),
|
||||
@@ -55,5 +63,6 @@ pub trait ExprVisitor<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;
|
||||
fn visit_logical(&mut self, l: &Logical) -> T;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ use crate::expr::Literal::LiteralString;
|
||||
use crate::expr::Literal::LiteralNumber;
|
||||
use crate::expr::Literal::LiteralBool;
|
||||
use crate::expr::Literal::LiteralNil;
|
||||
use crate::expr::{Assign, Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable};
|
||||
use crate::stmt::{BlockStatement, ExpressionStatement, PrintStatement, Statement, StatementVisitor, VarStatement};
|
||||
use crate::expr::{Assign, Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable, Logical};
|
||||
use crate::stmt::{BlockStatement, ExpressionStatement, IfStatement, PrintStatement, Statement, StatementVisitor, VarStatement, WhileStatement};
|
||||
use crate::token_type::TokenType;
|
||||
|
||||
pub struct Interpreter {
|
||||
@@ -18,15 +18,16 @@ impl Interpreter {
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_block( &mut self, statements: &Vec<Statement>, env: &Environment ) {
|
||||
let previous = self.environment.clone();
|
||||
fn execute_block( &mut self, statements: &Vec<Statement> ) {
|
||||
let new_env = Environment::new(Some(Box::new(self.environment.clone())));
|
||||
self.environment = new_env;
|
||||
|
||||
self.environment = (*env).clone();
|
||||
for s in statements {
|
||||
self.visit_stmt(s);
|
||||
}
|
||||
|
||||
self.environment = previous;
|
||||
let old_env = self.environment.clone().enclosing.unwrap();
|
||||
self.environment = *old_env;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +133,23 @@ impl ExprVisitor<Result<Literal, RuntimeError>> for Interpreter {
|
||||
TokenType::Or => { Err(RuntimeError { message: String::from("Pas encore implémenté.") }) }
|
||||
_ => { panic!("Parsing error") }
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_logical(&mut self, l: &Logical) -> Result<Literal, RuntimeError> {
|
||||
let left = self.visit_expr(&*l.left)?;
|
||||
if l.operator.token_type==TokenType::Or {
|
||||
if is_truthy(&left) {
|
||||
Ok(left)
|
||||
} else {
|
||||
Ok(self.visit_expr(&*l.right)?)
|
||||
}
|
||||
} else {
|
||||
if !is_truthy(&left) {
|
||||
Ok(left)
|
||||
} else {
|
||||
Ok(self.visit_expr(&*l.right)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_grouping(&mut self, g: &Grouping) -> Result<Literal, RuntimeError> {
|
||||
@@ -165,6 +182,7 @@ impl ExprVisitor<Result<Literal, RuntimeError>> for Interpreter {
|
||||
Expr::UnaryExpr(u) => { Ok(self.visit_unary(&u)?) }
|
||||
Expr::VariableExpr(v) => { Ok(self.visit_variable(&v)?) }
|
||||
Expr::AssignExpr(a) => { Ok(self.visit_assign(&a)?) }
|
||||
Expr::LogicalExpr(l) => { Ok(self.visit_logical(&l)?) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +205,8 @@ impl StatementVisitor<()> for Interpreter {
|
||||
Statement::Print(p) => { self.visit_print(p); }
|
||||
Statement::Var(v) => { self.visit_var_stmt(v); }
|
||||
Statement::Block(b) => { self.visit_block_stmt(b); }
|
||||
Statement::If(b) => { self.visit_if_stmt(b); }
|
||||
Statement::While(w) => { self.visit_while_stmt(w); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,9 +237,24 @@ impl StatementVisitor<()> for Interpreter {
|
||||
}
|
||||
|
||||
fn visit_block_stmt(&mut self, b: &BlockStatement) {
|
||||
let mut new_env = Environment::new(Some(Box::new(self.environment.clone())));
|
||||
self.execute_block(&b.statements );
|
||||
}
|
||||
|
||||
self.execute_block(&b.statements, &new_env );
|
||||
fn visit_if_stmt(&mut self, i: &IfStatement) {
|
||||
if is_truthy( &&self.visit_expr(&i.expr).unwrap()) {
|
||||
self.visit_stmt(& i.statement_then);
|
||||
} else {
|
||||
match &i.statement_else {
|
||||
Some(stmt_else) => { self.visit_stmt(stmt_else); }
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_while_stmt(&mut self, w: &WhileStatement) -> () {
|
||||
while is_truthy( &&self.visit_expr(&w.condition).unwrap()) {
|
||||
self.visit_stmt(& w.body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,4 +95,4 @@ fn run(src: String) -> i32 {
|
||||
// https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations#rust
|
||||
|
||||
// Pause :
|
||||
// http://www.craftinginterpreters.com/control-flow.html
|
||||
// https://www.craftinginterpreters.com/control-flow.html#for-loops
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use crate::expr::{Assign, Binary, Expr, Grouping, Unary, Variable};
|
||||
use crate::expr::{Assign, Binary, Expr, Grouping, Unary, Variable, Logical};
|
||||
use crate::expr::Expr::LogicalExpr;
|
||||
use crate::expr::Literal::{LiteralBool, LiteralNumber, LiteralString};
|
||||
use crate::token::Token;
|
||||
use crate::token_type::TokenType;
|
||||
use crate::stmt::{BlockStatement, ExpressionStatement, PrintStatement, Statement, VarStatement};
|
||||
use crate::stmt::{BlockStatement, ExpressionStatement, PrintStatement, Statement, VarStatement, IfStatement, WhileStatement};
|
||||
|
||||
pub struct Parser {
|
||||
tokens: Vec<Token>,
|
||||
@@ -96,8 +97,40 @@ impl Parser {
|
||||
self.assignment()
|
||||
}
|
||||
|
||||
fn or(&mut self) -> Result<Expr, ParseError> {
|
||||
let mut expr = self.and()?;
|
||||
|
||||
while self.match_token(&[TokenType::Or]) {
|
||||
let operator = self.previous();
|
||||
let right = self.and()?;
|
||||
expr = Expr::LogicalExpr(Logical{
|
||||
left: Box::new(expr),
|
||||
operator,
|
||||
right: Box::new(right)
|
||||
});
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
fn and(&mut self) -> Result<Expr, ParseError> {
|
||||
let mut expr = self.equality()?;
|
||||
|
||||
while self.match_token(&[TokenType::And]) {
|
||||
let operator = self.previous();
|
||||
let right = self.equality()?;
|
||||
expr = Expr::LogicalExpr(Logical{
|
||||
left: Box::new(expr),
|
||||
operator,
|
||||
right: Box::new(right)
|
||||
});
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
fn assignment(&mut self) -> Result<Expr, ParseError> {
|
||||
let expr = self.equality()?;
|
||||
let expr = self.or()?;
|
||||
|
||||
if self.match_token(&[TokenType::Equal]) {
|
||||
let value = Box::new(self.assignment()?); // l'assignation a une associativité par la droite
|
||||
@@ -126,7 +159,7 @@ impl Parser {
|
||||
});
|
||||
}
|
||||
|
||||
return Ok(expr);
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
fn comparison(&mut self) -> Result<Expr, ParseError> {
|
||||
@@ -224,10 +257,18 @@ impl Parser {
|
||||
}
|
||||
|
||||
fn statement(&mut self) -> Result<Statement, ParseError> {
|
||||
if self.match_token(&[TokenType::If]) {
|
||||
return self.if_statement();
|
||||
}
|
||||
|
||||
if self.match_token(&[TokenType::Print]) {
|
||||
return self.print_statement();
|
||||
}
|
||||
|
||||
if self.match_token(&[TokenType::While]) {
|
||||
return self.while_statement();
|
||||
}
|
||||
|
||||
if self.match_token(&[TokenType::LeftBrace]) {
|
||||
return self.block_statement();
|
||||
}
|
||||
@@ -257,6 +298,28 @@ impl Parser {
|
||||
}
|
||||
}
|
||||
|
||||
fn while_statement(&mut self) -> Result<Statement, ParseError> {
|
||||
self.consume(&TokenType::LeftParen, String::from("( attendu"))?;
|
||||
let condition = self.expression()?;
|
||||
self.consume(&TokenType::RightParen, String::from(") attendu"))?;
|
||||
let body = self.statement()?;
|
||||
|
||||
Ok(Statement::While(WhileStatement{ condition, body: Box::new(body) }))
|
||||
}
|
||||
|
||||
fn if_statement(&mut self) -> Result<Statement, ParseError> {
|
||||
self.consume(&TokenType::LeftParen, String::from("( attendu"))?;
|
||||
let expr = self.expression()?;
|
||||
self.consume(&TokenType::RightParen, String::from(") attendu"))?;
|
||||
let then_stmt = self.statement()?;
|
||||
if self.match_token(&[TokenType::Else]) {
|
||||
let else_stmt = self.statement()?;
|
||||
Ok(Statement::If(IfStatement{ expr, statement_then: Box::new(then_stmt), statement_else: Some(Box::new(else_stmt))}))
|
||||
} else {
|
||||
Ok(Statement::If(IfStatement{ expr, statement_then: Box::new(then_stmt), statement_else: None}))
|
||||
}
|
||||
}
|
||||
|
||||
fn expr_statement(&mut self) -> Result<Statement, ParseError> {
|
||||
match self.expression() {
|
||||
Ok(e) => {
|
||||
|
||||
17
src/stmt.rs
17
src/stmt.rs
@@ -7,6 +7,8 @@ pub enum Statement {
|
||||
Print(PrintStatement),
|
||||
Var(VarStatement),
|
||||
Block(BlockStatement),
|
||||
If(IfStatement),
|
||||
While(WhileStatement),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -30,6 +32,19 @@ pub struct BlockStatement {
|
||||
pub statements: Vec<Statement>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IfStatement {
|
||||
pub expr: Expr,
|
||||
pub statement_then: Box<Statement>,
|
||||
pub statement_else: Option<Box<Statement>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WhileStatement {
|
||||
pub condition: Expr,
|
||||
pub body: Box<Statement>,
|
||||
}
|
||||
|
||||
impl BlockStatement {
|
||||
pub fn new( statements: Vec<Statement> ) -> Self {
|
||||
BlockStatement {
|
||||
@@ -44,4 +59,6 @@ pub trait StatementVisitor<T> {
|
||||
fn visit_print(&mut self, p: &PrintStatement) -> T;
|
||||
fn visit_var_stmt(&mut self, v: &VarStatement) -> T;
|
||||
fn visit_block_stmt(&mut self, b: &BlockStatement) -> T;
|
||||
fn visit_if_stmt(&mut self, i: &IfStatement) -> T;
|
||||
fn visit_while_stmt(&mut self, w: &WhileStatement) -> T;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user