flex函数宏详解
更新时间:2023-11-10 16:25:01 阅读量: 教育文库 文档下载
- flex函数代码位置推荐度:
- 相关推荐
1.内置变量
yy_create_buffer:见后面的缓冲管理 yy_delete_buffer:见后面的缓冲管理 yy_flex_debug:见后面的缓冲管理 yy_init_buffer:见后面的缓冲管理 yy_flush_buffer:见后面的缓冲管理 yy_load_buffer_state:见后面的缓冲管理 yy_switch_to_buffer:见后面的缓冲管理
yyin: 输入缓冲流的文件指针,可以被替换以实现解析某个自定义的文件 yyleng:当前匹配字串的长度 yylex: 解析函数,接口 yylineno:当前匹配的文件行号 yyout: 输出流的指针
yyrestart: 手动调用yyrestart.会重启解析
yyrestart( yyin );一般是打开某个文件之后,yyrestart(yyin)再解析.
yytext: 当前匹配的字串
yywrap: 解析一个文件完毕之后,会调用yywrap:返回1表示结束,0表示继续(此时最好重新打开yyin或者重置yyin流) 2. 几个重要函数:
1). yymore(): yymore()的含义是,当当前匹配的字串之后,想把后面配置的字串附加到这个字串后面,组成新的token返回. 比如: %%
mega- ECHO; yymore(); kludge ECHO;
如果:“mega-kludge\the following will write \to the output。
为什么呢? 首先遇到 mega-,接着被more了一下,因此就会把kludga附加到mega-后面,而后面的kludge的动作又是打印,因此会打印出:mega-mega-kludge 2). yyless(): yyless()的含义是:当当前的匹配之后,我想只返回前面几个字符,并且把后面回退到输入 比如: %%
foobar ECHO; yyless(3); [a-z]+ ECHO;
input \ 为什么呢? foobar输入之后,匹配foobar,ECHO打印出来,接着yyless(3),则输入流变为bar了(yytext为foo).接着再匹配,于是匹配 到[a-z]+,因此再次打印出bar.
3).BEGIN: flex下一个起始解析状态。见第3节,flex的状态. 4).REJECT: 相当于拒绝此匹配,让系统重新找下一个匹配。 \
will write \ %%
a | ab | abc |
abcd ECHO; REJECT;
.|\\n /* eat up any unmatched character */
5).unput(c): 把c重新放到输入流。 6).input(): 读取输入流下一个字符
7).yyrestart(): 该函数迫使yylex重新解析。yyrestart有个函数指针流,可以再打开之后,重新使用yyrestart().
3. 解析源管理:
1). 默认是从yyin获取,而yyin则是stdout,也可以是其它文件。 if ( ! yyin ) yyin = stdin;
if ( ! yyout ) yyout = stdout;
2). 如果你打开了一个文件,并把yyin指向此文件,则从该文件中读取.比如:
在main中: FILE* fp = NULL;
fp = fopen(\ yyin = fp;
之后再使用 yylex()
则flex从hell.txt中读取信息并解析.
3).从字符串中解析
先使用下列函数,转化缓冲,之后再使用 yylex()
a. yy_scan_string(char*).使用了yy_scan_string(char*)之后,flex会把char*放到yy的输入缓冲中(会调用到yy_switch_to_buffer.) b. yy_scan_bytes(const char *base, int len); c. yy_scan_buffer(char *base, yy_size_t size)
这几个函数内部都使用的是缓冲切换的创建等函数,见后面的章节.
4).利用EOF内置规则,重新打开多个文件输入: 比如: <
if ( *++filelist )
yyin = fopen( *filelist, \ else
yyterminate(); }
5).多缓冲问题:
a.此问题可以按上面的 <
b.另外一种形式,比如:#include
这就需要用到在flex动作中手动切换缓冲。flex对每个缓冲有个缓冲输入流指针,指向当前位置,各个被切换的缓冲互不相干扰,这恰好很好地解决了文件包含另外一个文件,而子文件也许要yylex的这种场合. 这就需要使用到flex底层的缓冲管理了.见下节
4. flex的缓冲管理:
flex本质上都是对缓冲输入流进行yylex词法分析. 缓冲是个结构体,每个缓冲有个缓冲输入流指针,指向当前位置,各个被切换的缓冲互不相干扰,而相关yyin,yyrestart,yy_create_buffer,yy_scan_string系列函数都是操纵flex底层缓冲的.
flex缓冲是一个结构体:
我们以下面的词法规则为例子:(来自flex官方网站的注解) /* the \ * of an include file */ %x incl
%{
#define MAX_INCLUDE_DEPTH 10
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; %} %%
include BEGIN(incl);
[a-z]+ ECHO; [^a-z\\n]*\\n? ECHO;
fprintf( stderr, \ exit( 1 ); }
include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
yyin = fopen( yytext, \
if ( ! yyin ) error( ... );
yy_switch_to_buffer(
yy_create_buffer( yyin, YY_BUF_SIZE ) );
BEGIN(INITIAL); }
<
if ( --include_stack_ptr < 0 ) {
yyterminate(); }
else {
yy_delete_buffer( YY_CURRENT_BUFFER ); yy_switch_to_buffer(
include_stack[include_stack_ptr] ); } }
YY_BUFFER_STATE就是一个缓冲。该lex文法使用到了
<
BEGIN(INITIAL)类似于BEGIN(0),表示状态从开头解析(0表示不带状态的解析,也就说规则前没有<>这个标记的状态.
上面的文法可以知道:
a. 在遇到include之后,跳到incl状态。
b. 在incl状态中,跳过空白的字符,得到文件名(include file),先把当
前的flexBuffer保存到数组栈,然后打开新的文件,并把flex的当前输入流切换到刚打开的新文件的输入流.
c. 切换到INITIAL状态(没有<>在规则前的默认的状态)
d.这里用到了几个宏或者函数: yy_switch_to_buffer, yy_create_buffer,YY_CURRENT_BUFFER,yy_delete_buffer. 这些函数看名字就应该知道其作用了。
4. flex的状态(Start conditions).
上面的缓冲管理已经涉及到状态管理了。flex的状态管理相当于普通词法的扩展。通过flex的状态,大大扩充了词法分析本身的功能。 比如:
a.
表示在STRING状态下才进行 [^\匹配。
b.
... }
表示在INITIAL,STRING,QUOTE才匹配。\\. flex的状态怎么使用呢?
a. 首先定义:以%开头(flex的申明本质上所有的都是以%开头)定义,有2种: %s,%x,其中%s = %x+INITIAL,也就说是%s的状态为%x定义的+INITIAL状态 b. 在规则域中,使用<状态>规则,比如 comment是个状态,则有
d.某个规则可以支持多个状态,使用“,”隔开。比如<
e.flex还提供了一套相关函数:
yy_push_state, yy_pop_state, yy_top_state, BEGIN()
可以说有了状态的支持,flex的功能更加强大了,简单的文法分析甚至可以不借助于yacc/bison来做了。
一个完整的例子: %x str %%
char string_buf[MAX_STR_CONST]; char *string_buf_ptr;
\\\
*string_buf_ptr = '\\0';
/* return string constant token type and * value to parser */ }
/* error - unterminated string constant */ /* generate error message */ }
/* octal escape sequence */
int result;
(void) sscanf( yytext + 1, \
if ( result > 0xff )
/* error, constant is out-of-bounds */
*string_buf_ptr++ = result; }
/* generate error - bad escape sequence; something * like '\\48' or '\\0777777' */ }
while ( *yptr )
*string_buf_ptr++ = *yptr++;
}
5. flex C++的支持
编译时,使用flex -+ 文件,就可以得到.cc的文件,而且flex也会生成C++相关类,对应的类和方法有: FlexLexer:成员方法有:
a. yylex(), YYText(), YYLeng(),lineno(), set_debug(),debug(), b. 构造函数yyFlexLexer( istream* arg_yyin = 0, ostream* arg_yyout = 0 )
c. 缓冲:switch_streams(istream* new_in = 0, ostream* new_out = 0),yylex( istream* new_in = 0, ostream* new_out = 0 ) 等等。 例子:
// An example of using the flex C++ scanner class. %{
int mylineno = 0; %}
string \\\
ws [ \\t]+
alpha [A-Za-z] dig [0-9]
name ({alpha}|{dig}|\\$)({alpha}|{dig}|[_.\\-/$])* num1 [-+]?{dig}+\\.?([eE][-+]?{dig}+)?
正在阅读:
flex函数宏详解11-10
Excel公式(自学摘要) - 图文03-23
ANSYS操作常用菜单--中英文对照11-04
招商人员薪酬和佣金提成激励方案05-13
单片机 考前复习习题110-28
厦门大学结构化学第3章答案05-15
浅谈幼儿良好行为习惯的培养与养成04-14
2018年中国木瓜果酒市场供需报告目录05-21
无形资产作业参考答案04-08
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 详解
- 函数
- flex
- 山东省潍坊市高三上学期期末考试化学试题(B卷) - 图文
- 西米替丁联合山莨菪碱治疗轮状病毒性肠炎疗效观察
- 2014高中语文人教版必修三配套练习:第8课 寡人之于国也
- 中小学校及教育系统突发公共卫生事件应急预案
- 2013年考研管理类综合能力考试中文写作真题以及解析(一)
- 运用多媒体技术培养学生的创新能力
- 生产车间主管和组长的岗位职责
- Java程序设计 实验七
- 英国文学史课程考试大纲
- 数字信号课程设计 课题六 语音信号分析系统设计
- 基础知识总结(2)
- 鄂教版小学语文毕业考试模拟试卷14
- 佛山市教育局 - 图文
- 专家意见修改围护土方开挖方案
- 危害辨识与风险评价控制培训试题- 答案
- 安全技术交底(铁艺安装)
- 英语写作 教案 - 图文
- 师生联系手册(2016)
- 2017-2018学年北京市海淀区高一(下)期中数学试卷
- 实验 2 Java 基本语法练习 - 20131031