Ajout des instructions.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
use crate::expr::{Binary, Expr, ExprVisitor, Grouping, Literal, Unary};
|
use crate::expr::{Binary, Expr, ExprVisitor, Grouping, Literal, Unary};
|
||||||
|
use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor};
|
||||||
|
|
||||||
pub struct ASTPrinter {
|
pub struct ASTPrinter {
|
||||||
pub(crate) depth: u32
|
pub(crate) depth: u32
|
||||||
@@ -59,4 +60,22 @@ impl ExprVisitor<()> for ASTPrinter {
|
|||||||
Expr::UnaryExpr(u) => { self.visit_unary(u); }
|
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!(") ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
use crate::token::Token;
|
use crate::token::Token;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Binary {
|
pub struct Binary {
|
||||||
pub left: Box<Expr>,
|
pub left: Box<Expr>,
|
||||||
pub operator: Token,
|
pub operator: Token,
|
||||||
pub right: Box<Expr>,
|
pub right: Box<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Grouping {
|
pub struct Grouping {
|
||||||
pub expression: Box<Expr>,
|
pub expression: Box<Expr>,
|
||||||
}
|
}
|
||||||
@@ -18,11 +20,13 @@ pub enum Literal {
|
|||||||
LiteralNil,
|
LiteralNil,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Unary {
|
pub struct Unary {
|
||||||
pub operator: Token,
|
pub operator: Token,
|
||||||
pub right: Box<Expr>,
|
pub right: Box<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
BinaryExpr(Binary),
|
BinaryExpr(Binary),
|
||||||
GroupingExpr(Grouping),
|
GroupingExpr(Grouping),
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ 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};
|
use crate::expr::{Binary, Expr, ExprVisitor, Grouping, Literal, Unary};
|
||||||
|
use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor};
|
||||||
use crate::token_type::TokenType;
|
use crate::token_type::TokenType;
|
||||||
|
|
||||||
pub struct Interpreter;
|
pub struct Interpreter;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct RuntimeError {
|
pub struct RuntimeError {
|
||||||
pub(crate) message: String
|
pub(crate) message: String
|
||||||
}
|
}
|
||||||
@@ -145,4 +147,24 @@ impl ExprVisitor<Result<Literal, RuntimeError>> for Interpreter {
|
|||||||
UnaryExpr(u) => { Ok(self.visit_unary(&u)?) }
|
UnaryExpr(u) => { Ok(self.visit_unary(&u)?) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
44
src/main.rs
44
src/main.rs
@@ -2,7 +2,7 @@ use std::{env, fs, io};
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process;
|
use std::process;
|
||||||
use crate::astprinter::ASTPrinter;
|
use crate::astprinter::ASTPrinter;
|
||||||
use crate::expr::{ExprVisitor, Literal};
|
use crate::expr::ExprVisitor;
|
||||||
use crate::interpreter::Interpreter;
|
use crate::interpreter::Interpreter;
|
||||||
use crate::parser::Parser;
|
use crate::parser::Parser;
|
||||||
|
|
||||||
@@ -13,8 +13,10 @@ mod token_type;
|
|||||||
mod expr;
|
mod expr;
|
||||||
mod astprinter;
|
mod astprinter;
|
||||||
mod parser;
|
mod parser;
|
||||||
|
mod stmt;
|
||||||
|
|
||||||
use crate::scanner::Scanner;
|
use crate::scanner::Scanner;
|
||||||
|
use crate::stmt::{Statement, StatementVisitor};
|
||||||
|
|
||||||
// Exit codes from #include <sysexits.h>
|
// Exit codes from #include <sysexits.h>
|
||||||
const EX_OK: i32 = 0;
|
const EX_OK: i32 = 0;
|
||||||
@@ -71,26 +73,24 @@ fn run(src: String) -> i32 {
|
|||||||
|
|
||||||
println!("Parser");
|
println!("Parser");
|
||||||
let mut parser = Parser::new( scanner.tokens );
|
let mut parser = Parser::new( scanner.tokens );
|
||||||
match parser.parse() {
|
let program = parser.parse();
|
||||||
Some(expr) => {
|
|
||||||
println!("AST");
|
println!("AST");
|
||||||
let mut printer = ASTPrinter { depth: 0 };
|
let mut printer = ASTPrinter { depth: 0 };
|
||||||
printer.visit_expr(&expr);
|
for s in program.clone() {
|
||||||
println!("Interpretation");
|
match s {
|
||||||
let mut interpreter = Interpreter;
|
Statement::Expression(e) => { printer.visit_expr_stmt(&e) }
|
||||||
let result = interpreter.visit_expr(&expr);
|
Statement::Print(p) => { printer.visit_print(&p) }
|
||||||
match result {
|
}
|
||||||
Ok(r) => { match r {
|
}
|
||||||
Literal::LiteralNumber(f) => { println!("Resultat numérique = {}", f); }
|
|
||||||
Literal::LiteralString(s) => { println!("Résultat chaîne = {}", s); }
|
println!("Interpretation");
|
||||||
Literal::LiteralBool(b) => { println!("Résultat booléen = {}", b); }
|
let mut interpreter = Interpreter;
|
||||||
Literal::LiteralNil => { println!("Résultat nul")}
|
for s in program {
|
||||||
}}
|
match s {
|
||||||
Err(e) => { println!("Erreur d'exécution : {}", e.message); return EX_EXECERR; }
|
Statement::Expression(e) => { interpreter.visit_expr_stmt(&e) }
|
||||||
}
|
Statement::Print(p) => { interpreter.visit_print(&p) }
|
||||||
println!();
|
}
|
||||||
},
|
|
||||||
None => { println!("An error occurred while parsing expression."); return EX_DATAERR; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EX_OK
|
EX_OK
|
||||||
@@ -101,4 +101,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
|
// http://www.craftinginterpreters.com/statements-and-state.html#global-variables
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ use crate::expr::{Binary, Expr, Grouping, Unary};
|
|||||||
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;
|
||||||
|
use crate::stmt::{ExpressionStatement, PrintStatement, Statement};
|
||||||
|
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
tokens: Vec<Token>,
|
tokens: Vec<Token>,
|
||||||
current: usize
|
current: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct ParseError {
|
pub struct ParseError {
|
||||||
message: String
|
message: String
|
||||||
}
|
}
|
||||||
@@ -203,13 +205,32 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(&mut self) -> Option<Expr> {
|
fn statement(&mut self) -> Statement {
|
||||||
match self.expression() {
|
if self.match_token(&[TokenType::Print]) {
|
||||||
Ok(expr) => Some(expr),
|
self.print_statement()
|
||||||
Err(error) => {
|
} else {
|
||||||
println!("Error while parsing expression : {}",error.message);
|
self.expr_statement()
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<Statement> {
|
||||||
|
let mut statements= Vec::new();
|
||||||
|
while !self.is_at_end() {
|
||||||
|
statements.push(self.statement());
|
||||||
|
}
|
||||||
|
|
||||||
|
statements
|
||||||
|
}
|
||||||
}
|
}
|
||||||
22
src/stmt.rs
Normal file
22
src/stmt.rs
Normal file
@@ -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<T> {
|
||||||
|
fn visit_expr_stmt(&mut self, e: &ExpressionStatement) -> T;
|
||||||
|
fn visit_print(&mut self, p: &PrintStatement) -> T;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user