我正在尝试解决如何处理ANTLR
中的歧义问题。
我需要正确解析带有大小前缀的标识符或标识符。
首先,我想到了这个错误的语法
grammar PrefixProblem;
options
{
language = Java;
}
goal: (size_prefix ':')? id;
size_prefix: B;
id: LETTER+;
LETTER: 'A'..'Z' ;
B: 'B';
WSFULL:(' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;};
我需要将B
作为ID
,B:B
作为id
B
处理前缀B
。它不起作用。
然后我找到了解决这个问题的两种方法。
grammar PrefixSolution1;
options
{
language = Java;
}
goal: (size_prefix ':')? id;
size_prefix: B;
id: (LETTER | B)+;
LETTER: 'A' | 'C'..'Z' ;
B: 'B';
WSFULL:(' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;};
在上面的代码中,B
已从lexer
规则中删除,并在id
规则中连接。
grammar PrefixSolution2;
options
{
language = Java;
}
goal: PREFIX_VAR;
PREFIX_VAR: (B WSFULL* ':' WSFULL*)? ID;
fragment ID: (LETTER)+;
fragment LETTER: 'A'..'Z' ;
fragment B: 'B';
WSFULL:(' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;};
我刚将规则移至lexer
。
PrefixSolution1
有一个主要的骗局,我需要将词法规则分成较小的块,然后再串联。
PrefixSolution2
:这种做法导致我总是需要一个应该忽略的帐户空白字符。
至于我,两种解决方案都会导致为整个语言编写语法。还有其他解决方案吗?如果不是,哪种方式是最优的?
所有源代码均可用here
答案 0 :(得分:1)
我不会选择其中任何一个。我只需创建ID
令牌和不 B
令牌(或创建PREFIX_VAR
令牌:这属于解析器。)
您可以在解析器规则中使用消除歧义的语义谓词 1 匹配大写字母B(capB
),如下所示:
grammar Test;
goal
: (prefixVar | ID)+ EOF
;
prefixVar
: capB ':' ID
;
capB
: {input.LT(1).getText().equals("B")}? ID
;
ID : LETTER+;
WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;};
fragment LETTER: 'A'..'Z' ;
将输入B:B B B:C
解析为以下解析树:
答案 1 :(得分:0)
试试这个:
grammar PrefixProblem;
options
{
language = Java;
}
goal: (size_prefix ':')? (id|B);
size_prefix: B;
id: LETTER+;
LETTER: 'A'|'C'..'Z' ;
B: 'B';
WSFULL:(' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;};