Antlr语法:替代品永远不会匹配

时间:2012-07-30 11:59:46

标签: java antlr

我正在研究Antlr语法来解析多个变量中的多项式表达式。因此,我创建了以下语法:

grammar Function;

parseFunction returns [java.util.List<java.util.List<Object>>]  :   { list = new java.util.ArrayList(); } (p=polypart { list.add($p.list); })+
;

polypart returns [java.util.List<Object> list]: 
  m=NUMBER { list = new java.util.ArrayList(); list.add("+"); list.add($m.text); list.add("0"); }
| s=SIGN m=NUMBER {list = new java.util.ArrayList(); list.add($s.text); list.add($m.text); }
| v=VARIABLE {list = new java.util.ArrayList(); list.add("+"); list.add($v.text); }
| s=SIGN v=VARIABLE {list = new java.util.ArrayList(); list.add($s.text); list.add($v.text); }
| v=VARIABLE e=exponent { list = new java.util.ArrayList(); list.add("+"); list.add($v.text); list.add($e.value); } 
| s=SIGN v=VARIABLE e=exponent { list = new java.util.ArrayList(); list.add($s.text); list.add($v.text); list.add($e.value); }
| m=NUMBER v=VARIABLE { list = new java.util.ArrayList(); list.add("+"); list.add($m.text); $list.add($v.text); }
| s=SIGN m=NUMBER v=VARIABLE { list = new java.util.ArrayList(); list.add($s.text); list.add($m.text); $list.add($v.text); }
| m=NUMBER v=VARIABLE e=exponent { list = new java.util.ArrayList(); list.add("+"); list.add($m.text); list.add($v.text); list.add($e.value); }
| s=SIGN m=NUMBER v=VARIABLE e=exponent { list = new java.util.ArrayList(); list.add($s.text); list.add($m.text); list.add($e.value); }
;

exponent returns [int value]: ('^' n=NUMBER) { $value = 1; if ( $n != null && $n.text.length() > 0) $value = Integer.parseInt($n.text); }
;

VARIABLE    : ('a'..'z'|'A'..'Z')+
;

NUMBER  : ('0'..'9')+
;

SIGN    :   ('+'|'-')
;

WS  :   (' '|'\t')+ {skip();} ;

显然,这不起作用。用Antlr 3.4编译它,我得到了警告

  

“SIGN NUMBER VARIABLE”使用替代品2,8; “SIGN NUMBER VARIABLE   '^'NUMBER“使用替代品2,10;”NUMBER VARIABLE“使用   备选方案1,7和“NUMBER VARIABLE'^'NUMBER”使用替代方案   1,9。

我可以忍受这些警告(虽然我很感兴趣,为什么它们会弹出),但困难的是我得到以下错误:

error(201): Function.g:6:47: The following alternatives can never be matched: 7,8,9,10

这是因为它们因警告而被禁用,所以我想我必须先解决警告。


编辑:

在仔细考虑了这个问题之后,我通过切换一些代码来修改我的代码,现在我至少不会再遇到任何错误了。但是,我还没有测试它,我也想摆脱最后两个警告。新代码是:

grammar Function;

parseFunction returns [java.util.List<java.util.List<Object>>]  :   { list = new java.util.ArrayList(); } (p=polypart { list.add($p.list); })+
;

polypart returns [java.util.List<Object> list]: 
s=SIGN m=NUMBER v=VARIABLE e=exponent { list = new java.util.ArrayList(); list.add($s.text); list.add($m.text); list.add($e.value); }
| m=NUMBER v=VARIABLE e=exponent { list = new java.util.ArrayList(); list.add("+"); list.add($m.text); list.add($v.text); list.add($e.value); }
| s=SIGN m=NUMBER v=VARIABLE { list = new java.util.ArrayList(); list.add($s.text); list.add($m.text); $list.add($v.text); }
| m=NUMBER v=VARIABLE { list = new java.util.ArrayList(); list.add("+"); list.add($m.text); $list.add($v.text); }
| s=SIGN v=VARIABLE e=exponent { list = new java.util.ArrayList(); list.add($s.text); list.add($v.text); list.add($e.value); }
| v=VARIABLE e=exponent { list = new java.util.ArrayList(); list.add("+"); list.add($v.text); list.add($e.value); } 
| s=SIGN v=VARIABLE {list = new java.util.ArrayList(); list.add($s.text); list.add(1); list.add($v.text); }
| v=VARIABLE {list = new java.util.ArrayList(); list.add("+"); list.add(1); list.add($v.text); }
| s=SIGN m=NUMBER {list = new java.util.ArrayList(); list.add($s.text); list.add($m.text); }
| m=NUMBER { list = new java.util.ArrayList(); list.add("+"); list.add($m.text); }
;

