多个flex选项通过下面的菜单被分类。如果你想通过名称查找一个特殊的选项,查看扫描器选项索引。
14.1 指定文件名的选项
‘--header-file=FILE,%option header-file=”FILE”’
命令flex写一个C头文件到FILE。这个文件包含函数的原型,extern变量,和扫描器使用的类型。仅通过头文件导出外部API。许多在扫描器动作内使用的宏没有被导出到头文件。这是由于命名空间的问题和一个干净的外部API的目标。
在头文件中,定义了yyIN_HEADER宏,其中的yy被替换为适当的前缀。
当C++扫描器在yyFlexLexer.h中提供了它自己的头文件时,’--header-file’选项不兼容’--c++’选项。
‘-oFILE,--outfile=FILE,%option outfile=”FILE”’
指示flex写扫描器文件FILE替代lex.yy.c。如果你在’--stdout’选项中组合’--outfile’,则扫描器被写到stdout,但是它的#line指令(查看上面的’-l’选项)引用到文件FILE。
‘-t,--stdout,%option stdout’
命令flex写扫描器输出到标准输出而不是lex.yy.c。
‘-SFILE,--skel=FILE’
覆盖flex用来构造扫描器的默认skeleton文件。除非您正在进行flex维护或开发,否则永远不需要这个选项。
‘--tables-file=FILE’
写序列化的扫描器dfa表到FILE。产生的扫描器将不包含这个表,且要求它们在运行时被加载。查看序列化章节。
‘--tables-verify’
这个选项是为flex开发使用。我们在这里记录它,以防您偶然发现它,或者以防您怀疑序列化表中存在不一致。flex将序列化扫描器dfa表,但也会像往常一样生成代码内表。在运行时,扫描器将验证序列化表是否与代码内表匹配,而不是加载它们。
14.2 影响扫描程序行为的选项
‘-i, --case-insensitive,%option case-insensitive’
命令flex产生大小写敏感的扫描器。在flex输入模式中给出的字母大小写将被忽略,并且无论大小写如何,都会匹配输入中的标记。yytext中给出的匹配文本将保留大小写(即,它不会被折叠)。对于棘手的行为,查看case and character ranges章节。
‘-l, --lex-compat, %option lex-compat’
为原始的AT&T lex实现开放最大的兼容性。注意这样做不意味着全部兼容。这个选项的使用会导致大量的性能损失,且它不可以与’--c++’,’--full’,’--fast’,’-Cf’,或’-CF’选项一起使用。在兼容性上更详细的描述请查看Lex and Posix章节。这个选项也会导致在生成扫描器中产生#define’ 的YY_FLEX_LEX_COMPAT的名字。
‘-B, --batch, %option batch’
命令flex产生一个batch扫描器,与’--interactive’生成的交互式扫描器相反(见下文)。通常,当您确定您的扫描器永远不会被交互使用时,并且希望从中获取更多的性能时,您可以使用’-B’。如果您的目标是提高更多的性能,您应该使用’-Cf’或’-Cf’选项,它们会自动打开’--batch’。
‘-I, --interactive, %option interactive’
命令flex产生一个交互式(interactive)扫描器。交互式扫描器只在绝对必要的情况下提前判断匹配了什么标记。事实证明,即使扫描器已经看到了足够多的文本来消除当前标记的歧义,始终向前查找一个额外的字符比只在必要时向前查找要快一些。但是总是向前看的扫描器交互性能很差;例如,当用户键入换行符时,它不会被识别为换行符,直到它们输入另一个标记,这通常意味着键入另一个整行。
flex扫描器默认是interactive,除非你使用’-Cf’或’-CF’表压缩选项(查看性能章节)。这是因为如果您正在寻找高性能时,您应该使用这些选项之一,所以如果您不这样做,flex会假设您宁愿牺牲一点运行时性能来换取直观的交互行为。注意,’--interactive’和’-Cf’或’-CF’是互斥的,不能同时使用。因此,这个选项实际上并不需要;在所有允许的情况下,默认情况下它是打开的。
你可以使用’--batch’选项强制扫描器不进行交互。
‘-7, --7bit, %option 7bit’
命令flex产生一个7位的扫描器,例如,它只能识别输入中的7位字符。使用’--7bit’的有点是扫描器的表可以达到使用’--8bit’生成表的一半大小。缺点是,如果这些扫描器的输入包含8位字符,那么它们经常会被挂起或崩溃。
但是,请注意,除非您使用’-Cf’或’-CF’表压缩选项生成扫描器,否则使用’--7bit’只会节省少量的表空间,并使扫描器的可移植性大大降低。flex的默认行为是生成一个8位扫描器,除非你使用’-Cf’或’-CF’,在这种情况下,flex默认生成7位扫描器,除非你的站点总是被配置为生成8位扫描器(非USA的站点通常是这种情况)。您可以通过检查如上述所述的’--verbose’输出中的标志摘要来判断flex生成的是7位扫描器还是8位扫描器。
请注意,如果您使用’-Cfe’或’-CFe’,flex仍然默认生成8位扫描程序,因为通常使用这些压缩选项的完整8位表并不比7位表大多少。
‘-8, --8bit, %option 8bit’
命令flex产生一个8位的扫描器,例如,扫描器可以识别到8位的字符。此标志仅用于使用’-Cf’或’-CF’生成的扫描器,否则flex默认生成8位扫描器。
查看上面对于flex默认行为及7位和8位扫描器之间的权衡的关于’--7bit’的讨论。
‘--default, %option default’
产生默认的规则
‘--always-interactive, %option always-interactive’
命令flex生成一个始终认为其输入是交互式的扫描器。正常情况下,在每个新的输入文件上,扫描器调用isatty(),试图确定扫描器的输入源是否是交互式的,因此应该一次读取一个字符。但是当使用此选项时,不会进行此类调用。
‘--never-interactive, --never-interactive’
命令flex产生一个从来不会考虑输入是交互式的扫描器。这个选项与always-interactive互斥。
‘-X, --posix, %option posix’
最大可能的兼容POSIX 1003.2-1992定义的lex。由于flex最初是为了实现lex的POSIX定义而设计的,这通常只涉及很少的行为变化。目前编写的flex和POSIX标准之间的已知差异是:
在POSIX和AT&T的lex中,重复运算符’{}’的优先级低于串联(因此’ab{3}’产生’ababab’)。大多数POSIX实用程序使用扩展正则表达式(ERE)优先级,其重复操作符的优先级高于连接(这会导致’ab{3}’产生’abbb’)。默认情况下,flex将重复操作符的优先级置于连接之前,这与其它POSIX实用程序的ERE处理相匹配。当指定’--posix’或’-l’时,flex将为重复操作符使用传统的AT&T和POSIX兼容的优先级,其中连接的优先级高于重复操作符。
‘--stack, %option stack’
是能使用开始条件栈(查看开始条件章节)
‘--stdinit, %option stdinit’
如果设置(如,%option stdinit)则替代默认的NULL为初始的yyin为stdin,yyout为stdout。一些现有的lex程序依赖于这种行为,尽管它不符合ANSI C,因为ANSI C不要求标准输入和标准输出为编译时常数。然而,在可重入扫描器中,这不是问题,因为初始化在运行时是在yylex_init中执行的。
‘--yylineno, %option yylineno’
指示flex生成一个扫描其,该扫描器在全局变量yylineno中维护从其输入读取的当前行数。这个选项通过%option lex-compat实现。在可重入的C扫描程序中,无论%option yylineno的值如何,都可以访问宏yylineno,但是,除非启用了%option yylineno,否则它的值不会被flex修改。
‘--yywrap, %option yywrap’
如果不设置(如,--noyywrap),创建的扫描器在文件结束时不会调用yywrap(),但是简单的假设没有更多的文件需要扫描(直到用户将yyin指向一个新文件并再次调用yylex())。
14.3 代码级和API选项
‘--ansi-definitions, %option ansi-definitions’
被废弃,忽略
‘--ansi-prototypes, %option ansi-prototypes’
被废弃,忽略
‘--bison-bridge, %option bison-bridge’
命令flex产生一个C扫描器,意味着它被GNU bison解析器调用。扫描器对bison的兼容性进行了较小的API更改。特别的,yylex的声明被修改为接受一个额外的参数yylval。查看bison bridge章节。
‘--bison-locations, %option bison-locations’
命令flex正在使用GNU bison %locations。这意味着yylex被传递一个额外的参数yylloc。这个选项实现了%option bison-bridge。查看bison bridge章节。
‘-L, --noline, %option noline’
命令flex不产生#line指令。没有这个选项,flex会用#line指令对生成的扫描器进行干扰,这样操作中的错误信息就会根据原始flex输入文件(如果错误是由输入文件中的代码引起的)或lex.yy.c(如果错误是flex的错误 -- 您应该报嘎bug中给出的电子邮件地址报告这些类型的错误)正确定位。
‘-R, --reentrant, %option reentrant’
命令flex产生一个可重入的C扫描器。产生的扫描器可以安全的被用于多线程环境。可重入的扫描器的API与非重入的扫描器不同(查看可重入章节)。由于可重入和不可重入flex扫描器之间的API不同,因此必须先修改不可重入flex代码,然后才能适合使用该选项。这个选项不兼容’--c++’选项。
这个选项’--reentrant’不影响扫描器的性能。
‘-+, --c++, %option c++’
指定你想让flex产生的C++扫描器类。查看Cxx章节更详细的信息。
‘--array, %option array’
指定你想让yytext使用字符数组替代字符指针。
‘--pointer, %option pointer’
指定yytext为char *类型,而不是数组。这个默认是char *
‘-PPREFIX, --prefix=PREFIX, %option prefix=”PREFIX”’
将flex对所有全局可见的变量和函数名使用的默认’yy’前缀改为’prefix’。例如,’--prefix=foo’改变yytext的名字为footext。它也改变默认的输出文件的名字,从lex.yy.c变为lex.foo.c。以下是受影响的部分列表:
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
yytext
yywrap
yyalloc
yyrealloc
yyfree
(如果你正在使用C++扫描器,则仅yywrap和yyFlexLexer受到影响。)在扫描器内部,你仍然可以使用全局变量和函数名称的任意一个版本来引用它们;但是外部,它们有修改后的名称。
该选项允许你轻松的将多个flex程序连接到同一个可执行文件中。不过请注意,使用这个选项也会重命名yywrap(),因此您现在必须为您的扫描器提供您自己的(适当命名的)程序版本,或者使用%option noyywrap,因为使用’-Ifl’链接在默认情况下不再为您提供一个。
‘--main, %option main’
指示flex为扫描器提供默认的main()程序,该程序只需要调用yylex()。这个选项实现了noyywrap(查看下面的描述)
‘--nounistd, %option nounistd’
禁止包含非ANSI头文件unistd.h。这个选项用于不存在unistd.h的目标环境中。请注意,有些选项可能会导致flex生成依赖于通常再unistd.h中找到的函数代码(例如,isatty(),read()。)如果你想使用这些函数,你必须告诉编译器在哪里可以找到它们。查看option-always-interactive的描述。查看option-read的描述。
‘--yyclass=NAME, %option yyclass=”NAME”’
仅在产生C++扫描器时应用(‘--c++’选项)。它通知flex,你已经派生的名字作为yyFlexLexer的子类,所以flex将把你的动作在成员函数foo::yylex()而不是yyFlexLexer::yylex()。它还生成一个yyFlexLexer::yylex()成员函数,该函数在调用时发出一个运行时错误(通过调用yyFlexLexer::LexerError())。查看Cxx章节。
14.4 扫描器速度和大小选项
‘-C[aefFmr]’
控制表压缩的程度,更一般的说,控制小型扫描器和快速扫描器之间的权衡。
‘-C’
单独的’-C’指定应该压缩扫描表,但不应该使用等价类和元等价类。
‘-Ca, --align, %option align’
(“align”)指示flex在生成的扫描程序中放弃较大的表以获得更快的性能,因为表的元素在内存访问和计算方面可以更好的对齐。在一些RISC架构上,获取和操作长词比使用较小的单元(如短词)更有效。此选项可以使用扫描器使用的表大小增加四倍。
‘-Ce, --ecs, %option ecs’
指示flex构造等价类,即具有相同词法属性的字符集(例如,如果flex输入中数字的唯一出现是在字符类’[0-9]’中,那么数字’0’,’1’,...’9’都将放在同一个等价类中)。等效类通常会大大减少最终表/对象文件的大小(通常是2-5倍),并且在性能方面非常便宜(每个字符扫描一次数组查找)。
‘-Cf’
指定应该生成完整的扫描表 - flex不应该通过利用针对不同状态的类似转换函数来压缩表
‘-CF’
指定应该使用备用快速扫描器表示(在’--fast’标志下描述)。这个选项不可以与’--c++’一起使用。
‘-Cm, --meta-ecs, %option meta-ecs’
指示flex构造元等价类,元等价类是通常一起使用的等价类(或者字符,如果没有使用等价类的话)的集合。在使用压缩表时,元等价类通常是一大优势,但它们对性能的影响并不大(每个字符扫描一次数组且if测试一次或两次)
‘-Cr, --read, %option read’
导致生成扫描器绕过使用标准I/O库(stdio)进行输入。扫描器将使用read()系统调用,而不是调用fread()或getc(),从而获得性能增益,该增益因系统而异,但通常可以忽略不计,除非您也使用’-Cf’或’-CF’。使用’-Cr’可能会导致奇怪的行为,例如,如果您在调用扫描器之前使用stdio从yyin中读取(因为扫描器将错过之前读取的留在stdio输入缓冲区中的任何文本)。如果你定义了YY_INPUT(),’-Cr’不起作用(参见生成扫描器)。
选项’-Cf’或’-CF’和’-Cm’放在一起没有意义 - 如果表没有被压缩,就没有机会使用元等价类。否则,选项可能是自由混合的,并且是累积的。
默认设置是’-Cem’,它指定flex应该生成等价类和元等价类。此设置提供最高级别的表压缩。您可以以更大的表为代价来换取更快执行的扫描器,下面通常是正确的:
slowest & smallest
-Cem
-Cm
-Ce
-C
-C{f,F}e
-C{f,F}
-C{f,F}a
fastest & largest
请注意,具有最小表的扫描器通常是最快生成和编译的,因此在开发过程中,您通常希望使用默认的最大压缩。
对于生产扫描器来说,‘-Cfe’通常是速度和尺寸之间的一个很好的折中。
‘-f, --full, %option full’
指定快速扫描器。没有表压缩完成,stdio被绕过。结果是大但是快速。这个选项等效于’--Cfr’。
‘-F, --fast, %option fast’
指定应该使用快速扫描表表示(并绕过stdio)。这种表示法与全表表示法’--full’差不多快,而且对于某些模式集来说,速度会小的多(对于其它模式集来说,速度会大的多)。一般来说,如果模式集同时包含关键字和一个全捕获符,则标识符规则,如下:
"case" return TOK_CASE;
"switch" return TOK_SWITCH;
...
"default" return TOK_DEFAULT;
[a-z]+ return TOK_ID;
那么最好使用全表表示。如果只有标识符规则存在,然后使用哈希表或其它类似的方法来检测关键字,那么最好使用’--fast’。
这个选项等效于’-CFr’。它不能与’--c++’一起使用。
14.5 调试选项
‘-b, --backup, %option backup’
产生备用信息到lex.backup。这是一个需要备份的扫描器状态列表,以及需要备份的输入字符。通过添加规则,可以删除备份状态。如果消除所有备份状态并使用’-Cf’或’-CF’,生成的扫描程序将运行的更快(请参阅’--perf-report’标志)。只有希望从扫描器中挤出最后一个周期的用户才需要担心这个选项(见性能章节)。
‘-d, --debug, %option debug’
在调试模式中创建一个产生扫描器。每当模式被识别并且全局变量yy_flex_debug是非0时(默认值),扫描器将向stderr写入如下格式的一行:
-accepting rule at line 53 ("the matched text")
行号指的是定义扫描器的文件中规则的位置(即,提供给flex的文件)。当扫描器备份,接受默认规则到达其输入缓冲区的末端(或遇到NULL;此时,两者看起来是相同的(就扫描器而言)),或者达到文件的末尾。
‘-p, --perf-report, %option perf-report’
产生一个性能报告到stderr。该报告包含了关于flex输入文件特性的注释,这些特性会导致扫描器的性能严重下降。如果您给出两次标志,您还将获得有关导致轻微性能损失的特性的注释。
注意,使用REJECT和变量尾随上下文(请参阅限制)会带来很大的性能损失;使用yymore()、’^’操作符和’--interactive’标志会带来较小的性能损失。
‘-s, --nodefault,%option nodefault’
导致默认规则(不匹配的扫描器输入回显到标准输出)被抑制。如果扫描程序遇到的输入与它的任何规则都不匹配,它就会以错误终止。此选项对于查找扫描器规则集中的漏洞非常有用。
‘-T, --trace, %option trace’
在trace模式中创建flex运行。它会产生大量关于输入形式的错误信息,以及由此产生的非确定性和确定性有限自动机。这个选项主要用于维护flex。
‘-w, --nowarn, %option nowarn’
支持告警消息
‘-v, --verbose, %option verbose’
指定flex应该写入有关其生成的扫描程序的统计信息摘要。大多数统计数据对于临时flex用户来说是没有意义的,但是第一行标识flex的版本(与’--version’报告的版本相同),下一行是生成扫描器时使用的标志,包括那些默认打开的标志。
‘--warn, %option warn’
对某些事情发出警告。特别是,如果可以匹配默认规则,但没有给出默认规则,flex将警告您。我们推荐总是使用这个选项。
14.6 其它的选项
‘-c’
一个不做任何事情的选项包含了POSIX兼容性。
‘-h, -?, --help’
产生一个flex选项的’help’概述到stdout,然后退出。
‘-n’
另外一个什么也不做的选项包括了POSIX兼容性
‘-V, --version’
打印版本号到stdout并退出
即使有许多扫描器选项,一个典型的扫描器可能只指定以下选项:
%option 8bit reentrant bison-bridge
%option warn nodefault
%option yylineno
%option outfile="scanner.c" header-file="scanner.h"
第一行指定了我们想要的扫描器的一般类型。第二行说明我们很小心。第三行要求flex跟踪行号。最后一行告诉flex如何命名文件。(选项可以按任意顺序指定。我们只是把它们分开。)
flex还提供了一种机制来控制扫描器规范本身的选项,而不是通过flex命令行。这是通过在扫描器规范的第一部分中包含%option指令来实现的。你可以用一个%option指令指定多个选项,也可以在flex输入文件的第一部分指定多个指令。
大多数选项都简单的以名称的形式给出,可选的在前面加上单子’no’(中间没有空格)来否定它们的含义。这些名称与它们的长选项等效(但没有前导’--’)。
flex扫描您的规则操作,以确定您是否使用了REJECT或yymore()特性。REJECT和yymore选项可用于覆盖它是否使用这些选项的决定,通过设置它们(例如,%option reject)来表明确实使用了该特性,或者取消设置它们来表明它实际上没有使用(例如,%option noyymore)。
对于希望在生成的扫描程序中抑制不需要的程序出现纯粹的主义者,有许多选项可用。如果不设置(例如,%option nounput),则会导致相应的程序不出现在生成的扫描器中:
input, unput
yy_push_state, yy_pop_state, yy_top_state
yy_scan_buffer, yy_scan_bytes, yy_scan_string
yyget_extra, yyset_extra, yyget_leng, yyget_text,
yyget_lineno, yyset_lineno, yyget_in, yyset_in,
yyget_out, yyset_out, yyget_lval, yyset_lval,
yyget_lloc, yyset_lloc, yyget_debug, yyset_debug
(尽管yy_push_state()和friends不会出现,除非你使用%option stack。)