Momentan versuche ich einen Parser für VHDL zu erstellen, der einige der Probleme hat, die C++ - Parser haben. Die kontextfreie Grammatik von VHDL erzeugt ein Parse Wald statt einen einzigen Baum Parse wegen seiner Zweideutigkeit in Bezug auf Funktionsaufrufe und Array-AbonnementsFehlerhafte Bisonreduzierung mit% glr-parser und% merge rules
foo := fun(3) + arr(5);
Diese Zuordnung nur eindeutig analysiert werden kann, wenn der Parser würde tragen um eine hirachisch, Typ-bewusste Symboltabelle , die es verwenden würde, um die Unklarheiten etwas on-the-fly zu lösen.
Ich will nicht, dies zu tun, denn für Aussagen wie die oben erwähnt, die Parsewald nicht exponentiell wachsen würde, aber eher linear auf die Menge der Funktionsaufrufe abhängig und Array-Abonnements.
(Außer natürlich, würde man den Parser mit Aussagen wie Folter)
foo := fun(fun(fun(fun(fun(4)))));
Da Bison Kräfte der Benutzer nur einen einzigen Parse-Baum zu erstellen, I verwendet% merge Attribute alle Teilbäume sammeln rekursiv und hinzugefügt diese Teilbäume unter so genannte AMBIG Knoten im Singleton AST.
Das Ergebnis sieht wie this aus.
Um das obige zu erzeugen, habe ich den Token-Stream "I = I (N);" analysiert. Der Inhalt der Grammatik, die ich in der Datei parse.y verwendet habe, ist unten gesammelt. Es wird versucht, die mehrdeutigen Teile von VHDL zu ähneln:
start: prog
;
/* I cut out every semantic action to make this
text more readable */
prog: assignment ';'
| prog assignment ';'
;
assignment: 'I' '=' expression
;
expression: function_call %merge <stmtmerge2>
| array_indexing %merge <stmtmerge2>
| 'N'
;
function_call: 'I' '(' expression ')'
| 'I'
;
array_indexing: function_call '(' expression ')' %merge <stmtmerge>
| 'I' '(' expression ')' %merge <stmtmerge>
;
The whole sourcecode can be read at this github repository.
Und jetzt kommen wir zum eigentlichen Problem kriegen. Wie Sie oben in der generierten Parser-Struktur sehen können, beziehen sich die Knoten FCALL1 und ARRIDX1 auf denselben Einzelknoten EXPR1, der seinerseits zweimal auf N1 verweist.
Dies sollte auf jeden Fall nicht passiert sein und ich weiß nicht warum. Stattdessen sollte es die Wege sein
FCALL1 -> EXPR2 -> N2
ARRIDX1 -> EXPR1 -> N1
Haben Sie eine Ahnung, warum Bison die oben genannten Knoten wieder verwendet?
Ich schrieb auch einen Bugreport auf dem offiziellen gnu Mailing Liste für Bison, ohne eine Antwort auf diesen Punkt obwohl. Leider aufgrund der restictions für neue Stackoverflow Benutzer, kann ich nicht nein Link zu diesem Fehlerbericht liefern ...