Im vorherigen Artikel Unterstützt if-Anweisungen. Da es keinen Operator gibt, der in der bedingten Anweisung der if-Anweisung angegeben werden kann, möchte ich ihn unterstützen.
Stellen Sie sicher, dass Sie es einfach machen möchten. Zum Beispiel gibt es das folgende Programm. Da die Ungleichungszahl in der ersten Zeile korrekt ist, wird "1" ausgegeben, die die Wahrheit darstellt. Da die Ungleichungszahl mit der gleichen Zahl in der zweiten Zeile falsch ist, wird "0" ausgegeben, was falsch anzeigt. Die dritte Zeile gibt "1" aus, da das Ergebnis der logischen Operation wahr ist. Im Beispiel wird es nur ausgegeben, es kann jedoch als bedingter Ausdruck in der if-Anweisung beschrieben werden.
println(10 > 1)
println(5 <= 1)
println(!(1 == 2) && (3 != 4))
Informationen zur Implementierung finden Sie unter Implementierung der Syntaxanalyse und Implementierung des Interpreters. Deswegen Bitte beziehen Sie sich darauf, da es nichts Neues gibt.
Fahren Sie mit der Implementierung fort. Informationen zur Phrasenanalyse (Lexer), Syntaxanalyse (Parser), Interpreter (Interpreter) Schauen wir uns die Änderungen und Ergänzungen der Reihe nach an.
Lexer.java
Eine Implementierung von Lexer.java. Entspricht dem hinzugefügten Operator. Bisher waren alle Operatoren Ein-Buchstaben-Operatoren, aber es ist möglicherweise neu, dass auch Zwei-Buchstaben-Operatoren zugenommen haben.
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
Eine Implementierung von Parser.java.
Fügen Sie eine Definition hinzu, wie es für die Bedeutung des Tokens funktioniert.
Ein neuer Operator wurde von <-Add
hinzugefügt.
Da !
Ein einzelner Termoperator ist, wird er zu <-Update
hinzugefügt.
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
Eine Implementierung von Interpreter.java.
Da es für die Methode praktisch ist, zu beurteilen, ob der bedingte Ausdruck wahr ist, haben wir die Vielfalt durch verschiedene Arten von Argumenten hinzugefügt.
Interpreter.java
public boolean isTrue(Token token) throws Exception {
return isTrue(value(expression(token)));
}
public boolean isTrue(Integer value) throws Exception {
return 0 != value;
}
In dieser Sprache werden boolesche Werte durch Ganzzahlen dargestellt. Bereiten Sie daher eine Methode vor, um den logischen Werttyp in eine Ganzzahl zu konvertieren. True wird in "1" umgewandelt.
Interpreter.java
public Integer toInteger(boolean b) {
return b ? 1 : 0;
}
Eine Methode, die einen mononomischen Operator ausführt.
Logische Ablehnung zu <-Add
hinzugefügt.
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");
}
}
Eine Methode, die einen binären Operator ausführt.
Ab <-Add
fügen wir eine neue arithmetische Implementierung hinzu.
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");
}
}
Das folgende Programm verwendet die obige Implementierung
println(10 > 1)
println(5 <= 1)
println(!(1 == 2) && (3 != 4))
Wird ausgeführt und "1", "0" und "1" werden an die Standardausgabe ausgegeben.
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
}
Das ist alles für die Implementierung. Vielen Dank.
Die vollständige Quelle finden Sie hier.
Calc https://github.com/quwahara/Calc/tree/article-11-compare-r2/Calc/src/main/java
Es gibt einen Folgeartikel.
** Entspricht der while-Anweisung ** http://qiita.com/quwahara/items/36f6704ae9c756240068
Recommended Posts