2013-08-28 19 views
18

Vor einer Woche habe ich folgendes Projekt gestartet: eine Grammatik, die Suffixe eines Java-Codes erkennt.ANTLR: Wie kann das Verhalten dieser Grammatik, die Suffixe eines Java-Codes erkennt, erklärt werden?

Ich verwendete die offizielle ANTLR Grammatik für Java (Java.g4) als Grundlinie und begann, einige Regeln hinzuzufügen. Diese neuen Regeln führten jedoch auch zu einer Linksrekursion, mit der ich mich auch befassen musste.

Nach ein paar Tagen der Arbeit hatte ich die following code. Als ich anfing zu testen, bemerkte ich etwas Ungewöhnliches, das ich immer noch nicht erklären kann. Wenn der Eingang { } eingegeben wird, teilt mir der Parser no viable alternative at input '<EOF>', aber wenn ich die Reihenfolge der Klemmen in der rechten Seite der Regel s2, insbesondere, wenn wir die Rechtsseite von v2_1 | v2_2 | v2_3 ... zu v2_36 | v2_1 | v2_2 ... wechseln (die Klemme v2_36 wird nach verschoben) die erste Position), wird die Sequenz { } akzeptiert.

Meine erste Gedanken waren, dass Antlr nicht Rückzieher, weil ich bemerkte, dass mit dem Eingang { } die erste Version des Parsers der Regel v2_3 zu folgen beginnt und melden nur, dass nichts gefunden wird und nicht versuchen, andere Optionen zu prüfen (das was ich denke, aber vielleicht ist es nicht wahr) wie v2_36, die genau die positive Antwort geben.

Aber nach ein paar Recherchen fand ich heraus, dass ANTLR eigentlich Backtrack tut, aber nur, wenn alles andere fehlschlägt. Zumindest gilt dies für v3.3 (lesen Sie es in offiziellen ANTLR Papier), aber ich denke, es gilt auch für v4. Jetzt bin ich ein bisschen verwirrt. Nachdem ich so viele Stunden mit diesem Projekt verbracht habe, würde ich mich wirklich schrecklich fühlen, wenn ich es nicht funktioniere. Kann jemand eine Art Trinkgeld oder etwas geben? Es wäre sehr dankbar, danke.

EDIT

Managed das Problem zu

grammar Java; 
@parser::members {String ruleName; } 

start : compilationUnitSuf EOF; 

compilationUnitSuf 
    : {ruleName = "typeDeclarationSuf"; } s2 
    ; 

s2: '{' '}' v2_81 | '{' '}'; 
v2_81 : {ruleName.equals("enumBodyDeclarationsSuf")}? t173 | t173 '}'; 
t173: '}' | '{'*; 

LBRACKET: '{'; 
RBRACKET: '}'; 

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

Warum also die Vorhersage- Algorithmus vorschlagen, mich zu isolieren s2 -> v'{' '}' v2_81 -> ... statt s2 -> '{' '}' zu folgen?

+1

Ich habe keine Ahnung, was Sie mit _ "Suffixe eines Java-Codes" _. –

+0

Wenn wir die Sequenz 'a [1..n]' der Token eines gegebenen Java-Codes haben, definieren wir ein Suffix als die Sequenz 'a [j], a [j + 1], ..., a [ n] 'für einige' 1 <= j <= n' (für den Code 'Klasse A {int a;}' mögliche Suffixe sind 'A {int a;}', '{int a}},' int a ;} usw.), aber ich denke, das ist irrelevant für die Frage – svs

+2

Gibt es einen Grund, warum Sie ANTLR verwenden? Für das Suffix-Parsing wäre ein GLR-Parser viel einfacher, und es würde ein Suffix verwenden, um eine LR (1) -Grammatik in ungefähr linearer Zeit zu analysieren. Es gibt ein ganzes Kapitel über das Suffix-Parsing in Grune & Jacobs (Parsing Techniques: A Practical Guide). – rici

Antwort

1

Ich denke, dass Sie feststellen werden, dass es nicht in der Weise Backtracking ist, wie Sie erwarten. Der Grund ist, dass es die {} findet und dann erwartet, eine v2_181 zu sehen, die es nicht findet. weil es dann nicht zurückgeht, findet es nicht die Alternative, die Sie wollen. Die Alternative besteht darin, das v2_181 optional zu machen, dann brauchen Sie das Backtracking nicht. Etwas wie unten:

grammar Java; 
@parser::members {String ruleName; } 

start : compilationUnitSuf EOF; 

compilationUnitSuf 
    : {ruleName = "typeDeclarationSuf"; } s2 
    ; 

s2: '{' '}' v2_81?; 
v2_81 : {ruleName.equals("enumBodyDeclarationsSuf")}? t173 | t173 '}'; 
t173: '}' | '{'*; 

LBRACKET: '{'; 
RBRACKET: '}'; 

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