альтернативный номер не установлен правильно для правил с левой рекурсией - PullRequest
0 голосов
/ 05 июня 2019

У меня есть следующая грамматика выражений, которую я генерирую синтаксическим анализатором, используя опцию
-DcontextSuperClass=RuleContextWithAltNum, чтобы я мог узнать, какая альтернатива для правила соответствует.Однако для грамматики с левым рекурсивным правилом, подобным приведенному ниже, она дает неожиданные значения для альтернатив, фактически каждой альтернативе правила aexpr присваивается альтернативный номер 1.

grammar expr;

expr        : aexpr  

    ;

aexpr       :   NUM 
    |   IDENTIFIER
    |   aexpr binop aexpr  
    |   '(' aexpr ')'
    |   funcall
    |   '-' aexpr
    ;

binop       :  '*' | '+' | '-' | '**' | '/'
            ;



funcall     :   IDENTIFIER '('expr (',' expr)*')'
            ;

 NUM : [1-9][0-9]*
     ;

 IDENTIFIER : [a-zA-Z][a-zA-Z0-9_]*
            ;

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

Вот драйверпрограмма и слушатель, который просто печатает альтернативный номер.

public class Main {
    public static void main(String[] args) throws Exception {
    // create a CharStream that reads from standard input
    ANTLRInputStream input = new ANTLRInputStream(System.in);

    // create a lexer that feeds off of input CharStream
    exprLexer lexer = new exprLexer(input);

    // create a buffer of tokens pulled from the lexer
    CommonTokenStream tokens = new CommonTokenStream(lexer);

    // create a parser that feeds off the tokens buffer
    exprParser parser = new exprParser(tokens);

    ParseTree tree = parser.expr(); // begin parsing at init rule
    ParseTreeWalker walker = new ParseTreeWalker();
    Listener listen = new Listener();
    walker.walk(listen, tree);
    System.out.println(tree.toStringTree(parser)); 
  }
}


public class Listener extends exprBaseListener {
    public void enterEveryRule(ParserRuleContext ctx) {
       System.out.println(ctx.getRuleIndex() +"/"+ctx.getAltNumber());
   }
}

Я проверил его на следующих входах

входное выражение: ((21))

output:

0/1
1/1
1/1
1/1
(expr:1 (aexpr:1 ( (aexpr:1 ( (aexpr:1 21) )) )))

Третий вариант правила aexpr был найден, но он возвращается с альтернативным номером 1.

Однако, избавление от (комментирование)левая рекурсивная альтернатива aexpr : aexpr binop aexpr, возвращаются правильные альтернативные номера.На том же входе ((21)) я получаю:

0/1
1/3
1/3
1/1
(expr:1 (aexpr:3 ( (aexpr:3 ( (aexpr:1 21) )) )))

Подобная проблема , кажется, все еще открыта, хотя позже в комментариях говорится, что она будет исправлена ​​в Antlr4,6.Я использую 4.7.2.Кто-нибудь когда-нибудь пытался решить эту проблему, или, по крайней мере, получить правильные альтернативные числа для другой нерекурсивной альтернативы aexpr?Или какая-либо идея о том, как сделать исправление из источников (я просматривал источники antlr)?

...