Dans l'article précédent, Prend en charge les déclarations if. Puisqu'il n'y a aucun opérateur qui peut être spécifié dans l'instruction conditionnelle de l'instruction if, je voudrais la soutenir.
Assurez-vous de vouloir le faire facilement. Par exemple, il existe le programme suivant. Puisque le nombre d'inégalité est correct sur la première ligne, «1» qui représente la vérité est affiché. La deuxième ligne renvoie «0», qui représente le mensonge, car l'inégalité avec le nombre égal est incorrecte. La troisième ligne renvoie «1» car le résultat de l'opération logique est vrai. Dans l'exemple, il s'agit uniquement d'une sortie, mais elle peut être décrite comme une expression conditionnelle dans l'instruction if.
println(10 > 1)
println(5 <= 1)
println(!(1 == 2) && (3 != 4))
Pour savoir comment mettre en œuvre, voir Implémentation de l'analyse syntaxique et Implémentation de l'interpréteur. À cause de ça Veuillez vous y référer car il n'y a rien de nouveau.
Passez à la mise en œuvre. À propos de l'analyse de phrases (Lexer), de l'analyse syntaxique (Parser), de l'interpréteur (Interpreter) Jetons un coup d'œil aux modifications et aux ajouts dans l'ordre.
Lexer.java
Une implémentation de Lexer.java. Correspond à l'opérateur ajouté. Jusqu'à présent, tous les opérateurs utilisaient une lettre, mais il est peut-être nouveau que les opérateurs à deux lettres aient également augmenté.
Lexer.java
private boolean isSignStart(char c) {
return c == '=' || c == '+' || c == '-' || c == '*' || c == '/' || c == '!' || c == '<' || c == '>' || c == '&'
|| c == '|';
}
private Token sign() throws Exception {
Token t = new Token();
t.kind = "sign";
char c1 = next();
char c2 = (char) 0;
if (!isEOT()) {
if (c1 == '=' || c1 == '!' || c1 == '<' || c1 == '>') {
if (c() == '=') {
c2 = next();
}
} else if (c1 == '&') {
if (c() == '&') {
c2 = next();
}
} else if (c1 == '|') {
if (c() == '|') {
c2 = next();
}
}
}
String v;
if (c2 == (char) 0) {
v = Character.toString(c1);
} else {
v = Character.toString(c1) + Character.toString(c2);
}
t.value = v;
return t;
}
Parser.java
Une implémentation de Parser.java.
Ajoutez une définition de la façon dont cela fonctionne pour la signification du jeton.
Un nouvel opérateur a été ajouté à partir de <-Add
.
Puisque !
Est un opérateur à terme unique, il est ajouté à <-Update
.
Parser.java
public Parser() {
degrees = new HashMap<>();
degrees.put("(", 80);
degrees.put("*", 60);
degrees.put("/", 60);
degrees.put("+", 50);
degrees.put("-", 50);
degrees.put("==", 40); // <-- Add
degrees.put("!=", 40);
degrees.put("<", 40);
degrees.put("<=", 40);
degrees.put(">", 40);
degrees.put(">=", 40);
degrees.put("&&", 30);
degrees.put("||", 30);
degrees.put("=", 10);
factorKinds = Arrays.asList(new String[] { "digit", "ident" });
binaryKinds = Arrays.asList(new String[] { "sign" });
rightAssocs = Arrays.asList(new String[] { "=" });
unaryOperators = Arrays.asList(new String[] { "+", "-", "!" }); // <-- Update
reserved = Arrays.asList(new String[] { "function", "return", "if", "else" });
}
Interpreter.java
Une implémentation d'Interpreter.java.
Puisqu'il est pratique pour la méthode de juger si l'expression conditionnelle est vraie, nous avons ajouté de la variété par différents types d'arguments.
Interpreter.java
public boolean isTrue(Token token) throws Exception {
return isTrue(value(expression(token)));
}
public boolean isTrue(Integer value) throws Exception {
return 0 != value;
}
Dans ce langage, les valeurs booléennes sont représentées par des entiers, préparez donc une méthode pour convertir le type de valeur logique en entier. True est converti en «1».
Interpreter.java
public Integer toInteger(boolean b) {
return b ? 1 : 0;
}
Une méthode qui exécute un opérateur mononome.
Ajout d'un refus logique à <-Add
.
Interpreter.java
public Object unaryCalc(Token expr) throws Exception {
Integer left = value(expression(expr.left));
if (expr.value.equals("+")) {
return left;
} else if (expr.value.equals("-")) {
return -left;
} else if (expr.value.equals("!")) { // <-- Add
return toInteger(!isTrue(left));
} else {
throw new Exception("Unknown sign for unary calc");
}
}
Une méthode qui exécute un opérateur binaire.
À partir de <-Add
, nous ajoutons une nouvelle implémentation arithmétique.
Interpreter.java
public Object calc(Token expr) throws Exception {
Integer left = value(expression(expr.left));
Integer right = value(expression(expr.right));
if (expr.value.equals("+")) {
return left + right;
} else if (expr.value.equals("-")) {
return left - right;
} else if (expr.value.equals("*")) {
return left * right;
} else if (expr.value.equals("/")) {
return left / right;
} else if (expr.value.equals("==")) { // <-- Add
return toInteger(left == right);
} else if (expr.value.equals("!=")) {
return toInteger(left != right);
} else if (expr.value.equals("<")) {
return toInteger(left < right);
} else if (expr.value.equals("<=")) {
return toInteger(left <= right);
} else if (expr.value.equals(">")) {
return toInteger(left > right);
} else if (expr.value.equals(">=")) {
return toInteger(left >= right);
} else if (expr.value.equals("&&")) {
return toInteger(isTrue(left) && isTrue(right));
} else if (expr.value.equals("||")) {
return toInteger(isTrue(left) || isTrue(right));
} else {
throw new Exception("Unknown sign for Calc");
}
}
Le programme ci-dessous utilisant l'implémentation ci-dessus
println(10 > 1)
println(5 <= 1)
println(!(1 == 2) && (3 != 4))
Est exécuté, et "1", "0" et "1" sont envoyés à la sortie standard.
Interpreter.java
public static void main(String[] args) throws Exception {
String text = "";
text += "println(10 > 1)";
text += "println(5 <= 1)";
text += "println(!(1 == 2) && (3 != 4))";
List<Token> tokens = new Lexer().init(text).tokenize();
List<Token> blk = new Parser().init(tokens).block();
new Interpreter().init(blk).run();
// --> 1
// --> 0
// --> 1
}
C'est tout pour la mise en œuvre. Merci beaucoup.
La source complète est disponible ici.
Calc https://github.com/quwahara/Calc/tree/article-11-compare-r2/Calc/src/main/java
Il y a un article de suite.
** Correspond à l'instruction while ** http://qiita.com/quwahara/items/36f6704ae9c756240068
Recommended Posts