【问题标题】:What is wrong with this grammar? (ANTLRWorks 1.4)这个语法有什么问题? (ANTLRWorks 1.4)
【发布时间】:2010-09-26 18:30:29
【问题描述】:

我有以下用 ANTLRWorks 1.4 编写的代码

grammar hmm;

s           :   (put_a_in_b)|(put_out_a)|(drop_kick)|(drop_a)|(put_on_a);

put_a_in_b  :   (PUT_SYN)(ID)(IN_SYN)(ID);  
put_out_a   :   (PUT2_SYN)(OUT_SYN)(ID) | (E1)(ID); 
drop_kick   :   ('drop')('kick')(ID);
drop_a      :   (DROP_SYN)(ID);
put_on_a    :   (E2)(ID);

PUT_SYN     :   'put' | 'place' | 'drop';
PUT2_SYN    :   'put' | 'douse';
IN_SYN      :   'in' | 'into' | 'inside' | 'within';    
OUT_SYN     :   'out';
E1          :   'extinguish'|'douse';
DROP_SYN    :   'drop' | 'throw' | 'relinquish';
WS          :   ( ' '  | '\t' | '\r' | '\n' ) {$channel=HIDDEN;};
ID          :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
E2          :   'put on'|'don'|'wear';
COMMENT
    :   '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
    ;

当我使用输入运行它时:

drop object

我得到一个 MismatchedTokenException(5 != 15)。

然后输入:

put o1 in o2

我得到一个 NoViableAltException。

虽然它运行良好

place o2 in o2

我是新手,但似乎有歧义?或者我对 ANTLR 的使用不正确?

【问题讨论】:

  • 它是否处理“放在对象上”? 'throw object' 呢?
  • (这是“rikki”,提问者。在其他计算机上登录时遇到问题,但现在已登录。)是的,这些都可以解析。

标签: antlr grammar ambiguity antlrworks


【解决方案1】:

您已将'drop''put' 放入两个不同的词法分析器规则中:

PUT_SYN  : 'put' | 'place' | 'drop';          // drop & put
PUT2_SYN : 'put' | 'douse';                   //        put
...
DROP_SYN : 'drop' | 'throw' | 'relinquish';   // drop

当词法分析器遇到put 时,PUT_SYN 将始终是与之匹配的规则,因此可以(或应该)从PUT2_SYN 规则中删除'put'

因此,您在解析字符串 drop object 时遇到的问题:解析器将尝试匹配 drop_a : (DROP_SYN)(ID);,但 "drop" 将在词法分析器规则 PUT_SYN 中匹配。

编辑

这些同义词列表可以更好地制成解析器规则(而不是词法分析器规则)。这是一个小演示:

grammar TextAdventure;

parse
  :  command (EndCommand command)* EOF
  ;

command
  :  put_syn_1 OtherWord in_syn OtherWord
  |  put_syn_2 out_syn_1 OtherWord
  |  out_syn_2 OtherWord
  |  Drop Kick OtherWord
  |  drop_syn OtherWord
  ;

drop_syn
  :  Drop
  |  Throw 
  |  Relinquish
  ;

in_syn
  :  In
  |  Into
  |  Inside
  |  Within
  ; 

put_syn_1
  :  Put
  |  Place
  |  Drop
  ;

put_syn_2
  :  Put
  |  Douse
  ;

out_syn_1
  :  Out
  ;

out_syn_2
  :  Extinguish
  |  Douse
  ;

Space      : (' ' | '\t' | '\r' | '\n'){$channel=HIDDEN;};
EndCommand : ';';
Put        : 'put';
Place      : 'place';
Drop       : 'drop';
Douse      : 'douse';
In         : 'in';
Into       : 'into';
Inside     : 'inside';
Within     : 'within';    
Out        : 'out';
Extinguish : 'extinguish';
Throw      : 'throw';
Relinquish : 'relinquish';
Kick       : 'kick';
OtherWord  : ('a'..'z' | 'A'..'Z')+;

解释以下来源时:

drop object ; put yourself in myshoes ; place it in avase

您将看到 ANTLRWorks 生成以下解析树:

【讨论】:

  • 听起来很合理......解决方法是什么 - 获得各种替代方案?将非终端用于“drop”(另一个用于“put”),然后使用该非终端构建替代方案?
  • 感谢巴特的解释。我也想知道一种解决方法。
  • 解决方案是排除这种共性并将关键字put 放入自己的规则中。像PUT_SYN: 'put' (PUT_CMD); PUT_CMD: (ID) ...|(OUT_SYN) ...; 这样的东西只是我所说的“分解”的一个例子。
  • @Rao,@Jonathan,修复/解决方法是 @linuxuser27 提到的。
  • @Rao(或@rikki),也许您想解释一下您要解析哪种语言,因为我在您的语法中看到了很多可能需要修复的奇怪内容。
猜你喜欢
  • 2016-09-06
  • 2012-07-07
  • 2012-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多