Ja. Viele moderne Programmiersprachen haben diese Eigenschaft, einschließlich Algol 60, C und C ++; siehe unten für Details.
Algol 60 hatte bekanntlich das Problem "Dangling else" . Bei einigen Programmen war es nicht eindeutig, wie sie analysiert werden sollten (welcher Analysebaum sollte das Ergebnis sein).
Viele moderne Sprachen lösen dieses Problem, indem sie eine Grammatik auswählen, die die Mehrdeutigkeit auf bestimmte Weise auflöst. Dies erfordert jedoch eine sorgfältige Erstellung der Grammatik, um Mehrdeutigkeiten zu beseitigen. Oft führt die natürlichste Art, die Grammatik zu schreiben, zu einer mehrdeutigen Grammatik, und Sie müssen die Grammatik transformieren, um die Mehrdeutigkeit zu vermeiden.
Ein anderer Ansatz ist die Verwendung eines GLR-Parsers, der diese Grammatiken verarbeiten kann. Anschließend können Sie zur Laufzeit prüfen, ob mehrere mögliche Parser vorhanden sind, und die Mehrdeutigkeit beheben.
Ein weiteres klassisches Beispiel sind die Programmiersprachen C und C ++. Die Referenzgrammatik für C ist nicht kontextfrei, denn wenn Sie einen Namen sehen, müssen Sie wissen, ob es sich um den Namen eines Typs oder einer Variablen handelt, um zu wissen, wie die Anweisung analysiert wird. Betrachten Sie zum Beispiel den Ausdruck
(A)*B
Wenn A
es sich um eine Variable handelt, ist dies die Multiplikation zweier Variablen und entspricht A*B
. Wenn A
es sich jedoch um den Namen eines Typs handelt, handelt es sich um eine Zeiger-Dereferenzierung und Typumwandlung (ebenso B
wie ein Variablenname, der einen Zeigertyp enthält), der äquivalent zu ist (A) *B
.
Ähnlich,
A*B;
A
Dies kann entweder eine Variablendeklaration sein (wenn der Name eines Typs ist, deklariert dies eine Variable mit dem Namen, B
deren Typ Zeiger auf ist A
) oder eine Multiplikation (wenn A
und B
sind die Namen von Variablen).
Compiler beheben dies normalerweise, indem sie zusätzlichen Code einfügen, der außerhalb der Sprache reiner kontextfreier Grammatiken liegt. Sie verfolgen alle Variablennamen und Typnamen im Gültigkeitsbereich und verwenden diese, um das Parsen bei dieser Mehrdeutigkeit zu steuern. Siehe den Lexer Hack .
Siehe auch LL und LR im Kontext: Warum Parsing-Tools schwierig sind und Bisons Handbuchseiten in seinem GLR-Parser (der eine Diskussion eines anderen mehrdeutigen Falls in der C ++ - Grammatik enthält).
Schließlich: Ich denke, die Frage hat einige Verwirrung über den Unterschied zwischen Mehrdeutigkeit und Nichtdeterminismus. Automaten und Sprachen können deterministisch / nicht deterministisch sein, aber keine Grammatiken. Grammatiken und Sprachen können mehrdeutig / eindeutig sein. Siehe Gibt es inhärent mehrdeutige und deterministische kontextfreie Sprachen? und grammatische Charakterisierung von deterministisch kontextfreien Sprachen und wenn ein Parser kann eine nicht-deterministische Grammatik analysieren, ist der Parser nicht-deterministisch ? . Die obigen Beispiele qualifizieren sich tatsächlich sowohl als mehrdeutige Grammatiken als auch als nicht deterministische Sprachen.