2013-02-06 28 views
7

W instrukcji LLVM tutorials podano instrukcje jak pisać prosty kompilator JIT. Niestety, lekser i parser w tym samouczku są pisane ręcznie. Myślałem, że takie rozwiązanie jest dobre do celów edukacyjnych, ale nie nadaje się do pisania skomplikowanych, gotowych do użycia kompilatorów. Wygląda na to, że GCC i kilka innych "dużych kompilatorów" jest napisanych odręcznie. Ale myślę, że wszystkie te generatory parserów dają duży impuls przy pisaniu własnego kompilatora (szczególnie gdy robisz to sam, bez zespołu ludzi).LLVM JIT Pisanie parsera za pomocą Bison/Antlr/Packrat/Elkhound/

Czy można użyć dowolnego istniejącego generatora parsera, takiego jak Bison/Antlr/Packrat/Elkhound itp., Razem z LLVM, aby utworzyć kompilator JIT? Chcę móc "zasilać" analizator składni w sposób ciągły (nie raz na początku) za pomocą wyrażeń i kompilować je w czasie wykonywania.

Dodatek Znalazłem wiele pytań na temat "najlepszego, nowoczesnego" generatora analizatora składni (takiego jak ten: https://stackoverflow.com/questions/428892/what-parser-generator-do-you-recommend). Jeśli możliwe jest użycie tych narzędzi do stworzenia kompilatora JL LMM, byłbym wdzięczny za wszelkie dodatkowe wskazówki i rekomendacje, które narzędzie byłoby najlepsze pod względem wydajności i elastyczności w tym konkretnym przypadku.

+0

"Takie rozwiązanie jest dobre do celów edukacyjnych, ale nie nadaje się do pisania złożonych, gotowych do kompilacji kompilatorów" - Hm. Zawsze myślałem, że GCC to skomplikowany i gotowy do użycia kompilator. Cokolwiek ... –

+0

GCC używał bizona na początku, ale masz rację - poprawiam to na moje pytanie. Ale tak naprawdę, chciałbym użyć generatora, aby uprościć to zadanie, jeśli jest to możliwe. –

+5

Jeśli cokolwiek, chciałbym powiedzieć, że jest odwrotnie: yacc, Bison i inni, nadają się do celów edukacyjnych i takich, ale dla poważnych prac produkcyjnych, ręczny parser może być jedynym sposobem na spełnienie wymagań. –

Odpowiedz

9

Istnieje wiele zalet korzystania z generatora analizatora składni, takiego jak bison lub antlr, szczególnie podczas opracowywania języka. Niewątpliwie skończysz wprowadzanie zmian w gramatyce, a będziesz chciał zakończyć dokumentacją końcowej gramatyki. Narzędzia, które automatycznie generują gramatykę z dokumentacji, są naprawdę użyteczne. Mogą także pomóc ci w uzyskaniu pewności, że gramatyka języka jest (a) tym, czym myślisz, że jest i (b) nie jest niejednoznaczna.

Jeśli twój język (w przeciwieństwie do języka C++) jest w rzeczywistości LALR (1), a nawet lepszy, LL (1), i używasz narzędzi LLVM do budowania AST i IR, to jest mało prawdopodobne, że będziesz musiał zrobić znacznie więcej niż zapisz gramatykę i zapewnij kilka prostych działań, aby zbudować AST. To pozwoli ci na chwilę.

Powodem, dla którego ludzie ostatecznie decydują się na tworzenie własnych analizatorów, innych niż "prawdziwi programiści nie używają generatorów parsera", jest to, że nie jest łatwo zapewnić dobrą diagnostykę błędów składniowych, szczególnie w przypadku LR (1) parsowanie. Jeśli jest to jeden z twoich celów, powinieneś postarać się, aby twoja gramatyka LL (k) była parsowana (nadal nie jest łatwo zapewnić dobrą diagnostykę za pomocą LL (k), ale wydaje się, że jest trochę łatwiejsza) i użyć LL (k) ramy takie jak Antlr.

Istnieje inna strategia, która polega na tym, że najpierw należy przeanalizować tekst programu w najprostszy możliwy sposób, używając parsera LALR (1), który jest bardziej elastyczny niż LL (1), nawet bez prób zapewnienia diagnostyki. Jeśli analiza nie powiedzie się, możesz ją ponownie przeanalizować za pomocą wolniejszego, a nawet wstecznego parsera, który nie wie, jak generować wartości AST, ale śledzi lokalizację źródłową i próbuje naprawić błędy składniowe. Odzyskiwanie z eroz składni bez unieważniania AST jest jeszcze trudniejsze niż po prostu kontynuowanie analizowania, więc jest wiele do powiedzenia na nie próbowanie. Ponadto śledzenie lokalizacji źródłowej jest bardzo powolne i nie jest zbyt użyteczne, jeśli nie musisz tworzyć diagnostyki (chyba że potrzebujesz jej do dodawania adnotacji do debugowania), więc możesz przyspieszyć analizę parsera, nie przejmując się śledzenie lokalizacji.

Osobiście jestem stronniczy wobec parsowania pakietów, ponieważ nie jest jasne, jaki jest rzeczywisty język analizowany przez PEG. Inni ludzie nie przejmują się tak bardzo i YMMV.

+1

Dlaczego "nie jest jasne", jaki jest rzeczywisty język? PEG jest dobrze zdefiniowany, nawet ze wszystkimi fajnymi hackami, które pozwala packrat (parsowanie na wysokim poziomie i takie). –

+1

@ SK-logic: dobrze zdefiniowane nie jest takie samo jak jasne. Ręcznie napisany parser napisany w C++ jest dobrze zdefiniowany. Maszyna Turinga jest dobrze zdefiniowana. Tak, PEG jest dobrze zdefiniowany. Ale dla nich wszystkich jedynym sposobem sprawdzenia, czy dany ciąg jest w języku, jest wykonanie kodu. (Z tych trzech alternatyw, PEG jest najmniej szkodliwy, ale nadal preferuję gramatykę bez kontekstu formalnego, jednak jak już wspomniałem, inni ludzie, tacy jak PEG, i wszystko, co pracuje dla ciebie, jest ze mną w porządku.) – rici

+0

Z mojego praktycznego doświadczenia , PEG to najbardziej czytelne i łatwe do odczytania gramatyki. Mogę przetłumaczyć specyfikację języka bezpośrednio na PEG z bardzo niewielkimi modyfikacjami. Oczywiście można to zaciemnić, ale jeszcze nie widziałem tak naprawdę zła gramatyki. Podczas gdy istnieje wiele nieczytelnych poza wszelką nadzieję gramatyk Yacc. –