Variables globales (déclaration, affectation avec une expression et évaluation)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::expr::{Binary, Expr, ExprVisitor, Grouping, Literal, Unary};
|
||||
use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor};
|
||||
use crate::expr::{Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable};
|
||||
use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor, VarStatement};
|
||||
|
||||
pub struct ASTPrinter {
|
||||
pub(crate) depth: u32
|
||||
@@ -58,8 +58,13 @@ impl ExprVisitor<()> for ASTPrinter {
|
||||
Expr::GroupingExpr(g) => { self.visit_grouping(g); }
|
||||
Expr::LiteralExpr(l) => { self.visit_literal(l); }
|
||||
Expr::UnaryExpr(u) => { self.visit_unary(u); }
|
||||
Expr::VariableExpr(v) => { self.visit_variable(v); }
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_variable(&mut self, v: &Variable) -> () {
|
||||
println!("{}VARIABLE(name={})", self.ast_tab(), v.name.literal);
|
||||
}
|
||||
}
|
||||
|
||||
impl StatementVisitor<()> for ASTPrinter {
|
||||
@@ -78,4 +83,18 @@ impl StatementVisitor<()> for ASTPrinter {
|
||||
self.depth-=1;
|
||||
print!(") ");
|
||||
}
|
||||
|
||||
fn visit_var_stmt(&mut self, v: &VarStatement) -> () {
|
||||
println!("{} VAR_STMT(", self.ast_tab());
|
||||
self.depth+=1;
|
||||
println!("variable name = {}",&v.token.literal);
|
||||
print!("variable initializer = ");
|
||||
match &v.initializer {
|
||||
Some(v) => { self.visit_expr(&v) }
|
||||
None => {}
|
||||
}
|
||||
|
||||
self.depth-=1;
|
||||
print!(") ");
|
||||
}
|
||||
}
|
||||
26
src/environment.rs
Normal file
26
src/environment.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
use std::collections::HashMap;
|
||||
use crate::expr::Literal;
|
||||
use crate::interpreter::RuntimeError;
|
||||
|
||||
pub struct Environment {
|
||||
pub values: HashMap<String, Literal>,
|
||||
}
|
||||
|
||||
impl Environment {
|
||||
pub fn new() -> Self {
|
||||
Environment {
|
||||
values : HashMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn define(&mut self, name: String, value: Literal) {
|
||||
self.values.insert(name, value);
|
||||
}
|
||||
|
||||
pub fn get(&self, name: &String) -> Result<Literal, RuntimeError> {
|
||||
match self.values.get(name) {
|
||||
Some(s) => { Ok(s.clone()) } ,
|
||||
None => { Err(RuntimeError { message: format!("Variable {} non définie", name) } ) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,18 @@ pub struct Unary {
|
||||
pub right: Box<Expr>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Variable {
|
||||
pub name: Token,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Expr {
|
||||
BinaryExpr(Binary),
|
||||
GroupingExpr(Grouping),
|
||||
LiteralExpr(Literal),
|
||||
UnaryExpr(Unary),
|
||||
VariableExpr(Variable),
|
||||
}
|
||||
|
||||
pub trait ExprVisitor<T> {
|
||||
@@ -40,5 +46,6 @@ pub trait ExprVisitor<T> {
|
||||
fn visit_literal(&mut self, l: &Literal) ->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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,28 @@
|
||||
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};
|
||||
use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor};
|
||||
use crate::expr::{Binary, Expr, ExprVisitor, Grouping, Literal, Unary, Variable};
|
||||
use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor, VarStatement};
|
||||
use crate::token_type::TokenType;
|
||||
|
||||
pub struct Interpreter;
|
||||
pub struct Interpreter {
|
||||
environment: Environment,
|
||||
}
|
||||
|
||||
impl Interpreter {
|
||||
pub fn new() -> Self {
|
||||
Interpreter {
|
||||
environment: Environment::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RuntimeError {
|
||||
@@ -145,18 +157,23 @@ impl ExprVisitor<Result<Literal, RuntimeError>> for Interpreter {
|
||||
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)? )}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_variable(&mut self, v: &Variable) -> Result<Literal, RuntimeError> {
|
||||
self.environment.get(&v.name.literal)
|
||||
}
|
||||
}
|
||||
|
||||
impl StatementVisitor<()> for Interpreter {
|
||||
fn visit_expr_stmt(&mut self, e: &ExpressionStatement) -> () {
|
||||
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) -> () {
|
||||
fn visit_print(&mut self, p: &PrintStatement) {
|
||||
match self.visit_expr(&p.expr) {
|
||||
Ok(lit) => match (lit) {
|
||||
Ok(lit) => match lit {
|
||||
Literal::LiteralNumber(f) => { println!("{}", f); }
|
||||
Literal::LiteralString(s) => { println!("{}", s); }
|
||||
Literal::LiteralBool(b) => { println!("{}", b); }
|
||||
@@ -165,6 +182,16 @@ impl StatementVisitor<()> for Interpreter {
|
||||
Err(e) => panic!("{}", e.message)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_var_stmt(&mut self, v: &VarStatement) {
|
||||
match &v.initializer {
|
||||
Some(e) => {
|
||||
let value = self.visit_expr(&e).unwrap();
|
||||
self.environment.define(v.token.literal.clone(), value);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
10
src/main.rs
10
src/main.rs
@@ -2,7 +2,6 @@ use std::{env, fs, io};
|
||||
use std::io::Write;
|
||||
use std::process;
|
||||
use crate::astprinter::ASTPrinter;
|
||||
use crate::expr::ExprVisitor;
|
||||
use crate::interpreter::Interpreter;
|
||||
use crate::parser::Parser;
|
||||
|
||||
@@ -14,15 +13,16 @@ mod expr;
|
||||
mod astprinter;
|
||||
mod parser;
|
||||
mod stmt;
|
||||
mod environment;
|
||||
|
||||
use crate::scanner::Scanner;
|
||||
use crate::stmt::{Statement, StatementVisitor};
|
||||
|
||||
// Exit codes from #include <sysexits.h>
|
||||
const EX_OK: i32 = 0;
|
||||
const EX_DATAERR: i32 = 65;
|
||||
//const EX_DATAERR: i32 = 65;
|
||||
const EX_USAGE : i32 = 66;
|
||||
const EX_EXECERR: i32 = 70;
|
||||
//const EX_EXECERR: i32 = 70;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
@@ -81,15 +81,17 @@ fn run(src: String) -> i32 {
|
||||
match s {
|
||||
Statement::Expression(e) => { printer.visit_expr_stmt(&e) }
|
||||
Statement::Print(p) => { printer.visit_print(&p) }
|
||||
Statement::Var(v) => { printer.visit_var_stmt(&v) }
|
||||
}
|
||||
}
|
||||
|
||||
println!("Interpretation");
|
||||
let mut interpreter = Interpreter;
|
||||
let mut interpreter = Interpreter::new();
|
||||
for s in program {
|
||||
match s {
|
||||
Statement::Expression(e) => { interpreter.visit_expr_stmt(&e) }
|
||||
Statement::Print(p) => { interpreter.visit_print(&p) }
|
||||
Statement::Var(v) => { interpreter.visit_var_stmt(&v) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::expr::{Binary, Expr, Grouping, Unary};
|
||||
use crate::expr::{Binary, Expr, Grouping, Unary, Variable};
|
||||
use crate::expr::Literal::{LiteralBool, LiteralNumber, LiteralString};
|
||||
use crate::token::Token;
|
||||
use crate::token_type::TokenType;
|
||||
use crate::stmt::{ExpressionStatement, PrintStatement, Statement};
|
||||
use crate::stmt::{ExpressionStatement, PrintStatement, Statement, VarStatement};
|
||||
|
||||
pub struct Parser {
|
||||
tokens: Vec<Token>,
|
||||
@@ -60,15 +60,12 @@ impl Parser {
|
||||
return self.tokens[self.current - 1].clone();
|
||||
}
|
||||
|
||||
fn consume(&mut self, token_type: &TokenType, message: String) -> Result<(), ParseError> {
|
||||
fn consume(&mut self, token_type: &TokenType, message: String) -> Result<Token, ParseError> {
|
||||
if self.check(token_type) {
|
||||
self.advance();
|
||||
return Ok(());
|
||||
Ok(self.advance())
|
||||
} else {
|
||||
Err(ParseError { message })
|
||||
}
|
||||
|
||||
Err(ParseError {
|
||||
message
|
||||
})
|
||||
}
|
||||
|
||||
fn synchronise(&mut self) {
|
||||
@@ -192,6 +189,10 @@ impl Parser {
|
||||
if self.match_token(&[TokenType::String]) {
|
||||
return Ok(Expr::LiteralExpr(LiteralString(self.previous().literal)));
|
||||
}
|
||||
if self.match_token(&[TokenType::Identifier]) {
|
||||
return Ok(Expr::VariableExpr(Variable { name: self.previous() } ));
|
||||
}
|
||||
|
||||
if self.match_token(&[TokenType::LeftParen]) {
|
||||
let expr = self.expression()?;
|
||||
self.consume(&TokenType::RightParen, String::from("Expect ')' after expression."))?;
|
||||
@@ -205,7 +206,7 @@ impl Parser {
|
||||
}
|
||||
}
|
||||
|
||||
fn statement(&mut self) -> Statement {
|
||||
fn statement(&mut self) -> Result<Statement, ParseError> {
|
||||
if self.match_token(&[TokenType::Print]) {
|
||||
self.print_statement()
|
||||
} else {
|
||||
@@ -213,22 +214,53 @@ impl Parser {
|
||||
}
|
||||
}
|
||||
|
||||
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 print_statement(&mut self) -> Result<Statement, ParseError> {
|
||||
match self.expression() {
|
||||
Ok(e) => {
|
||||
self.consume(&TokenType::Semicolon, String::from("; attendu"))?;
|
||||
Ok(Statement::Print(PrintStatement{ expr: e }))
|
||||
}
|
||||
Err(e ) => { Err(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 })
|
||||
fn expr_statement(&mut self) -> Result<Statement, ParseError> {
|
||||
match self.expression() {
|
||||
Ok(e) => {
|
||||
self.consume(&TokenType::Semicolon, String::from("; attendu"))?;
|
||||
Ok(Statement::Expression(ExpressionStatement{ expr: e }))
|
||||
}
|
||||
Err(e ) => { Err(e) }
|
||||
}
|
||||
}
|
||||
|
||||
fn declaration(&mut self) -> Result<Statement, ParseError> {
|
||||
if self.match_token(&[TokenType::Var]) {
|
||||
self.var_declaration()
|
||||
} else {
|
||||
self.statement()
|
||||
}
|
||||
}
|
||||
|
||||
fn var_declaration(&mut self) -> Result<Statement, ParseError> {
|
||||
let name = self.consume(&TokenType::Identifier, String::from("nom de variable attendu"))?;
|
||||
|
||||
let mut initializer: Option<Expr> = None;
|
||||
if self.match_token(&[TokenType::Equal]) {
|
||||
initializer = Some(self.expression()?);
|
||||
}
|
||||
|
||||
self.consume(&TokenType::Semicolon, String::from("; attendu"))?;
|
||||
Ok(Statement::Var(VarStatement{ token: name, initializer }))
|
||||
}
|
||||
|
||||
pub fn parse(&mut self) -> Vec<Statement> {
|
||||
let mut statements= Vec::new();
|
||||
while !self.is_at_end() {
|
||||
statements.push(self.statement());
|
||||
match self.declaration() {
|
||||
Ok(stmt) => statements.push(stmt),
|
||||
Err(_e) => self.synchronise(),
|
||||
}
|
||||
}
|
||||
|
||||
statements
|
||||
|
||||
11
src/stmt.rs
11
src/stmt.rs
@@ -1,9 +1,11 @@
|
||||
use crate::expr::Expr;
|
||||
use crate::token::Token;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Statement {
|
||||
Expression(ExpressionStatement),
|
||||
Print(PrintStatement)
|
||||
Print(PrintStatement),
|
||||
Var(VarStatement),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -16,7 +18,14 @@ pub struct PrintStatement {
|
||||
pub expr: Expr
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct VarStatement {
|
||||
pub token: Token,
|
||||
pub initializer: Option<Expr>
|
||||
}
|
||||
|
||||
pub trait StatementVisitor<T> {
|
||||
fn visit_expr_stmt(&mut self, e: &ExpressionStatement) -> T;
|
||||
fn visit_print(&mut self, p: &PrintStatement) -> T;
|
||||
fn visit_var_stmt(&mut self, v: &VarStatement) -> T;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user