一些scanner会都多个stream读取输入,由于flex使用大的buffer读取输入,因此你不能简单的写一个YY_IPUT(),因为你可能在buffer还没有处理完的时候(include语句后面还有很长的buffer)就需要切换输入文件。
为了处理这些文件,flex提供了一些机制。
YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size )
YY_BUFFER_STATE在内部是一个指针,指向一个透明的结构体struct yy_buffer_state。file只被YY_INPUT的yyin,如果你重定义了YY_IPUT,不在用它,你可以传一个NULL,size是buffer的大小,你可以使用宏YY_BUF_SIZE。
void yy_switch_to_buffer ( YY BUFFER STATE new buffer )
切换buffer
void yy_delete_buffer ( YY BUFFER STATE buffer )
删除buffer相关的存储
void yypush_buffer_state ( YY BUFFER STATE buffer )
栈操作,入栈一个buffer
void yypop_buffer_state ( )
弹出一个buffer,被弹出的buffer将使用yy_delete_buffer删除。
void yy_flush_buffer ( YY BUFFER STATE buffer )
丢掉buffer中的内容,从YY_INPUT()重新填充。
YY_CURRENT_BUFFER宏返回当前的BUFFER。
下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | /* the "incl" state is used for picking up the name * of an include file */ %x incl %% include BEGIN(incl); [a-z]+ ECHO; [^a-z\n]*\n? ECHO; <incl>[ \t]* /* eat the whitespace */ <incl>[^ \t\n]+ { /* got the include file name */ yyin = fopen( yytext, "r" ); if ( ! yyin ) error( ... ); yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE )); BEGIN(INITIAL); } <<EOF>> { yypop_buffer_state(); if ( !YY_CURRENT_BUFFER ) { yyterminate(); } } |
下面的routines还可以scanning内存中的字符串。
YY_BUFFER_STATE yy_scan_string ( const char *str )
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len )
yy会拷贝到buffer中去scan。
YY_BUFFER_STATE yy_scan_buffer (char *base, yy size t size)
这个直接scan base,最后两个字节必须为YY_END_OF_BUFFER_CHAR (ASCII NUL)
特殊的rule <<EOF>>,表示读取到文件末尾,且yywarp()返回了非0(意味着没有更多文件了)。action必须执行下面的操作之一:
将一个新的文件打开到yyin
执行return
执行特殊的yyterminate()
切换到新的buffer
如果<<EOF>>没有指定start conditon,那么它应用到所有还没有执行<<EOF>>的start condition,想要指定一个<<EOF>>只用在初始start condition,使用:
<INITIAL><<EOF>>
YY_USER_ACTION宏,在每个被匹配的rule的action执行之前,执行这个宏。
YY_NUM_RULES,rules的个数。
YY_USER_INIT,在scanner扫描之前执行的初始化。
yy_set_interactive(is_interactive)
是否是交互式输入
YY_BREAK
rules的action是一个大的swtich块,YY_BREAK用来结束一个action,通常是break
char *yytext
存储当前token,它可以被修改,但是不能追加内容。
如果指定了%array选项,那么yytext被声明为 char yytext[YYLMAX]
int yyleng
存储当前token的长度
FILE *yyin
void yyrestart(FILE *new_file)
切换yyin,但是buffer中的内容丢失了。
FILE *yyout
ECHO使用yyout来输出。
YY_CURRENT_BUFFER
当前buffer
YY_START
当前start condition的整数值
yacc parser-generator主要使用flex来获取token。因此yylex()的主要作用是返回下一个token的类型,以及设置yylval。
因此典型的用法:
%{
#include "y.tab.h"
%}
%%
[0-9]+ yylval = atoi( yytext ); return TOK_NUMBER;