Bonjour, Dans mon langage Lisek, je suis parvenu a produire ce qui suit:
output
: Contient les tokens,values
: Contient les valeurs des variables, accessible avec le tokenIdent(id)
qui contient l’ID dansvalues
de sa valeur La syntaxe de mon langage se présente comme suit:
let a (2)
let b (+ 1 (- 2 1)) // 2
cond (boolean_statment) { /* if */ } { /* else */ }
until (boolean_statment) { /* do */ } // loop
conc "hello," " world" // "hello, world"
format (a) // 2
format ("hello") // "hello"
let
est géré totalement pendant le parsing et il y a donc aucun Token associé a la création de variable.
Ce que je voudrais, et c’est ce que j’avais essayé, c’est de faire en sorte qu’un builtin (+
, -
, *
, until
, cond
, conc
, …) soit toujours le point d’entrée de toute choses, de sorte que rien ne puisse commencer avec une chaine de caractère ou un nombre par exemple car ça n’a pas de sens. J’avais tenté de faire une fonction eval
qui vérifie que le premier token soit un Builtin et si c’est le cas, appelait la fonction que contenait le builtin. Une fois la fonction appelé, dans cette fonction, j’appelle la fonction advance
le même nombre de fois qu’elle n’avait d’argument. Donc, par exemple, si je tombe sur cond
, j’appelle trois fois advance
pour récupérer le booléen, le scope du if
et du else
. La fonction advance
est la suivante:
pub fn advance(&mut self, tok: Token) {
match tok.ttype {
TType::String(s) => self.stack.push(Value::String(s)),
TType::Integer(i) => self.stack.push(Value::Integer(i)),
TType::Float(f) => self.stack.push(Value::Float(f)),
TType::Builtin(func) => func(self, self.pos, tok.line, tok.column),
TType::Ident(id) => self.advance(self.values.get(id).unwrap().clone()),
TType::SParen(v) => for t in v {self.advance(t)}
TType::SBrac(v) => self.stack.push(Value::SBrac(v))
}
}
Ma démarche nécessite beaucoup de choses étranges dans mon code, et elle m’a l’air assez triviale. J’aimerai que vous me proposiez une autre façon de faire pour évaluer de façon cohérente mes tokens.
Cordialement.