Linke Rekursion in ANTLR entfernen

As wird in @ erklä Linke Rekursion entfernen gibt es zwei Möglichkeiten, die linke Rekursion zu entfernen.

Ändern Sie die ursprüngliche Grammatik, um die linke Rekursion mit einer Prozedur zu entfernenSchreibe die Grammatik ursprünglich so, dass die linke Rekursion nicht angezeigt wird

Welche Leute verwenden normalerweise, um die linke Rekursion mit ANTLR zu entfernen (nicht zu haben)? Ich habe Flex / Bison als Parser verwendet, aber ich muss ANTLR verwenden. Das einzige, was ich über die Verwendung von ANTLR (oder LL-Parser im Allgemeinen) befürchte, ist die Entfernung von Rekursionen.

Wie ernst ist es in der Praxis, die Linksrekursion in ANTLR zu entfernen? Ist dies ein Showstopper bei der Verwendung von ANTLR? Oder interessiert es niemanden in der ANTLR-Community?Ich mag die Idee der AST-Generation von ANTLR. Welche Methode (von den 2 Methoden zum Entfernen der linken Rekursion) ist für die schnelle und einfache Erlangung von AST vorzuziehen?Hinzugefüg

Ich habe mit der folgenden Grammatik experimentiert.

E -> E + T|T
T -> T * F|F
F -> INT | ( E )

Nach dem Entfernen der linken Rekursion erhalte ich die folgende

E -> TE'
E' -> null | + TE'
T -> FT'
T' -> null | * FT'

Ich könnte mir die folgende ANTLR-Darstellung einfallen lassen. Auch wenn es relativ einfach und unkompliziert ist, sollte die Grammatik ohne die linke Rekursion der bessere Weg sein.

grammar T;

options {
    language=Python;
}

start returns [value]
   : e {$value = $e.value};
e returns [value]
   : t ep  
     {
       $value = $t.value
       if $ep.value != None:
         $value += $ep.value
     }
   ;
ep returns [value]
   : {$value = None}
   | '+' t r = ep 
     {
       $value = $t.value
       if $r.value != None:
            $value += $r.value
     }
   ;
t returns [value]
  : f tp 
    {
      $value = $f.value
      if $tp.value != None:
        $value *= $tp.value
    }
  ;
tp returns [value]
  : {$value = None}
  | '*' f r = tp 
    {
      $value = $f.value;
      if $r.value != None:
        $value *= $r.value
    }
  ;
f returns [int value]
  : INT {$value = int($INT.text)}
  | '(' e ')' {$value = $e.value}
  ;

INT :   '0'..'9'+ ;
WS: (' '|'\n'|'\r')+ {$channel=HIDDEN;} ;

Antworten auf die Frage(8)

Ihre Antwort auf die Frage