Мы были даны грамматику в классе, который выглядит следующим образом:Использование грамматики с посетителем для вычисления арифметических выражений
grammar Calculator;
@header {
import java.util.*;
}
@parser::members {
/** "memory" for our calculator; variable/value pairs go here */
Map<String, Double> memory = new HashMap<String, Double>();
}
statlist : stat+ ;
stat : vgl NL #printCompare
| ass NL #printAssign
| NL #blank
;
ass : <assoc=right> VAR ('=') vgl #assign
;
vgl : sum(op=('<'|'>') sum)* #compare
;
sum : prod(op=('+'|'-') prod)* #addSub
;
prod : pot(op=('*'|'/') pot)* #mulDiv
;
pot :<assoc=right> term(op='^' pot)? #poten
;
term : '+' term #add
| '-' term #subtract
| '(' sum ')' #parens
| VAR #var
| INT #int
;
/*Rules for the lexer */
MUL : '*' ;
DIV : '/' ;
ADD : '+' ;
SUB : '-' ;
BIG : '>' ;
SML : '<' ;
POT : '^' ;
VAR : [a-zA-Z]+ ;
NL : [\n] ;
INT : [0-9]+ ;
WS : [ \r\t]+ -> skip ; // skip spaces, tabs
У меня возникают проблемы перевод конструкции как эти
sum : prod(op=('+'|'-') prod)* #addSub
в рабочий код. В настоящее время соответствующий метод выглядит следующим образом:
/** prod(op=('+'|'-') prod)* */
@Override
public Double visitAddSub(CalculatorParser.AddSubContext ctx) {
double left = visit(ctx.prod(0));
if(ctx.op == null){
return left;
}
double right = visit(ctx.prod(1));
return (ctx.op.getType() == CalculatorParser.ADD) ? left+right : left-right;
}
Выходной ток будет выглядеть следующим образом
3+3+3
6.0
, который, очевидно, неверно. Как заставить посетителя правильно посещать узлы, не касаясь грамматики?
Это делает много смысла @ Лукас. Однако я не уверен, как перебирать детей. op сам не имеет никакого отношения, и дети из prod (1), например, выглядят так: 'Вход: 3 + 3 + 3' ' System.out.println (ctx.children); [[42 34 21 16], +, [44 34 21 16], +, [44 34 21 16]] ' ' System.out.println (ctx.prod (0) .children); [[50 42 34] 21 16]] ' ' System.out.println (ctx.prod (1) .children); [[50 44 34 21 16]] ' – Xianahru
Похоже, вы можете получить всю необходимую информацию из коллекции' children' , –
по какой-то причине ctx.op всегда является последним оператором. Например, с учетом ввода '1 + 2-3'ctx.op заканчивается' -'. Я раздражен, потому что 1 + 2 * 3 возвращает 7 с 'visit (ctx.prod (1))' return '6-0'. Там должно быть что-то, чего я пропускаю, что делает это проще, чем повторение всех детей и отбрасывание логики, которую дает конечный посетитель. – Xianahru