Flex如何处理二义性模式:

1、词法分析器匹配输入时匹配尽可能多的字符串

2、如果两个模式都可以匹配的话,匹配在程序中更早出现的模式

上下文相关的记号

flex提供起始状态(start state)的概念,可以动态地开启和关闭针对特定模式的识别,对于处理上述上下文相关的情况比较有用。

Flex词法分析器中的文件IO操作

除非另行制定,否则flex词法分析器总是读取标准输入。

词法分析器总是通过名为yyin的文件句柄读取输入。

[root@typhoeus79 flex2]# more fb2-1.l
%option noyywrap %{
#include <string.h>
int chars = 0;
int lines = 0;
int words = 0;
%}
%%
[a-zA-Z]+ { words++; chars += strlen(yytext); }
\n { lines++; chars++; }
[ \t] {}
. { chars++; } %% int main(int argc, char**argv)
{
if(argc>1)
{
yyin=fopen(argv[1],"r"); if(yyin == NULL)
{
perror(argv[1]);
return 1;
}
} yylex(); printf("chars=%d,words=%d,lines=%d\n",chars,words,lines); return 0;
} 对应的Makefile:
[root@typhoeus79 flex2]# more Makefile
fb2-1:lex.yy.o
gcc -o fb2-1 lex.yy.o -lfl lex.yy.o:fb2-1.l
flex fb2-1.l
gcc -Wall -c -g lex.yy.c clean:
rm -rf lex.yy.* fb2-1

读取多个文件

flex提供yyrestart(f)例程,它使词法分析器读取标准输入输出文件f。

%option noyywrap
%{
#include <string.h>
int totchars = 0;
int totlines = 0;
int totwords = 0; int chars = 0;
int lines = 0;
int words = 0; %}
%% [a-zA-Z]+ { chars += strlen(yytext); words++; }
[ \t] { }
\n { lines++; }
. { chars++; } %%
int main(int argc, char ** argv)
{
if(argc<2)
{
yylex();
printf("chars=%d,words=%d,lines=%d\n",chars,words,lines);
return 0;
} int i;
for(i=1; i<argc; i++)
{
FILE* f = fopen(argv[i],"r"); if(f == NULL)
{
perror(argv[i]);
return 1;
} yyrestart(f); yylex(); totchars += chars;
totlines += lines;
totwords += words; } printf("totchars=%d,totwords=%d,totlines=%d\n",totchars,totwords,totlines); return 0;
}

这个例子打开每个文件,使用yyrestart()把打开的文件作为词法分析器的输入,然后调用yylex()进行词法分析。

Flex词法分析器的IO结构

flex提供三层输入系统

从文件读取和从终端读取存在差异——预读机制

1、从文件读取,可以通过大段的读操作来提高工作效率

2、从终端读取,用户可能一次只输入一行,并且期望每行

flex词法分析器会检查当前其输入是否来自终端并决定使用哪一种读取方式。

flex词法分析器使用YY_BUFFER_STATE的数据结构处理输入,包含一个字符串缓冲区以及一些变量和标记。

可以指向所读取的文件的FILE*,也可以创建一个与文件无关的YY_BUFFER_STATE来分析已经在内存中的字符串。

默认的flex词法分析器的输入行为如下:

YY_BUFFER_STATE  bp;
extern FILE* yyin; ......任何第一次调用词法分析器之前所需要做的事情 if(!yyin) yyin = stdin; 默认输入设备是stdin bp = yy_create_buffer(yyin, YY_BUF_SIZE); // YY_BUF_SIZE由flex定义,大小通常为16K yy_switch_to_buffer()
yylex();或者yyparse()或者其他对词法分析器的调用

  

1、如果yyin没有设置,就把stdin设置给它

2、使用yy_create_buffer创建一个读取yyin的新缓冲区

3、使用yy_switch_to_buffer来让词法分析器从缓冲区读入,接着开始分析

4、当需要读取多个文件时,每打开一个文件就调用yyrestart(fp),把词法分析器的输入切换到标准输入输出文件fp

其他函数也可以用来创建分析区,包括yy_scan_string(“string”)——分析以空字符串结尾的字符串

和yy_scan_buffer(char *base,size)分析长度确定的数据流

出于最大灵活性的考虑,可以重新定义flex用于读取输入到当前缓冲区的宏:

#define  YY_INPUT(buf,result,max_size)

每当词法分析器的输入缓冲区为空时,调用YY_INPUT,buf是缓冲区,maxsize是缓冲区大小,而result则迎来放置实际读取的长度,如果位于EOF,则result等于0.

flex提供两个在动作代码中比较有用的宏:input()和 unput()

