我正在努力学习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语句中的错误? 谢谢
答案 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行结尾),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。