Мне нужно создать простой компилятор для калькулятора, и я использую antlr4 и шаблон посетителя. это мой файл грамматики Simple_Calculator.g4:
grammar Simple_Calculator;
program : statements ;
statements : statement | statements statement ;
statement : identifier '=' expr ';' #assign
| 'begin' statements 'end' #brac
| 'if' expr 'then' statement #if
| 'if' expr 'then' statement 'else' statement #if_elset
| 'while' expr 'do' statement #while
| 'for' identifier '=' number ':' number 'do' statement #for
| 'print' identifier ';' #print
;
expr : expr binop expr #ope
| '!' expr #invert
| '(' expr ')' #parenthesis
| identifier #identify
| number #num
;
binop : '+'
| '-'
| '*'
| '/'
| '<'
| '>'
| '<='
| '>='
| '=='
| '!='
| '^'
;
identifier : STRING+('-'|STRING|INT)* ;
number : INT+('.'INT+)? ;
STRING: [a-zA-Z]+ ;
INT : [0-9]+ ;
WS : [ \t\r\n] -> skip ;
и следуют методы visitOpe
и visitAssign
в классе MainVisitor extends Simple_CalculatorBaseVisitor
:
public class MainVisitor extends Simple_CalculatorBaseVisitor<Object> {
@Override
public Object visitAssign(Simple_CalculatorParser.AssignContext ctx) {
String id = (String) (visit(ctx.identifier()));
String value = (String)(visit(ctx.expr()));
if (storage.containsKey(id)) {
storage.replace(id, value);
} else {
storage.put(id, value);
}
return storage; //To change body of generated methods, choose Tools | Templates.
} // end of visitAssign
@Override
public Object visitOpe(Simple_CalculatorParser.OpeContext ctx) {
String leftOperand = (String) visit(ctx.expr(0));
String rightOperand = (String) visit(ctx.expr(1));
/*if (rightOperand.matches("^\\d+$")) {
return rightOperand;
}*/
String Operation = ctx.binop().getText();
switch (Operation) {
case "+": {
leftOperand = setOperands(leftOperand);
rightOperand = setOperands(rightOperand);
return String.valueOf(Integer.parseInt(leftOperand) + Integer.parseInt(rightOperand));
}
case "-":
leftOperand = setOperands(leftOperand);
rightOperand = setOperands(rightOperand);
return String.valueOf(Integer.parseInt(leftOperand) - Integer.parseInt(rightOperand));
case "*":
leftOperand = setOperands(leftOperand);
rightOperand = setOperands(rightOperand);
return String.valueOf(Integer.parseInt(leftOperand) * Integer.parseInt(rightOperand));
case "/":
leftOperand = setOperands(leftOperand);
rightOperand = setOperands(rightOperand);
return String.valueOf(Integer.parseInt(leftOperand) / Integer.parseInt(rightOperand));
// the rest possible conditions
}
//other methods
}// end of visitOpe
проблема в том, что когда я хочу использовать оператор '-' в выражении назначения, когда программа читает строку String value = (String)(visit(ctx.expr()));
в visitAssign
, она не посещает visitOpe
после этого, вместо этого она возвращает все выражение. например, когда я даю программу:
i=5;
i=i+2;
print i;
как ввод, он работает нормально. он сохраняет i
в качестве идентификатора в HashMap
, а во второй строке добавит к нему 2 единицы и, наконец, напечатает его значение. но если я изменю i=i+2;
на i=i-2
, он сохранит i
с начальным значением 5, но во второй строке он просто не пройдет через метод visitOpe
, вместо этого он вернет «i-2» и сохранит это как значение i
и, наконец, напечатает Это. Операторы '*' и '/' прекрасно работают в качестве сложения. Речь идет только о «-», и я не знаю, в чем проблема. Итак, как это исправить:
С Уважением