exponent returns [int value]: ('^' n=INTEGER) { $value = 1; if ( $n != null && $n.text.length() > 0) $value = Integer.parseInt($n.text); }
;

VARIABLE    : ('a'..'z'|'A'..'Z')+
;

INTEGER : ('0'..'9')+
;

NUMBER  : ('0'..'9')+(','('0'..'9')+)?
;

SIGN    :   ('+'|'-')
;

WS  :    (' ' | '\t' | '\r'| '\n')+ {skip();} 
;

现在我收到以下警告:

"NUMBER VARIABLE" uses mutiple alternatives: 4,10 (10 is disabled).
"SIGN NUMBER VARIABLE" uses multiple alternatives: 3,9 (9 is disabled).

如果有人能向我解释如何摆脱这两个警告,我将不胜感激。


在对Parser进行测试后,我可以说它确实接受了:

X; +X; -X; X^42; +X^42; -X^42

它不接受:

42; +42; -42; 42X^42; +42X^42; -42X^42

1 个答案:

答案 0 :(得分:0)

如果在没有前导符号的情况下接受NUMBER和VARIABLE,并且也接受NUMBER VARIABLE形式的输入,则可能有两种解释:NUMBER VARIABLE - &gt; polypart polypart - &gt; NUMBER polypart - &gt; NUMBER VARIABLE或NUMBER VARIABLE - &gt; polypart - &gt; NUMBER VARIABLE因此,领先SIGN的案例必须来源,然后它才有效!

以下代码编译时没有警告或错误:

grammar Function;

parseFunction returns [java.util.List<java.util.List<Object>> list] :   
    { list = new java.util.ArrayList(); }                                              ( f=functionPart { list.add($f.list); } )+
|   { list = new java.util.ArrayList(); } ( fb=functionBegin ) { list.add($fb.list); } ( f=functionPart { list.add($f.list); } )*
;

functionBegin returns [java.util.List<Object> list]:
m=NUMBER v=VARIABLE e=exponent  { list = new java.util.ArrayList(); list.add("+"); list.add($m.text); list.add($v.text); list.add($e.value); }
| m=NUMBER v=VARIABLE           { list = new java.util.ArrayList(); list.add("+"); list.add($m.text); list.add($v.text); }
| v=VARIABLE e=exponent         { list = new java.util.ArrayList(); list.add("+"); list.add("1");     list.add($v.text); list.add($e.value); }  
| v=VARIABLE                    { list = new java.util.ArrayList(); list.add("+"); list.add("1");     list.add($v.text); }
| m=NUMBER                      { list = new java.util.ArrayList(); list.add("+"); list.add($m.text); }
;

functionPart returns [java.util.List<Object> list] :    
s=SIGN m=NUMBER v=VARIABLE e=exponent   { list = new java.util.ArrayList(); list.add($s.text); list.add($m.text); list.add($v.text); list.add($e.value); }
| s=SIGN m=NUMBER v=VARIABLE            { list = new java.util.ArrayList(); list.add($s.text); list.add($m.text); list.add($v.text); }
| s=SIGN v=VARIABLE e=exponent          { list = new java.util.ArrayList(); list.add($s.text); list.add("1");     list.add($v.text); list.add($e.value); }
| s=SIGN v=VARIABLE                     { list = new java.util.ArrayList(); list.add($s.text); list.add("1");     list.add($v.text); }
| s=SIGN m=NUMBER                       { list = new java.util.ArrayList(); list.add($s.text); list.add($m.text); }
;

exponent returns [int value]: ('^' n=INTEGER) { $value = 1; if ( $n != null && $n.text.length() > 0) $value = Integer.parseInt($n.text); }
;

VARIABLE    : ('a'..'z'|'A'..'Z')+
;

INTEGER : ('0'..'9')+
;

NUMBER  : ('0'..'9')+ (','('0'..'9')+)?
;

SIGN    :   ('+'|'-')
;

WS  :    (' ' | '\t' | '\r'| '\n')+ {skip();} 
;

如果在Java中编译和使用该语法,则接受大多数输入值。显然,并非所有有效输入值都被接受。弹出不使用逗号的数字,如+42,会抛出错误:

line 1:1 no viable alternative at input '+'

但是,这与原始问题不符,将会澄清here