我是flex的新手,我在编程方面的经验还很少。我需要使用flex创建一个扫描器,该扫描器最终将输出令牌流。目前,我只需要启动并运行绝对的基础知识。我希望编译后的输出文件“ a.exe”能够从单个文件中的文本而不是用户输入中运行。输出也应该是文件。作业要求程序能够像在cmd / PS窗口中那样运行: 。\ a.exe inputfile.txt outputfile.txt 输入和输出文件是按此顺序添加的任何文件名。 就目前情况而言,我的程序创建了我指定的输出文件,但未写入任何内容。尝试阅读Flex手册时,我感到非常困惑,因为我对计算机科学总体上还是很陌生。 目前,我只想获取一个可执行文件,该文件将遵循rules部分并正确输出。这就是说,我一般只是在计算输入文件中的字符,然后尝试将它们显示到输出文件中。我还试图帮助班上的其他人有个开始的地方(因为在这一事件中没有一个人被正式授课过),所以我花一些时间尝试以通用方式(带有安装和使用说明)创建该文件,以便我可以给他们一个地方来开始实际制作扫描仪的工作。
我从http://gnuwin32.sourceforge.net/packages.html安装了Flex 2.5.4a。安装后,我编辑了路径以包含bin文件。
我使用命令“ flex tokenout.l”和“ gcc lex.yy.c”构建文件,然后生成一个a.exe文件。在创建输出文件后,该文件似乎一点用都没有。
代码:
int num_lines = 0;
int num_chars = 0;
FILE *yyin;
FILE *yyout;
%%
\n ++num_lines; ++num_chars;
. ++num_chars;
%%
int yywrap(void) {
return 0;
}
int main(int argc, char *argv[])
{
yyin = fopen(argv[1],"r");
yyout = fopen(argv[2],"w");
yyparse();
yylex();
fprintf(yyout,"# of lines = %d, # of chars = %d\n", num_lines, num_chars);
fclose(yyin);
fclose(yyout);
return 0;
}
结果应为指定为第二个参数的文件的“行数=实际行数,字符数=实际字符数”行。
当前已创建第二个自变量指定的文件,但仍为空白。
答案 0 :(得分:1)
Lex(flex)在到达其输入流的末尾(在yywrap
中时调用(或更准确地说,生成调用yyin
的代码)。此功能的作用是:
yyin
重新打开到下一个文件,则返回0。或者,如the manual所述:
扫描仪从YY_INPUT接收到文件结尾指示后,便会检查“
yywrap()
”功能。如果“yywrap()
”返回false(零),则认为函数已经执行并设置yyin
指向另一个输入文件,然后继续扫描。如果返回true(非零),则扫描程序终止,并向其调用方返回0。请注意,无论哪种情况,启动条件均保持不变;它不会恢复为INITIAL
。如果您不提供自己的'
yywrap()
'版本,则必须使用'%option noyywrap
'(在这种情况下,扫描仪的行为就像'yywrap()
'返回了1 ),否则您必须链接“-lfl
”以获得该例程的默认版本,该版本始终返回1。
(现代flex具有<<EOF>>
规则,通常这是处理堆叠输入文件的更好方法,因为文件之间的转换几乎总是会强制标记边界。)
答案 1 :(得分:1)
yyin = fopen(argv[1],"r");
yyout = fopen(argv[2],"w");
yyparse();
yylex();
目前,我的程序创建了我指定的输出文件,但是没有写入任何内容。
您很困惑,因为您不知道程序在做什么,也不知道程序在做什么,因为它没有告诉您。您需要的是反馈。特别是,您需要检查错误。
例如,如果第一个打开(3)失败怎么办?如果 yyparse 失败或不返回怎么办? (不会。)检查错误,并让程序告诉您正在发生的事情。
#include <err.h>
if( argc < 3 ) {
errx(EXIT_FAILURE, "syntax: foo in out");
}
if( (yyin = fopen(argv[1],"r")) == NULL ) {
err(EXIT_FAILURE, "could not read '%s'", argv[1]);
}
if (yyout = fopen(argv[2],"w")) == NULL ) {
err(EXIT_FAILURE, "could not write '%s'", argv[2]);
}
printf("starting yyparse\n");
if( 0 != yyparse() ) {
errx(EXIT_FAILURE, "parse error");
}
printf("starting yylex\n");
if( 0 != yylex() ) {
errx(EXIT_FAILURE, "lex error");
}
以上内容可确保使用足够的参数启动程序,确保两个文件均成功打开,并检查错误分析和词法检查。不过,这只是一个例子。正如John Bollinger advised一样,您不需要yyparse,因为您没有使用野牛,并且yyout仅控制flex ECHO语句使用的文件。您可以使用自己的全局FILE *
句柄,并在flex操作中对其使用 fprintf (3)。
我想您会发现,您永远不会在屏幕上看到“开始yylex”,因为yyparse永远不会返回,因为-如果它是在某个地方生成的,它不会返回,因为它正在调用 yylex < / strong>,它从不返回任何内容。
我将删除这些行,并使用以下命令设置flex调试
yy_flex_debug = 1;
在调用yylex之前。我认为您会发现它更有意义。
答案 2 :(得分:0)
您似乎是从改编an example program from the Flex manual开始的。很好,但是也许您的第一步应该是使确切的示例程序正常工作。之后,一次执行一次。例如,下一步可能是使它使用第一个参数作为输入文件的名称(并且没有其他更改)。
关于您介绍的部分程序,我看到了两个语义问题:
当将flex与bison(或yacc)一起使用时,调用yyparse()
的是生成的解析器(通过yylex()
访问),通常它将重复执行直到输入为累。在这种情况下,主程序直接调用lexer是没有用的。
yyout
是flex将ECHO
语句的输出定向到的文件,仅此而已。它对您不是特别有用,我暂时将其忽略。