我正在使用IntelliJ的antlr4插件为我正在处理的项目创建语法。在学习如何使用antlr的过程中,我看了下面显示的Github用户shmatov的简单antlr4计算器。
grammar Calculator;
INT : [0-9]+;
DOUBLE : [0-9]+'.'[0-9]+;
PI : 'pi';
E : 'e';
POW : '^';
NL : '\n';
WS : [ \t\r]+ -> skip;
ID : [a-zA-Z_][a-zA-Z_0-9]*;
PLUS : '+';
EQUAL : '=';
MINUS : '-';
MULT : '*';
DIV : '/';
LPAR : '(';
RPAR : ')';
input
: plusOrMinus NL? EOF # Calculate
;
plusOrMinus
: plusOrMinus PLUS multOrDiv # Plus
| plusOrMinus MINUS multOrDiv # Minus
| multOrDiv # ToMultOrDiv
;
multOrDiv
: multOrDiv MULT pow # Multiplication
| multOrDiv DIV pow # Division
| pow # ToPow
;
pow
: unaryMinus (POW pow)? # Power
;
unaryMinus
: MINUS unaryMinus # ChangeSign
| atom # ToAtom
;
atom
: PI # ConstantPI
| E # ConstantE
| DOUBLE # Double
| INT # Int
| ID # Variable
| LPAR plusOrMinus RPAR # Braces
;
有趣的是,当输入单个数字时,例如整数“5”,生成的解析树会显示运行#Plus和#Multiplication标签。这对我来说没有多大意义。输入中没有+
或*
运算符。我已经上传了下面的解析树图片,以便更好地了解我在说什么。
似乎antlr默认为规则中的第一个替代方案,但是计算器采用标记# Calculate -> # ToMultOrDiv -> # ToPow -> # ToAtom -> # Int
的直线路径会不会更有意义?如果没有合适的操作员,它甚至如何通过#Plus和#Rultiplication?
答案 0 :(得分:0)
好观察!我猜测ANTLR插件没有正确显示标签。你可以在这里打开一个问题:https://github.com/antlr/intellij-plugin-v4/issues(编辑,我自己开了一个问题:https://github.com/antlr/antlr4/issues/2222)
当您让输入"5"
通过侦听器时,您将看到显示正确的路径:
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
public class Main {
static class Listener extends CalculatorBaseListener {
@Override
public void enterCalculate(CalculatorParser.CalculateContext ctx) {
System.out.println("Calculate");
}
@Override
public void enterToMultOrDiv(CalculatorParser.ToMultOrDivContext ctx) {
System.out.println("ToMultOrDiv");
}
@Override
public void enterToPow(CalculatorParser.ToPowContext ctx) {
System.out.println("ToPow");
}
@Override
public void enterPower(CalculatorParser.PowerContext ctx) {
System.out.println("Power");
}
@Override
public void enterToAtom(CalculatorParser.ToAtomContext ctx) {
System.out.println("ToAtom");
}
@Override
public void enterInt(CalculatorParser.IntContext ctx) {
System.out.println("Int");
}
}
public static void main(String[] args) {
CalculatorLexer lexer = new CalculatorLexer(CharStreams.fromString("5"));
CalculatorParser parser = new CalculatorParser(new CommonTokenStream(lexer));
ParseTreeWalker.DEFAULT.walk(new Listener(), parser.input());
}
}
将打印:
Calculate
ToMultOrDiv
ToPow
Power
ToAtom
Int