免责声明:这是为了课程工作,也是我的第一篇SO帖子,因为通常在之前都会问我问题
在一个关于antlr的简短速成课程之后,我已经尽了最大努力来找出如何最好地解决创建一个支持数字、逻辑和关系运算的RPN计算器的问题。只接受int和boolean。
现在,虽然我的代码可能远未达到标准的antlr质量,但除了我的"开始"规则匹配时,其他代码都正常工作。我希望它打印出堆栈中的结果,但由于某种原因,匹配后堆栈总是空的。
例如2 3+;在我的打印调试语句中,我看到所有内容都被推送、弹出,并且5的结果被按预期推送。但是一旦终止";",堆栈就会为空与"开始"规则匹配。
我确信我错过了一些基本的东西,因为我们只在课堂上和antlr呆了一天,但我想不出来。我没有为antlr4找到任何幸运的调试器,它可以让我在代码运行时逐步完成代码,但我确实打印出了输入,弹出了项目,并在进行时推送了项目,一切似乎都在"启动"之前
下面是我的代码示例,只有加法运算,没有布尔输入:
grammar RPN;
@header {
import java.util.Stack;
}
@members {
Stack<String> s = new Stack<String>();
int first;
int second;
int parseInteger(String value) {
if(tryParseInt(value)) {
System.out.println("Integer parsed from stack: " + value + "n");
return Integer.parseInt(value);
} else {
System.out.println("ERROR: Invalid integer value; Unable to parsen");
return 0;
}
}
boolean tryParseInt(String value) {
try {
Integer.parseInt(value);
return true;
} catch(NumberFormatException nfe) {
return false;
}
}
boolean stackCheck(Stack st, int size) {
if(st.size() >= size) {
return true;
}
else {
System.out.println("ERROR: Operation needs " + Integer.toString(size) + " valuesn");
return false;
}
}
}
// PARSER RULES
start
: ( expr+ ';')+ EOF
{
if(stackCheck(s, 1)) {
System.out.println("Result: " + s.pop() + ';');
}
if(s.size() > 0) {
System.out.println("Too many operands suppliedn");
}
};
expr
: atom+ OPERATION;
atom
: INT;
// LEXER RULES
INT
: [0-9]+ { s.push(getText()); };
OPERATION
: '+' {
if(stackCheck(s, 2)) {
second = parseInteger(s.pop());
first = parseInteger(s.pop());
s.push(Integer.toString(first + second));
}
};
WS
: ( ' ' | 't' | 'r' | 'n' )+ {skip();};
我已经解决了我的问题。我仍然不完全理解为什么,但解析器规则似乎是在lexer规则之前运行的。因此,我修改了我的程序,使我的解析器规则具有推送新输入和执行操作的操作。
如果有人能帮我理解为什么会这样,我将不胜感激。在我看来,解析器规则是由其他解析器规则和lexer规则组成的。Lexer规则由正则表达式规则组成。由于lexer是最低的公分母,我认为lexer规则会首先被调用,但在我使用antlr时发现这是错误的。