为什么 Antlr 默认使用某些替代方案?
Why does Antlr default to certain alternatives over others?
我正在使用 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 和#Multiplication?
好观察!我猜 ANTLR 插件没有正确显示标签。你可以在这里打开一个问题:https://github.com/antlr/intellij-plugin-v4/issues (EDIT, opened an issue myself: 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
我正在使用 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 和#Multiplication?
好观察!我猜 ANTLR 插件没有正确显示标签。你可以在这里打开一个问题:https://github.com/antlr/intellij-plugin-v4/issues (EDIT, opened an issue myself: 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