Lex - 识别令牌

时间:2012-01-16 05:05:55

标签: c yacc lex

我正在努力学习Lex。我有一个简单的程序,我想在文件中读取并识别令牌。

现在我收到了一些错误。我想我遇到了问题,因为文件中有多行来识别令牌?

这是文件

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 个答案:

答案 0 :(得分:1)

当我使用flex(2.5.35)和gcc(4.6.1)在MacOS X(10.7.2)上编译代码副本时,我从C获得的唯一投诉编译器是关于main()的非原型定义,那是因为我总是在启用该警告的情况下编译并提及yyunput() defined but not used(这不是你的错)。

由于您正在学习C,因此您应该只使用符号:

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

或同等的。

我还将miniStarLogo.l文件转换为DOS格式(CRLF行结尾),flexgcc似乎都没有结果 - 有点令我惊讶。您的机器可能不是这种情况。

当我在测试数据上运行代码时,我得到了:

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,其中rmkmake的变体,目录中的编译规则使用显示的命令行但是我重新编写了这些编译,以便正确地获取错误信息。完全如上所述。)

您可能需要查看扩展模式以接受[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。