Myślę, że pytanie zawiera założenie, które w najlepszym razie jest tylko poprawne na granicy.
W prawdziwym życiu dość powszechne jest po prostu życie z dwuznacznymi gramatykami, o ile nie są one (że tak powiem) zbyt dwuznaczne.
Na przykład, jeśli spojrzysz na gramatyki skompilowane za pomocą yacc (lub podobnych, takich jak bizon lub byacc), zauważysz, że sporo z nich generuje ostrzeżenia o „konfliktach przesunięcia / redukcji N” podczas ich kompilacji. Kiedy yacc napotyka konflikt przesunięcia / zmniejszenia, oznacza to dwuznaczność w gramatyce.
Konflikt przesunięcia / ograniczenia jest jednak zwykle dość niewielkim problemem. Generator analizatora składni rozwiąże konflikt na korzyść „zmiany” zamiast redukcji. Gramatyka jest w porządku, jeśli tego właśnie chcesz (i wydaje się, że sprawdza się doskonale w praktyce).
Konflikt przesunięcia / zmniejszenia zwykle pojawia się w przypadku na tej ogólnej kolejności (użycie limitów dla terminali innych niż terminale i małych liter dla terminali):
A -> B | c
B -> a | c
Kiedy napotykamy a c
, pojawia się dwuznaczność: czy powinniśmy parsować c
bezpośrednio jako A
, czy też powinniśmy parsować jako jako B
, co z kolei jest A
? W takim przypadku yacc i takie wybiorą prostszą / krótszą trasę i parsują c
bezpośrednio jako A
, zamiast iść trasą c
-> B
-> A
. Może to być złe, ale jeśli tak, to prawdopodobnie oznacza to, że masz naprawdę prosty błąd w gramatyce i nie powinieneś w ogóle dopuszczać tej c
opcji A
.
Teraz natomiast możemy mieć coś takiego:
A -> B | C
B -> a | c
C -> b | c
Teraz, gdy napotykamy jakiś c
konflikt między tym, czy traktować go c
jako B
a C
. Istnieje znacznie mniejsze prawdopodobieństwo, że strategia automatycznego rozwiązywania konfliktów wybierze to, czego naprawdę chcemy. Żadna z nich nie jest „zmianą” - obie są „redukcjami”, więc jest to „redukcja / redukcja konfliktu” (co osoby przyzwyczajone do yacc i takie na ogół uznają za znacznie większy problem niż konflikt zmiany / redukcji).
Tak więc, chociaż nie jestem pewien, czy posunę się tak daleko, aby powiedzieć, że ktoś naprawdę przyjmuje dwuznaczność w swojej gramatyce, przynajmniej w niektórych przypadkach jest na tyle niewielki, że tak naprawdę nikogo to nie obchodzi. W skrócie mogą spodobać im się pomysł usunięcia wszelkiej dwuznaczności - ale nie na tyle, by zawsze to robić. Na przykład, mała, prosta gramatyka, która zawiera niewielką dwuznaczność, może być lepsza niż większa, bardziej złożona gramatyka, która eliminuje niejasności (szczególnie gdy wchodzisz do praktycznej dziedziny faktycznego generowania parsera z gramatyki i stwierdzenia, że jest to jednoznaczne gramatyka tworzy parser, który nie będzie działał na twoim komputerze docelowym).