2010-01-30 10 views
22

Późniejsze dodawanie pliku źródłowego do istniejącego narzędzia, które wygenerowało pliki wyjściowe ze złożonych argumentów wiersza poleceń.Czy istnieje lepsze (bardziej nowoczesne) narzędzie niż lex/flex do generowania tokenizera dla C++?

Argumenty linii poleceń stały się tak złożone, że zaczęliśmy zezwalać na dostarczanie ich jako pliku, który został przeanalizowany tak, jakby był bardzo dużym wierszem komend, ale składnia była nadal niezręczna. Dodałem więc możliwość analizowania pliku źródłowego za pomocą rozsądniejszej składni.

Użyłem Flex 2.5.4 dla systemu Windows do generowania tokenizera dla tego niestandardowego formatu pliku źródłowego, i zadziałało. Ale nienawidziłem tego kodu. zmienne globalne, konwencja nazw wierd i wygenerowany kod C++ był okropny. Istniejący backend generowania kodu został przyklejony do wyjścia flex - nie używam yacc ani bison.

Zaraz przyjdę do tego kodu i chciałbym użyć lepszego/nowocześniejszego narzędzia. Czy ktoś o tym wie?

  • Działa w systemie Windows wiersz polecenia (integracja Visual Studio jest ok, ale używam tworzyć pliki budować)
  • Generuje właściwego zamknięty C++ tokenizera. (Bez zmiennych globalnych)
  • Używa wyrażeń regularnych do opisywania reguł tokenizacji (zgodnych ze składnią lex a plus)
  • Nie zmusza mnie do użycia c-runtime (lub fałszywego) do odczytu pliku. (Analizować z pamięci)
  • ostrzega mnie, kiedy moje zasady zmusić tokenizera prezydentom (lub rozwiązuje to automatycznie)
  • Daje mi pełną kontrolę nad nazwami zmiennych i metod (tak mogę odpowiadać na moje istniejące konwencją nazewnictwa)
  • pozwala mi połączyć wiele parserów w jeden exe bez kolizji nazw
  • może generować Unicode (UCS-2 16bit) parser jeśli chcę go
  • nie jest integralną tokenizer + parser-generator (Chcę lex zamiennik, a nie zamiennik lex + yacc)

Prawdopodobnie mógłbym żyć z narzędziem, które właśnie wygenerowało tokeny, gdyby to była jedyna dostępna opcja.

+3

Boost.Spirit, Boost.Proto i Boost.Xpressive nie są opcjami? –

+0

@Konrad: Mogą być, nie znam ich. coś, co generuje szablony zamiast klasy C++ byłoby do zaakceptowania. –

Odpowiedz

11

Ragel: http://www.complang.org/ragel/ Pasuje do większości wymagań.

  • To działa na Windows
  • Nie deklarować zmienne, dzięki czemu można umieścić je wewnątrz klasy lub wewnątrz funkcji, jak chcesz.
  • Ma ładne narzędzia do analizy wyrażeń regularnych, aby zobaczyć, kiedy będą się wycofywać. (Nie bardzo o tym wiem, ponieważ nigdy nie używam składni w Ragel, która tworzy parsera wstecznego).
  • Zmiennych nazw nie można zmienić.
  • Nazwy tabel są poprzedzane nazwą komputera i są zadeklarowane jako "const static", więc można umieścić więcej niż jeden w tym samym pliku i mieć więcej niż jeden o tej samej nazwie w jednym programie (o ile są w różnych plikach).
  • Możesz zadeklarować zmienne jako dowolny typ liczby całkowitej, w tym UChar (lub dowolny preferowany typ UTF-16). Nie obsługuje ona jednak automatycznie zastępczych par. Nie ma też specjalnych klas znaków dla Unicode (chyba).
  • Wykonuje tylko wyrażeń regularnych ... nie ma funkcji bison/yacc.

Kod, który generuje, bardzo rzadko koliduje z programem. Kod jest również niesamowicie szybki, a składnia Ragel jest bardziej elastyczna i czytelna niż cokolwiek, co kiedykolwiek widziałem. To solidny kawałek oprogramowania. Może generować parser sterowany tabelą lub parser sterowany goto.

