我尝试用ANTLR4编写我的第一个解析器。我在一个已经更大的语法文件中使用的规则之一应该是将2个数字作为2D点匹配。这里是语法的缩减示例:
grammar example;
WS: [ \t\r\n]+ -> channel(HIDDEN);
INT: [0-9]+;
FLOAT: [0-9]*'.'?[0-9]+ ;
IDSTRING: [a-zA-Z_] [a-zA-Z0-9_]*;
NUMBER: (INT | FLOAT) ;
id: IDSTRING;
num: NUMBER;
sem: ';' ;
point: num num;
macro: 'MACRO' id macroprops* 'END ' id;
macroprops: macroorigin ;
macroorigin: 'ORIGIN' point sem;
当我知道输入这样一个基本的例子时:
antlr4 example.g4 -o example/
cd example
javac *.java
echo -e "MACRO m_1\n ORIGIN 7 2.0 ;\nEND m_1" | grun example macro -tree
第一个num
与两个数字匹配,并且它会抛出一个错误,任何整数(此处为0)都不是数字:
line 3:9 mismatched input '0' expecting NUMBER
(macro MACRO (id m_1) (macroprops (macroorigin ORIGIN (point (num 0 0) (num <missing NUMBER>)) (sem ;))) END (id m_1))
我尝试了NUMBER
和point
的定义,但我认为它应该像这样工作。我甚至不明白num
可以匹配两个令牌。有人可以帮忙吗?
答案 0 :(得分:0)
似乎ANTLR4将TOKENS与它们在语法中给出的顺序相匹配。将fragment
添加到INT
和FLOAT
可以解决问题,因为NUMBER
是唯一匹配数字定义的TOKEN,允许浮点数和整数。
grammar example2;
WS: [ \t\r\n]+ -> channel(HIDDEN);
NUMBER: (INT | FLOAT) ;
fragment INT: [0-9]+;
fragment FLOAT: [0-9]*'.'?[0-9]+ ;
IDSTRING: [a-zA-Z_] [a-zA-Z0-9_]*;
id: IDSTRING;
num: NUMBER;
sem: ';' ;
point: num num;
macro: 'MACRO' id macroprops* 'END ' id;
macroprops: macroorigin ;
macroorigin: 'ORIGIN' point sem;
非常感谢您指出要观看令牌流。但我仍然不明白为什么它会将这两个数字与原始问题中的num
规则相匹配。
编辑:另一个错误是,正如GRosenberg所提到的那样,只是按照严格顺序定义语法元素,因此NUMBER
具有比其子规则更高的优先级。