第二章 flex输入输出

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;
}
时间: 2024-11-10 07:50:13

第二章 flex输入输出的相关文章

第二章 flex输入输出结构

对于一个词法分析程序,一般读取文件或者终端 一个默认lex程序大致看上去像这样 YY_BUFFER_STATE bp; extern FILE* yyin; ... whatever the program does before the first call to the scanner if(!yyin) yyin = stdin; default input is stdin bp = yy_create_buffer(yyin,YY_BUF_SIZE ); YY_BUF_SIZE def

第二章 flex处理二义性

大多数flex程序有二义性,相同的输入可能被多种模式匹配 flex通过下面2个规则来解决 匹配尽可能长的字符 如果2个模式都可以匹配, 匹配更早出现的那个模式 例子 "+" { return ADD; } "=" { return ASSIGN; } "+=" { return ASSIGNADD; } "if" { return KEYWORDIF; } "else" { return KEYWORDEL

linux程序设计——shell程序设计(第二章)

第二章    shell程序设计 本章介绍以下内容: 什么是shell 基本思路 微妙的语法:变量,条件判断和程序控制 命令列表 函数 命令和命令的执行 here文档 调试 grep命令和正则表达式 find命令 shell执行shell程序,这些程序通常称为脚本,它们是在运行时解释执行的.这使得调试工作比较容易进行,因为可以逐行地执行指令,而且节省了重新编译的时间.然而,这也使得shell不适合用来完成时间紧迫型和处理器忙碌型的任务. UNIX架构非常依赖于代码的高度可重用性,如果你编写了一个

C++ Primer Plus学习:第二章

C++入门第二章:开始学习C++ 进入C++ 首先,以下是一个C++程序: //myfirst.cpp 显示一行文字 #include<iostream> //预处理器编译指令 int main() //函数头 { using namespace std; //编译指令 cout<<"学习C++"; //显示消息 cout<<endl; //开始下一行 cout<<"你不会后悔!"; //更多输出 return 0;

【C Primer Plus笔记】第二章 C语言概述

第二章主要通过分析一个简单的实例来介绍C语言. 一.程序细节内容 1 #include <stdio.h> 此语句的作用相当于在文件中该行所在的位置键入了文件stdio.h的完整内容.实际上是一种剪切和粘贴操作. #include语句是C预处理器指令(preprocessor directive)的一个例子.stdio.h文件作为所有C编译包的一部分提供,它包含了有关输入和输出函数的信息供编译器使用.这个名字代表标准输入输出头文件. 最重要的是头文件中包含了建立最终可执行程序时编译器需要用到的

《Linux程序设计 第四版》之第二章的最后练习题

这篇文章是<Linux程序设计 第四版>中的第二章的最后练习题(2.8综合应用), 题目是编写一个CD数据库应用程序, 首先:用两个文件来保存存储的数据,一个是title_file.cdb,一个是column_file.cdb! title_file.cdb里面保存的是唱片的基本信息:拥有如下四个字段: CD的目录编号,标题,唱片类型,作曲家或艺术家: column_file.cdb里面保存的是唱片的详细信息即唱片包含的歌曲信息:拥有如下三个字段: CD的目录编号,曲目编号,歌曲名 其次: 有

openwrt教程 第二章 下载openwrt源码

2.1 开发环境 我们工作室(F403科技创意室:http://f403tech.taobao.com/)写的该教程,所使用的环境为: VMware Workstation:VMware 8 Ubuntu:Ubuntu12.04 具体环境搭建过程,可以向客服索要用户手册!上面有非常详细的过程! 2.2 准备工作 再下载.配置.编译openwrt系统之前,我们需要做些准备工作,安装一些必须的工具.库. (1) 安装SVN工具 安装SVN工具,用于下载openwrt源码: $ sudo apt-ge

Android开发艺术探索——第二章:IPC机制(中)

Android开发艺术探索--第二章:IPC机制(中) 好的,我们继续来了解IPC机制,在上篇我们可能就是把理论的知识写完了,然后现在基本上是可以实战了. 一.Android中的IPC方式 本节我们开始详细的分析各中跨进程的方式,具体方式有很多,比如可以通过在Intent中附加extras来传递消息,或者通过共享文件的方式来共享数据,还可以采用Binder方式来跨进程通信,另外,ContentProvider天生就是支持扩进程访问的,所以通过Socket也可以实现IPC,上述的各种方法都能实现I

汇编第二章知识总结

今天刚学完第二章,以下是一些学习到的内容. 首先是CPU的概述 1.一个典型CPU由运算器.控制器和寄存器等器件组成. 2.内部总线实现CPU内部各个部件之间的联系. 3.外部总线实现CPU和主板上其他器件的联系. 通用寄存器 1.8086CPU所用的寄存器都是16位的,可以存放2个字节.AX,BX,CX,DX这四个寄存器都唱用来存放一般性数据,被称为通用寄存器 2.为了保证与上一代8位CPU兼容,8086CPU的AX.BX.CX.DX可分为两个可独立使用的8位寄存器. AX可分为AH和AL B