+0

+1 to wygląda obiecująco. –

+0

Używam tego sam i zdecydowanie się zgadzam. Jest tam również Kelbt, autorstwa tego samego autora, do parsowania - nie jest to wersja release i ma swoje dziwactwa (w szczególności nie łączy się ani nie ujednoznacznia), ale i tak go używam i jedyne awarie " ve było w czasie budowania i wynikało z błędów kodu (odniesienie do nieistniejącego tokena w akcji parsowania). – Steve314

+0

Użyłem również treecc do definicji węzła AST z operacjami wielokrotnego wysyłania, w połączeniu z Kelbt i Ragel. W dzisiejszych czasach posiadam własne zamienniki z kilkoma dodatkowymi sztuczkami (np. Zajęcia z iteratora ruchu AST) - może nawet wypuszczę je, pewnego dnia ... – Steve314

5

Są dwa narzędzia, które przychodzą na myśl, chociaż trzeba się samemu przekonać, które z nich będą odpowiednie: Antlr i GoldParser. W obu narzędziach dostępne są powiązania językowe, w których można je podłączyć do środowiska wykonawczego C++.

+0

Mówiąc o tym, kiedy poszedłem na miejsce wyszukiwania, istnieje najwyraźniej obiektowa wersja flex/bison z użyciem biblioteki boost - sprawdź to http://dudka.cz/vyp08 – t0mm13b

+0

Już wiedziałem o porożu i znalazłem go nieodpowiedni. Jestem generatorem analizatora składni i wymaga on instalacji środowiska uruchomieniowego java, co z mojego doświadczenia jest niestabilne i denerwujące w systemie Windows. GoldParser wygląda obiecująco - dziękuję. –

+0

@ tommeib75: dudka.cz dobre znalezisko. może ma lepszy sposób na zmierzenie wyjścia elastycznego w czysty kod. –

5

Flex ma również opcję wyjścia C++.
Wynik jest zbiorem klas, które wykonują tę analizę.

Wystarczy dodać następujące głowy z was lex pliku:

%option C++ 
%option yyclass="Lexer" 

Następnie w ty źródła to:

std::fstream file("config"); 
Lexer   lexer(&file) 
while(int token = lexer.yylex()) 
{ 
} 
+0

Tak, próbowałem tego, to jest nawet gorsze niż kod C IMO, ale rozwiązuje on błędy golbal i wiele problemów z instancjami. –

+1

Ponieważ nie zachowujesz wyprodukowanego kodu, jego estetyczne właściwości są nieistotne. Twoim plikiem źródłowym jest plik lex. Dopóki kod działa, nie zanieczyszcza globalnej przestrzeni nazw, szczegóły implementacji są nieistotne.Uwaga1: Nie buduj plików źródłowych tylko kompiluj pliki obiektów i nagłówki (np. Usuń źródło natychmiast). Uzależnij obiekt od pliku lex, a nie od pliku źródłowego. Uwaga: są messey, ponieważ sprawiają, że jest skuteczny. –

6

Boost.Spirit.Qi (parsera-tokenizera) lub zwiększyć. Spirit.Lex (tylko tokenizer). Ja absolutnie kocham Qi, a Lex też nie jest zły, ale mam tendencję do brania Qi do moich potrzeb parsowania ...

Jedyną istotną wadą Qi jest wydłużenie czasu kompilacji, a także przebiega nieco wolniej niż odręczny kod parsujący. Zwykle jest znacznie szybszy niż parsowanie za pomocą regex.

http://www.boost.org/doc/libs/1_41_0/libs/spirit/doc/html/index.html

+0

Dzięki, przyjrzę się Boost.Spirit.Lex –

2

boost.spirit i Yard parser przyjść do mojego umysłu. Zauważ, że podejście mające generatory lexerów zostało nieco zastąpione wewnętrznym DSL C++ (język specyficzny dla domeny) w celu określenia tokenów. Po prostu dlatego, że jest częścią kodu bez korzystania z zewnętrznego narzędzia, po prostu przestrzegając szeregu reguł, aby określić gramatykę.

Powiązane problemy