Definiuję bardzo długi wzór flex, z wieloma lub przypadkami. Zastanawiam się, czy istnieje sposób napisania definicji w kilku wierszach, aby poprawić czytelność kodu. Coś jak
%option noyywrap
1 %{
...
14 %}
15
16 DIGIT [0-9]
17 ID [a-z][a-z0-9]*
18 LOOP_KWD for|while|
19 his|her //THIS IS WHAT I WOULD LIKE
20 SELECT_KWD if|else
21 STRING ".*"
22 COMP_OP <|>|==]
29
30 %%
31
32 {DIGIT}+ {
33 printf("INT_NUM<%s>", yytext);
34 }
35
36 {include} {
37 printf("PREPROCESSOR_INCLUDE");
38 }
39 {LOOP_KWD} {
40 printf("LOOP_KWD<%s>", yytext);
41 }
42 {SELECT_KWD} {
43 printf("SELECT_KWD<%s>", yytext);
44 }
kiedy próbuję to uruchomić, daje to:
flex -o tokenize.c my_first_token.l
my_first_token.l:40: unrecognised rule
make: *** [all] Error 1
Odpowiedzi:
0 dla odpowiedzi № 1Rzeczywistym problemem jest wielowierszowa definicja LOOP_KWD w liniach 18-19, a prostą odpowiedzią jest to, że nie możesz tego zrobić.
Bardziej złożoną odpowiedzią jest każde słowo kluczowepowinien mieć własną regułę. W przeciwnym razie parser może nie działać, więc nie powinieneś nawet próbować. Albo nie przeszkadza rozpoznawanie słów kluczowych w ogóle za pomocą reguł i po prostu użyj tabeli odnośników w regule IDENTIFIER.
0 dla odpowiedzi nr 2
lex
i flex
nie akceptuj linii kontynuacji w definicjach szyku, ale zezwalaj na podział linii w sekcji reguł. Możesz zmienić tę regułę na coś podobnego
for|
while|
his|
her {
printf("LOOP_KWD<%s>", yytext);
}
chociaż uważam, że lepiej jest używać tabeli odnośników, a lexer dotyczy tylko składni. Masz wzór dla {ID}
które można wykorzystać np.
{ID} {
int n;
for (n = 0; table[n] != 0; ++n) {
if (!strcmp(yytext, table[n])) {
printf("keyword<%s>", yytext);
break;
}
}
}
i tabela (oczywiście w sekcji kodu):
const char *table[] = { "for", "while", "his", "her", 0 };
Używanie wzoru {ID}
zamiast wyraźnych słów kluczowych rozwiązuje problem fałszywych dopasowań, np. "to" pasuje do "jego", "naprzód" pasujących do "dla" itp.