2010-05-20 11 views
8

Próbuję utworzyć metajęzyk do pisania kodu znaczników (takiego jak xml i html), który może być bezpośrednio osadzony w kodzie C/C++. Oto prosty przykład napisany w tym języku, ja to nazywam WDI (interfejs Web Development):Jak skutecznie zbudować interpretera (lexer + parser) w C?

/* 
    * Simple wdi/html sample source code 
    */ 
#include <mySite> 

string name = "myName"; 
string toCapital(string str); 

html 
{ 
    head { 
    title { mySiteTitle; } 
    link(rel="stylesheet", href="style.css"); 
    } 
    body(id="default") { 
    // Page content wrapper 
    div(id="wrapper", class="some_class") { 
    h1 { "Hello, " + toCapital(name) + "!"; } 

    // Lists post 
    ul(id="post_list") { 
    for(post in posts) { 
     li { a(href=post.getID()) { post.tilte; } } 
    } 
    } 
    } 
    } 
} 

Zasadniczo jest źródłem C z przyjazny dla użytkownika interfejs dla HTML. Jak widać, tradycyjny styl oparty na znacznikach jest zastępowany stylem C, z blokami ograniczonymi przez nawiasy klamrowe. Potrzebuję zbudować tłumacza, aby przetłumaczyć ten kod na html i później wstawić go do C, aby mógł zostać skompilowany. Część C pozostaje nienaruszona. Wewnątrz źródła wdi nie ma potrzeby używania wydruków, każda instrukcja zwrotu będzie używana do wyprowadzania (w funkcji printf). Wynik programu będzie czysty kod html.

Tak więc, na przykład pozycji 1 tag zostanie przekształcona tak:

h1 { "Hello, " + toCapital(name) + "!"; } 
// would become: 
printf("<h1>Hello, %s!</h1>", toCapital(name)); 

Moim głównym celem jest stworzenie tłumacza do przetłumaczenia WDI źródła html tak:

tag(attributes) {content} =><tag attributes>content</tag>

Po drugie kod html zwrócony przez interpreter musi zostać wstawiony do kodu C za pomocą printfs. Zmienne i funkcje, które występują wewnątrz programu wdi, należy również posortować w celu użycia ich jako parametrów printf (przypadek toCapital (name) w źródle próbki).

Poszukuję wydajnego (chcę utworzyć szybki parser) sposób tworzenia leksykonu i analizatora składni dla wdi. Już wypróbowany flex i żubr, ale nie jestem pewien, czy są to najlepsze narzędzia. Czy są jakieś dobre alternatywy? Jaki jest najlepszy sposób na stworzenie takiego tłumacza? Czy możesz doradzić jakąś krótką literaturę na ten temat?

+5

Imho, flex i bizon to prawdopodobnie najlepsze narzędzia do pracy. – ereOn

+0

Naprawdę nie pytasz o kompilator WDI-> C? Nie brzmi to tak, jakbyś chciał bezpośrednio wykonać kod WDI, ale raczej przekonwertować go na C, a następnie wprowadzić kod C do kompilatora C. –

+0

Zgadza się! WDI powinien zostać przekonwertowany na C. Ale myślę, że implementacja byłaby podobna, dlatego też chciałbym stworzyć tylko interpreter do użytku i testowania html. – Rizo

Odpowiedz

1

Jeśli poważnie myślisz o tym, to co chcesz zrobić, to zmodyfikować istniejący parser C. Opcja Edison Design Group C Front End może być opcją, ale musi ona być , tak naprawdę musi być tylko przednim końcem C (C++).

Inną opcją jest nasza DMS Software Reengineering Toolkit. DMS można uzyskać przy pomocy C Front End, który zawiera pełny parser C sterowany całkowicie z gramatyki.

DMS zapewnia bezpośrednie wsparcie dla budowania dialektów języków, a tym, co chcesz zrobić, jest zbudowanie dialektu języka C, aby mógł on wspierać Twój cel.DMS dostarcza także wiele maszyn do budowania tłumaczy, więc byłoby dość łatwo przetłumaczyć dialekt na prawdziwy kod C i wyemitować go.

3

bizon/Flex lub yacc/lex jest w tradycyjny sposób aby to zrobić. IMHO, nie ma nic lepszego dla danego zadania.

Należy pamiętać, że zadanie nie może być wykonane za pomocą zwykłego języka (np. Regex, prosty skrypt perl itp.), Więc naprawdę potrzebujesz parsera.

Lepiej zrobić to dobrze. Najczęściej parser generowany przez yacc/bison będzie znacznie czyściejszy (i szybszy) niż jakiś ręczny, rekursywny malejący parser.

+0

Jeśli zamierzasz parsować C (lub jego rozszerzenie, tak jak chce OP), przekonasz się, że żubr/yacc/LALR (1) nie radzi sobie z tym bardzo dobrze. Parsery kompilatora C to przeważnie straszne hacki, w których parsująca maszyneria jest splątana z rozpoznawaniem nazw. Więcej szczegółów można znaleźć na stronie http://stackoverflow.com/questions/243383/why-c-cannot-be-parsed-with-a-lr1-parser/1004737#1004737. –

1

Boost spirit może być lepszy niż żubr/elastyczny do takich celów.

+0

Czy kiedykolwiek go używałeś? A co z wydajnością? Czy to jest dobre w porównaniu z flexem i bizonem? Już zacząłem robić to z flexem i żubrem, więc muszę być pewny, że warto przenieść się do ducha bodźca. – Rizo

+0

wydajność jest naprawdę dobra. Czasy kompilacji są jednak powolne. –