bonjour, j’ai commence a créer un petit interpréteur en rust, j’ai fait le lexer , la construction d’arbre syntactique , et il manque que l’execution .
la sortie de mon arbre syntactique de ce code par example let a = 5
: Let {name: "a", value: Number {value: "5"}}
ou encore if a then b
donne IfThen {cond: Identifier {value: "a"} , then: Identifier {value: "b"}}
pouvez vous m’aider ou m’expliquez comment il faut faire
lexer.rs :
#[derive(Debug, PartialEq, Clone)]
pub enum Lexer {
// The lexer is a simple state machine with the following states.
//
// * `Seperator`: The lexer expects to find or one
// of the symbols `(`, `)`, `{`, `}`, `[`, `]`, `;`, `,`
//
// * `Operator`: The lexer expects to find one of the symbols `+`, `-`, `*`, `/`, `%`, `=`, `!`, `<`, `>`, `&`, `|`, `^`, `~`, `?`
// * `Comment`: The lexer expects to find a `*/` to end the comment.
//
// * `String`: The lexer expects to find a `"` to end the string.
//
// * `Number`: The lexer expects to find a number.
//
// * `Identifier`: The lexer expects to find an identifier.
//
// * `Operator`: The lexer expects to find an operator.
//
// * `Keyword`: The lexer expects to find a keyword.
//
// * `Error`: The lexer expects to find an error.
//
// * `Eof`: The lexer expects to find the end of the file.
Comment(String),
Number(String),
Identifier(String),
Operator(String),
Keyword(String),
String(String),
Error(String),
Eof
}
impl Lexer {
pub fn check_for_number(input: &str) -> bool {
input.to_string().parse::<f64>().is_ok()
}
pub fn check_for_identifier(input: &str) -> bool {
let chars = input.chars().collect::<Vec<char>>();
if input.len() == 0 {
return false;
}
chars[0].is_alphabetic() || chars[0] == '_'
}
pub fn check_for_operator(input: &str) -> bool {
if input.len() > 1 {
return false;
}
match input {
"+"| "-" | "*" | "/" | "%" => true,
"=" | "!" | "<" | ">" | "&" | "|" | "^" | "~" | "?" => true,
_ => return false
}
}
pub fn check_for_keyword(input : &str) -> bool {
match input {
// check if one of the keywords is in the input
"if" | "else" | "for" | "while" | "let" | "then" | "do" | "in" => true,
_ => false
}
}
pub fn check_for_seperator(input: &str) -> bool {
match input {
"(" | ")" | "{" | "}" | "[" | "]" | ";" | "," => true,
_ => false
}
}
}
pub fn tokenize(string: &str) -> Vec<Lexer> {
let mut tokens = Vec::new();
let buffer = string.to_string();
let mut tkchar = String::new();
let mut is_string = false;
let lenght = buffer.len();
let mut string_curr;
let mut d = false;
for (i, c) in &mut buffer.chars().enumerate() {
string_curr = c.to_string();
if d {
d = false;
continue
}
if is_string {
if string_curr == "\"" {
is_string = false;
tokens.push(Lexer::String(tkchar));
tkchar = String::new();
d = true;
continue
} else {
tkchar += &c.to_string();
continue
}
}
if string_curr == "\"" {
is_string = true;
continue
}
if i == lenght - 1 {
tkchar += &string_curr;
tkchar = tkchar.trim().to_string();
if Lexer::check_for_number(&tkchar) {
tokens.push(Lexer::Number(tkchar));
tkchar = String::new();
} else if Lexer::check_for_operator(&tkchar) {
tokens.push(Lexer::Operator(tkchar));
tkchar = String::new();
} else if Lexer::check_for_keyword(&tkchar) {
tokens.push(Lexer::Keyword(tkchar));
tkchar = String::new();
} else if Lexer::check_for_identifier(&tkchar) {
tokens.push(Lexer::Identifier(tkchar));
tkchar = String::new();
} else {
tokens.push(Lexer::Error(tkchar));
tkchar = String::new();
}
break;
}
if string_curr == " ".to_string() || string_curr == "\n".to_string() || string_curr == "\r".to_string() {
if i == 0 {
continue;
}
if Lexer::check_for_number(&tkchar) {
tokens.push(Lexer::Number(tkchar));
tkchar = String::new();
} else if Lexer::check_for_operator(&tkchar) {
tokens.push(Lexer::Operator(tkchar));
tkchar = String::new();
} else if Lexer::check_for_keyword(&tkchar) {
tokens.push(Lexer::Keyword(tkchar));
tkchar = String::new();
} else if Lexer::check_for_identifier(&tkchar) {
tokens.push(Lexer::Identifier(tkchar));
tkchar = String::new();
} else {
tokens.push(Lexer::Error(tkchar));
tkchar = String::new();
}
continue
}
tkchar += &string_curr;
}
return tokens;
}
tree.rs
#[derive(Debug, PartialEq, Clone)]
pub enum Expr {
IfThen {
cond: Box<Expr>,
then: Box<Expr>
},
IfThenElse {
cond: Box<Expr>,
then: Box<Expr>,
else_: Box<Expr>,
},
While {
cond: Box<Expr>,
body: Box<Expr>
},
Let {
name: String,
value: Box<Expr>
},
Number {
value: String
},
Identifier {
name: String
},
BinOp {
op: String,
left: Box<Expr>,
right: Box<Expr>
},
String {
value: String
},
For {
name: String,
iter: Box<Expr>,
body: Box<Expr>
},
}
et parser.rs
use crate::lexer::Lexer;
use crate::tree::Expr;
pub fn parse_expr(tokens: &mut Vec<Lexer>) -> Result<Expr, String> {
if tokens.len() == 0 {
return Err("Unexpected end of file".to_string());
}
let token = tokens[0].clone();
match token {
Lexer::Number(n) => {
tokens.remove(0);
return Ok(Expr::Number { value: n.clone() });
},
Lexer::Identifier(i) => {
tokens.remove(0);
Ok(Expr::Identifier { name: i.clone() })
},
Lexer::Keyword(k) => {
match k.as_ref() {
"if" => {
tokens.remove(0); // remove "if" of if block
let cond = parse_expr(tokens)?;
if tokens[0] != Lexer::Keyword("then".to_string()) {
return Err("Expected keyword 'then'".to_string());
}
tokens.remove(0); // remove "then" of if block
let then = parse_expr(tokens)?;
if tokens.len() == 1 {
Ok(Expr::IfThen {
cond: Box::new(cond),
then: Box::new(then)
})
} else if tokens.len() >= 2 {
tokens.remove(0);
let else_ = parse_expr(tokens)?;
Ok(Expr::IfThenElse {
cond: Box::new(cond),
then: Box::new(then),
else_: Box::new(else_)
})
} else {
Err("error syntatic".to_string()) // doesn't match any case
}
},
"while" => {
tokens.remove(0); // remove "while" of while block
let cond = parse_expr(tokens)?;
if tokens[0] != Lexer::Keyword("do".to_string()) {
return Err("Expected keyword 'do'".to_string());
}
tokens.remove(0); // remove "do" of while block
let body = parse_expr(tokens)?;
Ok(Expr::While {
cond: Box::new(cond),
body: Box::new(body)
})
},
"let" => {
tokens.remove(0);
if let Lexer::Identifier(name) = tokens[0].clone() {
tokens.remove(0);
if tokens[0] != Lexer::Operator("=".to_string()) {
return Err("Expected operator '='".to_string());
} else {
tokens.remove(0);
}
let value = parse_expr(tokens)?;
Ok(Expr::Let {
name: name.clone(),
value: Box::new(value)
})
} else {
Err("Expected identifier".to_string())
}
},
"for" => {
tokens.remove(0);
println!("for: {:?}", tokens.len());
if tokens.len() < 4 {
return Err("Expected identifier: invalid syntash".to_string());
}
if let Lexer::Identifier(name) = tokens[0].clone() {
tokens.remove(0);
if tokens[0] != Lexer::Keyword("in".to_string()) {
return Err("Expected keyword 'in'".to_string());
}
tokens.remove(0);
let iter = parse_expr(tokens)?;
if tokens[0] != Lexer::Keyword("do".to_string()) {
return Err("Expected keyword 'do'".to_string());
}
tokens.remove(0);
let body = parse_expr(tokens)?;
Ok(Expr::For {
name: name.clone(),
iter: Box::new(iter),
body: Box::new(body)
})
} else {
Err("Expected identifier: no var".to_string())
}
},
_ => Err("Unexpected keyword: ".to_string())
}
},
Lexer::Operator(op) => {
tokens.remove(0);
let left = parse_expr(tokens)?;
let right = parse_expr(tokens)?;
Ok(Expr::BinOp {
op: op.clone(),
left: Box::new(left),
right: Box::new(right)
})
},
Lexer::String(s) => {
tokens.remove(0);
Ok(Expr::String { value: s.clone() })
},
_ => Err("Unexpected token".to_string())
}
}
merci pour votre temps
+0
-0