Analizatory składni LR nie mogą obsługiwać niejednoznacznych reguł gramatycznych, zgodnie z projektem. (Uczynił teorię łatwiejszą w latach 70., kiedy pomysły były opracowywane).
C i C++ zarówno umożliwiają następujące oświadczenie:
x * y ;
Posiada dwie różne analizuje:
- może być deklaracja y, jako wskaźnik do x typ
- może on być mnożnikiem x i y, odrzucając odpowiedź.
Teraz możesz myśleć, że to drugie jest głupie i powinno zostać zignorowane. Większość zgodziłaby się z tobą; jednak istnieją przypadki, w których może on wywoływać efekt uboczny (np. jeśli mnożenie jest przeciążone). ale nie o to chodzi. Chodzi o to, że są dwiema różnymi parami, a zatem program może oznaczać różne rzeczy w zależności od tego, jak przeanalizowano ten , który powinien być.
Kompilator musi zaakceptować odpowiedni pod odpowiednimi warunkami, a przy braku jakichkolwiek innych informacji (np. Znajomość typu x) musi zebrać oba, aby zdecydować później, co robić. Dlatego gramatyka musi na to pozwalać. A to sprawia, że gramatyka jest niejednoznaczna.
Tak więc parsowanie LR nie poradzi sobie z tym. Ponadto wiele innych szeroko dostępnych generatorów analizatorów składni, takich jak Antlr, JavaCC, YACC lub tradycyjne Bizon, a nawet parserów w stylu PEG, nie jest używane w "czysty" sposób.
Istnieje wiele bardziej skomplikowanych przypadkach (analizowania składni szablonu wymaga arbitralnego uprzedzona, natomiast LALR (k) może patrzeć w przyszłość w większości żetonów K), ale tylko trwa tylko jeden kontrprzykład zestrzelić czystego LR (lub inne) parsowania.
większość/parser prawdziwy C C++ obsłużyć ten przykład za pomocą pewnego rodzaju deterministyczny parsera z dodatkowym Hack: oni splatają parsowania z tabeli symbol kolekcji ... tak że przez czas „X” jest napotkanych się parser wie, czy x jest typem, czy nie, i może w ten sposób wybrać między dwoma potencjalnymi analizami. Ale analizator składni , który to robi, nie jest pozbawiony kontekstu, a parsery LR (te czyste itp.) Są (w najlepszym wypadku) wolne od kontekstu.
Można oszukiwać i dodawać semantyczne kontrole czasu na podstawie reguł w do parserów LR, aby dokonać tej ujednoznacznienia. (Ten kod często nie jest prosty). Większość innych typów analizatorów składni ma pewne możliwości dodawania semantycznych sprawdzeń w różnych punktach w analizie, które można wykorzystać do tego.
A jeśli oszukasz wystarczająco, możesz sprawić, by parsery LR działały na C i C++. Faceci GCC robili to przez jakiś czas, ale dali mi do ręcznego kodowania, myślę, że chcieli poprawić diagnostykę błędów.
Istnieje jednak inne podejście, które jest ładne i czyste i parsuje C i C++ w porządku bez tablicy symboli hackery: GLR parsers. Są to pełne parserów bez kontekstu (mających faktycznie nieskończony wcześniejszą stronę).Analizatory składni GLR po prostu akceptują analizy zarówno, jak i , tworząc "drzewo" (właściwie skierowany wykres acykliczny, który jest w większości podobny do drzewa), co oznacza dwuznaczną analizę. Przepustka po analizie składniowej może rozwiązać niejednoznaczności.
Używamy tej techniki w C i C++ przodu kończy się dla naszego DMS Software Reengineering Tookit (od czerwca 2017 je obsługiwać pełny C++ 17 w SM i GNU dialektów). Służyły one do przetwarzania milionów linii dużych systemów C i C++, z kompletnymi, dokładnymi analizami składającymi się na AST z kompletnymi szczegółami kodu źródłowego. (Patrz the AST for C++'s most vexing parse.)
Podobnie jak: musisz zrozumieć rekursję, aby nauczyć się rekursji ;-). –
"Zrozumiesz parsery, kiedy sparujesz to zdanie." –