diff --git a/src/astprinter.rs b/src/astprinter.rs index 0eb9fff..e1944c5 100644 --- a/src/astprinter.rs +++ b/src/astprinter.rs @@ -1,4 +1,5 @@ use crate::expr::{Binary, Expr, ExprVisitor, Grouping, Literal, Unary}; +use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor}; pub struct ASTPrinter { pub(crate) depth: u32 @@ -59,4 +60,22 @@ impl ExprVisitor<()> for ASTPrinter { Expr::UnaryExpr(u) => { self.visit_unary(u); } } } +} + +impl StatementVisitor<()> for ASTPrinter { + fn visit_expr_stmt(&mut self, e: &ExpressionStatement) -> () { + println!("{} EXPR_STMT(", self.ast_tab()); + self.depth+=1; + self.visit_expr(&e.expr); + self.depth-=1; + print!(") "); + } + + fn visit_print(&mut self, p: &PrintStatement) -> () { + println!("{} EXPR_STMT(", self.ast_tab()); + self.depth+=1; + self.visit_expr(&p.expr); + self.depth-=1; + print!(") "); + } } \ No newline at end of file diff --git a/src/expr.rs b/src/expr.rs index db49f7b..f312571 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1,11 +1,13 @@ use crate::token::Token; +#[derive(Clone)] pub struct Binary { pub left: Box, pub operator: Token, pub right: Box, } +#[derive(Clone)] pub struct Grouping { pub expression: Box, } @@ -18,11 +20,13 @@ pub enum Literal { LiteralNil, } +#[derive(Clone)] pub struct Unary { pub operator: Token, pub right: Box, } +#[derive(Clone)] pub enum Expr { BinaryExpr(Binary), GroupingExpr(Grouping), diff --git a/src/interpreter.rs b/src/interpreter.rs index 3534c50..1ab3718 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -7,10 +7,12 @@ use crate::expr::Literal::LiteralNumber; use crate::expr::Literal::LiteralBool; use crate::expr::Literal::LiteralNil; use crate::expr::{Binary, Expr, ExprVisitor, Grouping, Literal, Unary}; +use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor}; use crate::token_type::TokenType; pub struct Interpreter; +#[derive(Debug)] pub struct RuntimeError { pub(crate) message: String } @@ -145,4 +147,24 @@ impl ExprVisitor> for Interpreter { UnaryExpr(u) => { Ok(self.visit_unary(&u)?) } } } -} \ No newline at end of file +} + +impl StatementVisitor<()> for Interpreter { + fn visit_expr_stmt(&mut self, e: &ExpressionStatement) -> () { + self.visit_expr(&e.expr).expect("Erreur pendant l'évaluation de l'expression."); + } + + fn visit_print(&mut self, p: &PrintStatement) -> () { + match self.visit_expr(&p.expr) { + Ok(lit) => match (lit) { + Literal::LiteralNumber(f) => { println!("{}", f); } + Literal::LiteralString(s) => { println!("{}", s); } + Literal::LiteralBool(b) => { println!("{}", b); } + Literal::LiteralNil => { println!("nul")} + } + Err(e) => panic!("{}", e.message) + } + } +} + + diff --git a/src/main.rs b/src/main.rs index 233d66b..aa39089 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use std::{env, fs, io}; use std::io::Write; use std::process; use crate::astprinter::ASTPrinter; -use crate::expr::{ExprVisitor, Literal}; +use crate::expr::ExprVisitor; use crate::interpreter::Interpreter; use crate::parser::Parser; @@ -13,8 +13,10 @@ mod token_type; mod expr; mod astprinter; mod parser; +mod stmt; use crate::scanner::Scanner; +use crate::stmt::{Statement, StatementVisitor}; // Exit codes from #include const EX_OK: i32 = 0; @@ -71,26 +73,24 @@ fn run(src: String) -> i32 { println!("Parser"); let mut parser = Parser::new( scanner.tokens ); - match parser.parse() { - Some(expr) => { - println!("AST"); - let mut printer = ASTPrinter { depth: 0 }; - printer.visit_expr(&expr); - println!("Interpretation"); - let mut interpreter = Interpreter; - let result = interpreter.visit_expr(&expr); - match result { - Ok(r) => { match r { - Literal::LiteralNumber(f) => { println!("Resultat numérique = {}", f); } - Literal::LiteralString(s) => { println!("Résultat chaîne = {}", s); } - Literal::LiteralBool(b) => { println!("Résultat booléen = {}", b); } - Literal::LiteralNil => { println!("Résultat nul")} - }} - Err(e) => { println!("Erreur d'exécution : {}", e.message); return EX_EXECERR; } - } - println!(); - }, - None => { println!("An error occurred while parsing expression."); return EX_DATAERR; } + let program = parser.parse(); + + println!("AST"); + let mut printer = ASTPrinter { depth: 0 }; + for s in program.clone() { + match s { + Statement::Expression(e) => { printer.visit_expr_stmt(&e) } + Statement::Print(p) => { printer.visit_print(&p) } + } + } + + println!("Interpretation"); + let mut interpreter = Interpreter; + for s in program { + match s { + Statement::Expression(e) => { interpreter.visit_expr_stmt(&e) } + Statement::Print(p) => { interpreter.visit_print(&p) } + } } EX_OK @@ -101,4 +101,4 @@ fn run(src: String) -> i32 { // https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations#rust // Pause : -// http://www.craftinginterpreters.com/statements-and-state.html +// http://www.craftinginterpreters.com/statements-and-state.html#global-variables diff --git a/src/parser.rs b/src/parser.rs index d2e0488..7c49a01 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2,12 +2,14 @@ use crate::expr::{Binary, Expr, Grouping, Unary}; use crate::expr::Literal::{LiteralBool, LiteralNumber, LiteralString}; use crate::token::Token; use crate::token_type::TokenType; +use crate::stmt::{ExpressionStatement, PrintStatement, Statement}; pub struct Parser { tokens: Vec, current: usize } +#[derive(Debug)] pub struct ParseError { message: String } @@ -203,13 +205,32 @@ impl Parser { } } - pub fn parse(&mut self) -> Option { - match self.expression() { - Ok(expr) => Some(expr), - Err(error) => { - println!("Error while parsing expression : {}",error.message); - None - } + fn statement(&mut self) -> Statement { + if self.match_token(&[TokenType::Print]) { + self.print_statement() + } else { + self.expr_statement() } } + + fn print_statement(&mut self) -> Statement { + let e = self.expression().unwrap(); + self.consume(&TokenType::Semicolon, String::from("; attendu")).unwrap(); + Statement::Print(PrintStatement{ expr: e }) + } + + fn expr_statement(&mut self) -> Statement { + let e = self.expression().unwrap(); + self.consume(&TokenType::Semicolon, String::from("; attendu")).unwrap(); + Statement::Expression(ExpressionStatement{ expr: e }) + } + + pub fn parse(&mut self) -> Vec { + let mut statements= Vec::new(); + while !self.is_at_end() { + statements.push(self.statement()); + } + + statements + } } \ No newline at end of file diff --git a/src/stmt.rs b/src/stmt.rs new file mode 100644 index 0000000..304c023 --- /dev/null +++ b/src/stmt.rs @@ -0,0 +1,22 @@ +use crate::expr::Expr; + +#[derive(Clone)] +pub enum Statement { + Expression(ExpressionStatement), + Print(PrintStatement) +} + +#[derive(Clone)] +pub struct ExpressionStatement { + pub expr: Expr +} + +#[derive(Clone)] +pub struct PrintStatement { + pub expr: Expr +} + +pub trait StatementVisitor { + fn visit_expr_stmt(&mut self, e: &ExpressionStatement) -> T; + fn visit_print(&mut self, p: &PrintStatement) -> T; +}