Ich denke, die Frage enthält eine Annahme, die bestenfalls an der Grenze stimmt.
Im wirklichen Leben ist es ziemlich üblich, einfach mit mehrdeutigen Grammatiken zu leben, solange sie nicht (sozusagen) zu mehrdeutig sind.
Wenn Sie sich beispielsweise Grammatiken ansehen, die mit yacc kompiliert wurden (oder ähnlichen, wie Bison oder Byacc), werden Sie feststellen, dass einige Warnungen zu "N-Verschiebungs- / Reduzierungskonflikten" beim Kompilieren ausgegeben werden. Wenn yacc auf einen Verschiebungs- / Reduzierungskonflikt stößt, signalisiert dies eine Mehrdeutigkeit in der Grammatik.
Ein Verschiebungs- / Reduzierungskonflikt ist jedoch normalerweise ein eher geringes Problem. Der Parser-Generator wird den Konflikt zugunsten der "Verschiebung" und nicht der Reduzierung lösen. Die Grammatik ist vollkommen in Ordnung, wenn Sie das möchten (und es scheint in der Praxis vollkommen gut zu funktionieren).
Ein Verschiebungs- / Reduzierungskonflikt tritt normalerweise in einem Fall in dieser allgemeinen Reihenfolge auf (Verwendung von Großbuchstaben für Nicht-Terminals und Kleinbuchstaben für Terminals):
A -> B | c
B -> a | c
Wenn wir auf ein c
treffen, gibt es eine Mehrdeutigkeit: Sollen wir das c
direkt als ein A
analysieren, oder sollten wir es als ein analysieren B
, was wiederum ein ist A
? In einem solchen Fall wählen yacc und solche die einfachere / kürzere Route und analysieren die Route c
direkt als eine A
, anstatt die Route c
-> B
-> zu wählen A
. Dies kann falsch sein, aber wenn ja, bedeutet dies wahrscheinlich, dass Sie einen wirklich einfachen Fehler in Ihrer Grammatik haben und Sie sollten die c
Option überhaupt nicht als Möglichkeit zulassen A
.
Im Gegensatz dazu könnten wir jetzt etwas ähnlicheres haben:
A -> B | C
B -> a | c
C -> b | c
Jetzt, wenn wir auf ein stoßen c
, haben wir einen Konflikt, ob wir das c
als ein B
oder ein behandeln sollen C
. Es ist viel unwahrscheinlicher, dass eine automatische Konfliktlösungsstrategie das wählt, was wir wirklich wollen. Keines von diesen ist eine "Verschiebung" - beide sind "Reduzierungen", so dass dies ein "Reduzieren / Reduzieren von Konflikten" ist (was diejenigen, die an Yacc gewöhnt sind, im Allgemeinen als ein viel größeres Problem als ein Verschieben / Reduzieren von Konflikten anerkennen).
Also, obwohl ich nicht sicher bin, ob ich so weit gehen würde zu sagen, dass jeder Zweideutigkeiten in seiner Grammatik wirklich begrüßt , ist es zumindest in einigen Fällen geringfügig genug, dass sich niemand wirklich sehr darum kümmert. In der Zusammenfassung mögen sie vielleicht die Idee, alle Mehrdeutigkeiten zu beseitigen - aber nicht genug, um es immer tatsächlich zu tun. Beispielsweise kann eine kleine, einfache Grammatik, die eine geringe Mehrdeutigkeit enthält, einer größeren, komplexeren Grammatik vorgezogen werden, die die Mehrdeutigkeit beseitigt (insbesondere, wenn Sie in den praktischen Bereich eintreten, aus der Grammatik tatsächlich einen Parser zu generieren, und feststellen, dass der Parser eindeutig ist) Grammatik erzeugt einen Parser, der nicht auf Ihrem Zielrechner läuft.