每次input()的调用将返回输入流的下一个字符,可以帮助读取一小段输入而不用定义相应的模式

每次对unput(c)的调用把字符c推回到输入流。

输入管理的三个层次是:

1、设置yyin来读取所需文件

2、创建并使用YY_BUFFER_STATE输入缓冲区

3、重定义YY_INPUT

Flex词法分析器的输出

默认的规则:所有没有被匹配的输入都拷贝到yyout

flex允许在添加%option nodefault,使它不要添加默认的规则

这样输入无法被给定的规则完全匹配时,词法分析器可以报告一个错误。

建议总是使用。

起始状态和嵌套输入文件

例子需求:

处理嵌套的包含文件并且打印它们,在打印的时候每行前加上行号。

这个程序需要维护一个包含嵌套输入文件和行号的堆栈,在每次遇到一个#include时压入当前文件和行号信息,在处理完包含文件后再把它们从堆栈弹出。

起始状态,允许指定在特定时刻哪些模式可以被来用匹配。

在靠近文件顶端的%x 行把IFILE定义为起始状态

可以定义任意多的起始状态

%option noyywrap
%option yylineno
%option nodefault %x IFILE %{
struct bufstack{
struct bufstack* prev; /*上一个文件信息*/
YY_BUFFER_STATE bs; /*保持的缓冲区*/ int lineno; /*保持的行号*/
char* filename; /*文件名*/
FILE* f; /*当前的文件句柄*/
}* curbs = 0; char* curfilename; int newfile(char *fn);
int popfile(void);
%} %% ^"#"[ \t]*include[ \t]*[\"<] { BEGIN IFILE; }/*第一个模式匹配#include语句,知道遇到文件名之前的双引号或者<号,得到匹配后,词法分析器会切换到IFILE状态*/ <IFILE>[^ \t\n \">]+ {
//匹配文件名,直到遇到引号、空白字符或者行结束符,文件名传递给newfile
//基于函数input读取include后面剩余的部分,当词法分析器从包含文件返回时,
//可以直接从下一行读取
int c; while((c=input()) && c!='\n'); yylineno++; if(!newfile(yytext))
yyterminate(); BEGIN INITIAL;
} <IFILE>.|\n { //匹配不规范的情况
fprintf(stderr,"%4d bad include file",yylineno);} <<EOF>> {
//特殊匹配模式,匹配输入文件的结束
if(!popfile())
yyterminate(); }
^. { fprintf(stdout,"%4d %s",yylineno,yytext);}
^\n { fprintf(stdout,"%4d %s",yylineno++,yytext);}
\n { ECHO; yylineno++; }
. { ECHO; } %% int main(int argc, char**argv)
{
if(argc<2)
fprintf(stderr,"need file name\n."); if(newfile(argv[1]))
yylex(); return 0; } /*
*维护一个bufstack结构的链表,每个bufstack都有一个例程指向前一个bufstack的指针
*/
int newfile(char *fn)
{ FILE*f = fopen(fn,"r");
struct bufstack * bs =(struct bufstack*)malloc(sizeof(struct bufstack)); if(!f) { perror(fn);return 0;}
if(!bs) { perror("malloca");exit(1);} /*记住当前状态*/
if(curbs) curbs->lineno = yylineno;
bs->prev = curbs; /*建立当前文件信息*/ bs->bs = yy_create_buffer(f,YY_BUF_SIZE);
bs->f = f;
bs->filename = fn;
//恢复到前一个缓冲区
yy_switch_to_buffer(bs->bs);
curbs = bs;
yylineno = 1;
curfilename = fn;
return 1;
} int popfile(void)
{
struct bufstack *bs = curbs;
struct bufstack *prevbs; if(!bs) return 0; /*删除当前文件信息*/
fclose(bs->f);
yy_delete_buffer(bs->bs); /*切回上一个文件*/
prevbs = bs->prev;
free(bs); if(!prevbs) return 0; yy_switch_to_buffer(prevbs->bs);
curbs = prevbs;
yylineno = curbs->lineno;
curfilename = curbs->filename;
return 1;
}

  

