Ich möchte benutzerdefinierte domänenspezifische Sprachen analysieren. Diese Sprachen ähneln normalerweise mathematischen Notationen (ich analysiere keine natürliche Sprache). Benutzer definieren ihr DSL in einer BNF-Notation wie folgt:
expr ::= LiteralInteger
| ( expr )
| expr + expr
| expr * expr
Eingaben wie 1 + ( 2 * 3 )
müssen akzeptiert werden, Eingaben wie 1 +
müssen als falsch zurückgewiesen werden und Eingaben wie 1 + 2 * 3
müssen als mehrdeutig zurückgewiesen werden.
Eine zentrale Schwierigkeit dabei ist der benutzerfreundliche Umgang mit mehrdeutigen Grammatiken. Die Grammatik so einzuschränken, dass sie eindeutig ist, ist keine Option: So ist die Sprache - die Idee ist, dass Autoren lieber Klammern weglassen, wenn sie nicht notwendig sind, um Mehrdeutigkeiten zu vermeiden. Solange ein Ausdruck nicht mehrdeutig ist, muss ich ihn analysieren, und wenn nicht, muss ich ihn ablehnen.
Mein Parser muss an jeder kontextfreien Grammatik arbeiten, auch an mehrdeutigen, und muss alle eindeutigen Eingaben akzeptieren. Ich benötige den Analysebaum für alle akzeptierten Eingaben. Bei ungültigen oder mehrdeutigen Eingaben möchte ich im Idealfall gute Fehlermeldungen, aber zunächst nehme ich, was ich bekommen kann.
Normalerweise rufe ich den Parser bei relativ kurzen Eingaben mit gelegentlich längeren Eingaben auf. Daher ist der asymptotisch schnellere Algorithmus möglicherweise nicht die beste Wahl. Ich möchte für eine Verteilung von rund 80% Eingaben mit weniger als 20 Symbolen, 19% zwischen 20 und 50 Symbolen und 1% seltenen längeren Eingaben optimieren. Die Geschwindigkeit für ungültige Eingaben ist kein großes Problem. Desweiteren erwarte ich eine Änderung des DSL etwa alle 1000 bis 100000 Eingänge; Ich kann ein paar Sekunden damit verbringen, meine Grammatik vorzubereiten, nicht ein paar Minuten.
Welche Analysealgorithmen sollte ich bei meinen typischen Eingabegrößen untersuchen? Sollte die Fehlerberichterstattung ein Faktor in meiner Auswahl sein, oder sollte ich mich auf das Parsen eindeutiger Eingaben konzentrieren und möglicherweise einen vollständig separaten, langsameren Parser ausführen, um Fehlerrückmeldung zu geben?
(In dem Projekt, in dem ich das benötigte (vor einiger Zeit), habe ich CYK verwendet , das nicht zu schwer zu implementieren war und für meine Eingabegrößen angemessen funktionierte, aber keine sehr schönen Fehler produzierte.)
x+y+z
.
+
, x+y+z
ist also in der Tat mehrdeutig und daher falsch.