用 Java 生成 Antlr 解析器:并非所有输入都被读取 [英] Generated Antlr Parser in Java: Not all inputs are read

查看:22
本文介绍了用 Java 生成 Antlr 解析器:并非所有输入都被读取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究我的 Antlr 语法,以使用 Java 解析多个变量中的多项式函数.合法输入的例子是

I am working on my Antlr grammar to parse polynomial functions in multiple variables using Java. Examples for legal input are

42; X; +42X; Y^42; 1337HelloWorld; 13,37X^42; 

以下语法在编译时没有警告或错误:

The following grammar does compile without warnings or errors:

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 中编译和使用,确实接受大多数输入值.显然,并非所有有效的输入值都被接受.一旦弹出一个不使用逗号的数字,比如输入

This grammar, if compiled and used in Java does accept most input values. Apparently, not all valid input values are accepted. As soon as a number not using a comma pops up, like the inputs

+42; 42; 42X^1337; 

抛出错误(来自输入+42"的错误):

an error is thrown (error from input "+42"):

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

如果我将输入修改为

+42,0; 42,0; 42,0X^1337

谁能说一下,为什么以及如何解决它?

Can anyone say, why and how to fix it?

推荐答案

第一个匹配最长的词法规则获胜,因此 42 是一个 INTEGER,而 NUMBER 实际上只在逗号部分存在时才匹配,即当 NUMBERINTEGER 匹配得更长时.

The first lexer rule with the longest match wins, thus 42 is an INTEGER, and NUMBER in fact only matches when the comma part is present, i.e. when NUMBER has a longer match than INTEGER.

这可以通过添加解析器规则来解决

This can be fixed by adding a parser rule

number : NUMBER | INTEGER ;

并使用它代替其他解析器规则中的 NUMBER.

and using that instead of NUMBER from other parser rules.

这篇关于用 Java 生成 Antlr 解析器:并非所有输入都被读取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