最优歧义解决

时间:2012-04-26 10:49:42

标签: antlr grammar antlr3 ambiguity

我正在尝试解决如何处理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作为IDB: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

2 个答案:

答案 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解析为以下解析树:

enter image description here

1 What is a 'semantic predicate' in ANTLR?

答案 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;};