Biorę udział w kursie budowy kompilatorów, a moje obecne zadanie polega na napisaniu lexera dla języka, który implementujemy. Nie mogę wymyślić, jak spełnić wymóg, aby lexer rozpoznawał połączone żetony. Oznacza to, że żetony nie są oddzielone białymi znakami. Np .: ciąg 39if
ma być rozpoznawany jako numer 39
i słowo kluczowe if
. Jednocześnie lexer musi również exit(1)
, gdy napotka nieprawidłowe dane wejściowe.Jak sprawić, aby lex/flex rozpoznawały tokeny nie oddzielone białymi znakami?
Uproszczona wersja kodu mam:
%{
#include <stdio.h>
%}
%option main warn debug
%%
if |
then |
else printf("keyword: %s\n", yytext);
[[:digit:]]+ printf("number: %s\n", yytext);
[[:alpha:]][[:alnum:]]* printf("identifier: %s\n", yytext);
[[:space:]]+ // skip whitespace
[[:^space:]]+ { printf("ERROR: %s\n", yytext); exit(1); }
%%
Gdy ten (lub moją pełną wersję) i przekazać go wejście 39if
reguła błąd jest dopasowany, a wyjście jest ERROR: 39if
, gdy Chciałbym go mieć:
number: 39
keyword: if
(czyli tyle samo, jakbym wszedł 39 if
jako wejście.)
Going by the manual, Mam przeczucie, że przyczyną jest, że reguła błędu pasuje do dłuższych możliwych danych wejściowych niż liczba i reguły słów kluczowych, a Flex woli to. Powiedział, że nie mam pojęcia, jak rozwiązać tę sytuację. Wydaje się niewykonalne, aby napisać wyraźne wyrażenie regularne, które odrzuci wszystkie dane wejściowe bez błędów i nie wiem, jak inaczej napisać regułę "catch-all" ze względu na obsługę błędów leksykonu.
UPDATE: Przypuszczam, że po prostu sprawiają, że catch-all reguła być . { exit(1); }
ale chciałbym trochę ładniejszy niż wyjście debugowania „I got mylić w wierszu 1”.
a) Czy uruchomiłeś uproszczoną wersję? b) co to jest źle? –
@IraBaxter Przepraszam, wydaje mi się, że zapomniałem być jednoznaczny o moim przypadku testowym, gdy zagubiłem się w spekulacjach w ostatnim paragrafie. Odpowiedzi są ** a) ** tak; oraz ** b) ** zgłasza błąd lexera zamiast dwóch tokenów. (Też dodałem je do pytania.) – millimoose
Ah.OK, tak, twoja reguła "^ space" będzie jadła każdą sekwencję nie-przestrzeni, a więc konsumuje "39if". Sekret: unikaj reguł, których wyrażenia nakładają się, chyba że dłuższa zasada przychodzi bezpiecznie pierwsza. W twoim przypadku użyłbym (nie jestem lex-pert) czegoś do zastąpienia:^spacja: to nie była cyfra, ani litera, ani spacja. ... –