使用flex的更多相关文章

  1. OpenCASCADE Expression Interpreter by Flex & Bison

    OpenCASCADE Expression Interpreter by Flex & Bison eryar@163.com Abstract. OpenCASCADE provide d ...

  2. Flex 布局教程:语法篇

    作者: 阮一峰 网页布局(layout)是CSS的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便 ...

  3. Flex 布局教程:实例篇

    该教程整理自 阮一峰Flexible教程 今天介绍常见布局的Flex写法.你会看到,不管是什么布局,Flex往往都可以几行命令搞定. 我的主要参考资料是Landon Schropp的文章和Solved ...

  4. CSS布局之div交叉排布与底部对齐--flex实现

    最近在用wordpress写页面时,设计师给出了一种网页排布图样,之前从未遇到过,其在电脑上(分辨率大于768px)的效果图如下: 而在手机(分辨率小于等于768px)上要求这样排列: 我想到了两种方 ...

  5. Flexible 弹性盒子模型之flex

    实例 让所有弹性盒模型对象的子元素都有相同的长度,忽略它们内部的内容: #main div { flex:1; } 复制 效果预览 浏览器支持 表格中的数字表示支持该属性的第一个浏览器的版本号. 紧跟 ...

  6. 信息系统实践手记6-JS调用Flex的性能问题一例

    说明:信息系统实践手记系列是系笔者在平时研发中先后遇到的大小的问题,也许朴实和细微,但往往却是经常遇到的问题.笔者对其中比较典型的加以收集,描述,归纳和分享. 摘要:此文描述了笔者接触过的部分信息系统 ...

  7. flex自适应高度内容高度超出容器高度自动出现滚动条的问题

    在容器中设置 flex-grow:2; overflow-y:auto;overflow-x:hidden;容器高度自适应. 内容高度不固定,无法出现滚动条,然后在容器中添加height:0,出现滚动 ...

  8. 在移动端中的flex布局

    flex布局介绍: flex布局很灵活, 这种布局我们也可以称之为弹性布局,  弹性布局的主要优势就是元素的宽或者高会自动补全; flex布局实例: 比如有两个div,一个div的宽度为100px, ...

  9. flex学习小结

    接触到flex一个多月了,今天做一个学习小结.如果有知识错误或者意见不同的地方.欢迎交流指教. 画外音:先说一下,我是怎么接触到flex布局的.对于正在学习的童鞋们,我建议大家没事可以逛逛网站,看看人 ...

  10. flex实验总结

    1.父元素 .box{ display:flex; flex-direction: column;//铺满垂直排列 flex-direction: column-reverse;//铺满垂直反向排列 ...

随机推荐

  1. ZOJ-2091-Mean of Subsequence (反证法的运用!!)

    http://blog.csdn.net/u014355480/article/details/40862041 ZOJ2091 题意:其实就是找后几个数的平均值的最大值!! (贪心策略!要找对) k ...

  2. Emgu.CV(一)

    由于这块的知识不少,会分好几期写完 什么是OpenCV? OpenCV是一个基于(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows和Mac OS操作系统上.它轻量级而且高效--由一 ...

  3. win10 uwp 绑定静态属性

    Jasoon 大神问,如何绑定静态属性. 我们经常有静态属性,那么我们如何绑定 假如我们的ViewModel有一个静态属性 public static string CVTE { set; get; ...

  4. Unity Shader - 消融效果原理与变体

    基本原理与实现 主要使用噪声和透明度测试,从噪声图中读取某个通道的值,然后使用该值进行透明度测试. 主要代码如下: fixed cutout = tex2D(_NoiseTex, i.uvNoiseT ...

  5. JavaScript中的比较规则之“==”运算符

    "=="运算符(两个操作数的类型不相同时) 如果一个值是null,另一个值是undefined,则它们相等 如果一个值是数字,另一个值是字符串,先将字符串转换为数学,然后使用转换后 ...

  6. Linux.杀毒.Centos安装杀毒软件Clam

    Linux系统用了几年, 甚少中毒 但前不久在阿里云的服务器被种马,折腾了几周才解决干净 感觉还是装个杀毒/马软件定期扫一扫比较稳妥, 这个Clam是免费的, 安装和配置办法记录如下: 已验证适用环境 ...

  7. Robot Framework自动化测试框架初探

    Robot Framework是一款python语言编写,通用的功能自动化测试框架.它使用了比较易用的表格数据语法,基于关键字驱动测试,主要用来验收测试和验收测试驱动开发(ATDD). 本文主要介绍R ...

  8. iOS初学,关于变量加下划线问题

    为什么做ios开发,变量前要加下划线才有用? 看到这个哥们的解释后,终于明白了,转帖到此. 链接在此:http://www.cocoachina.com/bbs/read.php?tid=234290 ...

  9. 从入门到放弃之IO

    浅说IO 学到现在利用过的特殊符号不少组合起来很多都有让人眼前一亮的用法,在这里先聊聊I/O的一些相关知识. 本文开始之前先介绍一下需要知道的一些小知识和需要注意的地方. 在linux中也是有优先级的 ...

  10. Java web学习 Cookie&&Session

    cookie&&session 会话技术 从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程,成为一次会话.会 话技术就是记录这次会话中客户端的状态与数据的. 会话技术分为Coo ...