flex程序默认总是从标准输入读取, 实际上,词法分析程序都从文件读取输入

flex总是通过名为yyin的文件句柄读取输入, 下面的例子,我们修改单词计数程序,使得它能从文件读取输入

/* even more like Unix wc */
%option noyywrap
%{
int chars = 0;
int words = 0;
int lines = 0;
%}
%%
[a-zA-Z]+ { words++; chars += strlen(yytext); }
\n { chars++; lines++; }
. { chars++; }
%%
main(argc, argv)
int argc;
char **argv;
{
  if(argc > 1) {
    if(!(yyin = fopen(argv[1], "r"))) {
      perror(argv[1]);
      return (1);
    }
  }
  yylex();
  printf("%8d%8d%8d\n", lines, words, chars);
}

 程序中,如果在命令行中提供的文件参数, 那么程序会打开它,修改yyin

 

yywrap

-lfl库,提供了默认的main主程序和早期lex遗留至今的鸡肋-yywrap

yywarp作用

单lex读取到文件末尾时,会调用yywrap(), 目的是,当有另外一个输入文件时,yywrap可以调整yyin的值并且返回0来重新开始词法分析。如果是真正的文件末尾,那么就返回1来完成分析。

 

flex默认main程序

int main()
{
while (yylex() != 0) ;
return 0;
}

现在大多flex程序使用“%option noyywrap” 来禁用yywrap,然后写出自己的主程序,所以它们不需要-lfl库

 

读取多个文件,yyrestart(fp); 如果yylex, yyparse()出现错误, 调用yyrestart()重置调整yyin,重新开始yylex(), 所以开始lex之前,都要调用yyrestart()

main(argc, argv)
int argc;
char **argv;
{
  int i;
  if(argc < 2) { /* just read stdin */
    yylex();
    printf("%8d%8d%8d\n", lines, words, chars);
    return 0;
  }
  for(i = 1; i < argc; i++) {     FILE *f = fopen(argv[i], "r");     if(!f) {       perror(argv[i]);       return (1);     }
    yyrestart(f);     yylex();     fclose(f);     printf("%8d%8d%8d %s\n", lines, words, chars, argv[i]);     totchars += chars; chars = 0;     totwords += words; words = 0;     totlines += lines; lines = 0;   }
  if(argc > 1) /* print total if more than one file */   printf("%8d%8d%8d total\n", totlines, totwords, totchars);   return 0; }