处理ANTLR4中模糊语法中的重载符号

时间:2014-04-14 13:58:51

标签: parsing prolog antlr4 answer-set-programming

我正在尝试为答案集编程(ASP)的方言编写一个解析器,就语法而言,它看起来像带有一些扩展的 Prolog 。 例如,一个扩展名为扩展,这意味着fact(1..3).例如在fact(1). fact(2). fact(3).中展开。请注意,该语言理解INTFLOAT个数字,并使用.作为终结符。

在某些情况下,解析器无法区分整数,浮点数,扩展名和分隔符,因为我认为语言显然不明确。在这种情况下,我必须明确地用白色空格分隔令牌。但是,任何 Prolog ASP 解析器都能正确处理此类产品。我读到 ANTLR4 可以自动消除有问题的产品歧义,但可能需要一些帮助,但我不知道该怎么办! ;-)我读过像herehere这样的内容,但显然他们没有帮助我。

有人可以告诉我该如何克服这种歧义吗? 请注意,我无法更改语言,因为它非常标准。 为了简化专家的工作,我创建了一个最小的工作示例。

grammar Test;

program: 
  statement* ;

statement: // DOT is the statement terminator
  range DOT |
  intNum DOT |
  floatNum DOT ;

intNum: // not needed, but helps in TestRig
  INT;

floatNum: // not needed, but helps in TestRig
  FLOAT;

range: // defines an expansion
  INT DOTS INT ;

DOTS: '..';
DOT: '.';

FLOAT: DIGIT+ '.' DIGIT* | '.' DIGIT+ ;
INT: DIGIT+ ;

WS: [ \t\r\n]+ -> skip ;

fragment NONZERO     : [1-9] ;
fragment DIGIT       : [0] | NONZERO ;

我使用以下输入:

1 .
1. .
1.5 .
.5 .
1 .. 5 .

1.
1..
1.5.
.5.
1..5.

我得到以下错误,而这些错误由其他工具解析:

line 8:0 extraneous input '1.' expecting '.'
line 11:2 extraneous input '.5' expecting '.'

非常感谢提前!

2 个答案:

答案 0 :(得分:1)

在您的DOTS规则之前,为语句终端点添加唯一规则并消除DOTS规则的歧义(并更改您的其他规则以使用TERMINAL):

TERMINAL: DOT { isTerminal(1) }? ;
DOTS: DOT DOT { !isTerminal(2) }? ;
DOT: '.';

其中谓词方法只是在_input字符流上向前看,以查看在当前令牌索引处,下一个字符是否为空格。把这样的东西放在你的语法中的@member块中:

public boolean isTerminal(int la) {
    int offset = _tokenStartCharIndex + 1 + la;
    String s = _input.getText(Interval.of(offset, offset));
    if (Character.isWhitespace(s.charAt(0))) {
        return true;
    }
    return false;
}

如果DOTS和尾随INT之间的空格有效,则可能需要做更多的工作。

答案 1 :(得分:0)

Prolog不接受1.作为浮点数。此功能使您的语法明显更加模糊,因此可能尝试删除该功能。