Lex - распознавание токенов - PullRequest
2 голосов
/ 16 января 2012

Я пытаюсь выучить Лекса.У меня есть простая программа, в которой я хочу прочитать файл и распознать токены.

Сейчас я получаю некоторые ошибки.Я думаю, что у меня проблемы, потому что в файле более одной строки для распознавания токенов?

Вот файл

fd 3x00
bk
setc 100
int xy3 fd 10 rt 90

. Вот результат, который я пытаюсь достичь:

Keyword: fd
Illegal: 3x00
Keyword: bk
Keyword: setc
Number: 100
Keyword: int

вот моя программа:

%{

/* Comment  */

 #include <stdio.h>
 #include <stdlib.h>

%}
%%
fd                     {printf("Keyword: fd\n");}
[0-9][a-z][0-9]        {printf("Illegal: 3x00\n");}
bk                     {printf("Keyword: bk\n");}
setc[0-9]              {printf("Keyword: setc\n Number: %s\n", yytext);}
int                    {printf("Keyword: int\n");}
xy3                    {printf("ID: xy3\n");}
fd[0-9]                {printf("Keyword: fd\n Number %s\n", yytext);}
rt[0-9]                {printf("Keyword: rt \n Number %s\n", yytext);}
%%

main( argc, argv)
int argc;
char** argv;
{
    if(argc > 1)
    {

        FILE *file;
        file = fopen(argv[1], "r");
        if(!file)
        {
           fprintf(stderr, "Could not open %s \n", argv[1]);
           exit(1);
        }

        yyin = file;

    }

    yylex();

}

вот ошибки, которые я получаю, когда пытаюсь его скомпилировать:

 In function 'yylex':
miniStarLogo.l:11: error: expected expression before '[' token
miniStarLogo.l:11: error: 'a' undeclared (first use in this function)
miniStarLogo.l:11: error: (Each undeclared identifier is reported only once
miniStarLogo.l:11: error: for each function it appears in.)
miniStarLogo.l:11: error: expected ';' before '{' token
miniStarLogo.l:13: error: expected expression before '[' token
miniStarLogo.l:13: error: expected ';' before '{' token

- это ошибка вмои заявления printf?Спасибо

1 Ответ

1 голос
/ 16 января 2012

Когда я скомпилировал копию вашего кода в MacOS X (10.7.2) с flex (2.5.35) и gcc (4.6.1), единственные жалобы, которые я получил от компилятора C, касалисьнепрототипное определение main(), и это потому, что я всегда компилирую с включенным предупреждением и упоминанием yyunput() defined but not used (это не ваша ошибка).

Поскольку вы изучаете C, вам следует толькоиспользуя нотацию:

int main(int argc, char **argv)
{
    ...
}

или эквивалентную.

Я также преобразовал файл miniStarLogo.l в формат DOS (окончания строк CRLF), и оба flex и gccказалось, что все в порядке с результатами - к моему удивлению.Это может быть не так на вашей машине.

Когда я запустил код на ваших тестовых данных, я получил:

Keyword: fd
 Illegal: 3x00
0
Keyword: bk

setc 100
Keyword: int
 ID: xy3
 Keyword: fd
 10 rt 90

Итак, вы не далеко, где вам нужно бытьпо моим расчетам.


В моих командах царит путаница.

Я использовал (хммм, это был GCC 4.2.1, а не 4.6.1), но:

$ flex miniStarLogo.l
$ gcc -Wall -Wextra -O3 -g -o lex.yy lex.yy.c -lfl
miniStarLogo.l:22: warning: return type defaults to ‘int’
miniStarLogo.l: In function ‘main’:
miniStarLogo.l:42: warning: control reaches end of non-void function
miniStarLogo.l: At top level:
lex.yy.c:1114: warning: ‘yyunput’ defined but not used
$ ./lex.yy <<EOF
> fd 3x00
> bk
> setc 100
> int xy3 fd 10 rt 90
> EOF
Keyword: fd
 Illegal: 3x00
0
Keyword: bk

setc 100
Keyword: int
 ID: xy3
 Keyword: fd
 10 rt 90
$

(ОК - я немного обманул: в первый раз я запустил rmk lex.yy LDLIBS=-lfl, где rmk - вариант make, а правила компиляции в каталоге используют показанную командную строку. Но я переделалкомпиляции для получения правильных сообщений об ошибках, точно так же, как указано выше.)

Возможно, вам придется взглянуть на расширение ваших шаблонов, чтобы принимать «одну или несколько» цифр с [0-9]+ вместо просто [0-9].Возможно, вам придется взглянуть на правило, касающееся непревзойденных символов.И лично я прилагаю большие усилия, чтобы избежать пропусков непосредственно перед новыми строками, поэтому вам нужно будет ужесточить форматирование печати в соответствии с моими критериями.Однако запуск программы не имеет смысла.

Кроме того, если вам нужно преобразовать файл из DOS в конец строки Unix, проще всего будет команда dos2unix, если она у вас есть на вашем компьютере.В противном случае используйте:

$ tr -d '\015' < miniStarLogo.l > x
$ od -c x
0000000   %   {  \r  \n  \r  \n   /   *       C   o   m   m   e   n   t
...
0001560  \n   }  \r  \n
0001564
$ mv x miniStarLogo.l
$

Я осторожно добавил возврат каретки, используя vim и :set fileformat=dos;было бы также возможно отменить это с vim и :set fileformat=unix.Это Unix, так что TMTOWTDI (есть больше, чем один способ сделать это - девиз Perl), и я даже не пытаюсь использовать Perl.

...