我认为这是一个简单的ANTLR问题。我有两种令牌类型:ident
和special_ident
。我希望我的special_ident
匹配一个字母后跟一个数字。我希望通用ident
匹配单个字母,可选地后跟任意数量的字母或数字。我的(不正确的)语法如下:
expr
: special_ident
| ident
;
special_ident : LETTER DIGIT;
ident : LETTER (LETTER | DIGIT)*;
LETTER : 'A'..'Z';
DIGIT : '0'..'9';
当我尝试检查这个语法时,我收到了这个警告:
决策可以使用多种替代方案匹配输入,例如“LETTER DIGIT”:1,2。 结果,对该输入禁用了备选方案2
我理解我的语法含糊不清,A1
之类的输入可以与ident
或special_ident
匹配。我真的只想在最狭窄的情况下使用special_ident
。
以下是一些示例输入以及我希望匹配的内容:
A : ident
A1 : special_ident
A1A : ident
A12 : ident
AA1 : ident
我如何形成语法,以便正确识别我的两种标识符?
答案 0 :(得分:3)
似乎你有3个案例:
A
AN
A(A|N)(A|N)+
您可以将中间一个归类为special_ident
,将另外两个归类为ident
;似乎应该这样做。
我对ANTLR有点生疏,我希望这个提示已经足够了。我可以尝试为你写出表达,但它们可能是错的:
long_ident : LETTER (LETTER | DIGIT) (LETTER | DIGIT)+
special_ident : LETTER DIGIT;
ident : LETTER | long_ident;
答案 1 :(得分:2)
扩展卡尔的想法,我猜你有四种不同的情况:
只有选项2应该是令牌special_ident,其他三个应该是ident。所有令牌都可以通过语法单独识别。这是我能够在ANTLRWorks中测试的快速语法,它似乎适合我。我认为卡尔在尝试检查AA时可能会有一个错误,但是让你获得99%有一个巨大的好处,所以这只是对他快速思考的一个小修改。
prog
: (expr WS)+ EOF;
expr
: special_ident {System.out.println("Found special_ident:" + $special_ident.text + "\n");}
| ident {System.out.println("Found ident:" + $ident.text + "\n");}
;
special_ident : LETTER DIGIT;
ident : LETTER
|LETTER DIGIT (LETTER|DIGIT)+
|LETTER LETTER (LETTER|DIGIT)*;
LETTER : 'A'..'Z';
DIGIT : '0'..'9';
WS
: (' '|'\t'|'\n'|'\r')+;