第三章输入文件的格式
flex输入文件由三部分组成,以只包含”%%”的行分隔。
definitions
%%
rules
%%
user code
3.1 定义段的格式
定义段包含简单名称定义的声明,以简化扫描程序规范,以及启动条件的声明,这些将在后面的部分中解释。
名称定义有如下形式:
name definition
“name”是一个以字母或下划线(“”)开头的单词,后面跟着0个或多个字母、数字、””、或”-”(破折号)。定义从名称后面的第一个非空白字符开始,一直到行尾。随后可以使用{name}引用定义,它将展开为(definition)。例如:
DIGIT [0-9]
ID [a-z][a-z0-9]*
将DIGIT定义为匹配单个数字的正则表达式,将ID定义为匹配字母后跟0个或多个字母或数字的正则表达式。后面提到的
{DIGIT}+"."{DIGIT}*
等效为:
([0-9])+"."([0-9])*
匹配一个或多个数字后面跟着’.’的0个或多个数字的浮点数。
无缩进注释(即以’/’开头的行)被逐字复制到输出中,直到下一个’/’。
任何缩进的文本或包含在’%{’和’%}’中的文本也会被逐字复制到输出中(删除’%{’和’%}’符号)。’%{’和’%}’符号必须在行上不缩进。
%top块类似于’%{’’...’’%}’块,除了%top块中的代码被重新定位到生成文件的顶部,在任何flex定义之前(实际上,yyIN_HEADER是在’%top’块之前定义的)。当您希望定义某些预处理宏或在生成代码之前包含某些文件时,%top块非常有用。单个字符{和}用于分隔%top块,如下例所示:
%top{
/* This code goes at the "top" of the generated file. /
#include <stdint.h>
#include <inttypes.h>
}
允许使用多个%top块,并且保留它们的顺序。
3.2 规则的格式
flex输入的规则部分包含了一系列这样的规则:
pattern action
其中pattern必须不缩进,动作必须从同一行开始。有关模式和操作的进一步描述,请参阅模式章节。
在规则部分,任何出现在第一个规则之前的缩进或%{ %}封闭的文本都可以用来声明扫描程序的局部变量,以及(在声明之后)在扫描程序进入时执行的代码。规则部分中的其它缩进或%{ %}文本仍然被复制到输出中,但其含义没有明确定义,并且很可能导致编译时错误(该特性是为了POSIX兼容性而存在的,参见lex和posix,了解其它类似的特性)。
任何缩进的文本和包含在%{ %}中的文本将逐字复制到输出中(删除%{和%}符号)。%{和%}符号必须在行上不缩进。
3.3 用户代码段格式
用户代码部分只是逐字复制到lex.yy.c中。它用于调用扫描器或被扫描器调用的函数。这个部分的存在是可选的,如果缺少,也可以跳过输入文件中的第二个”%%”。
3.4 输入中的注释
flex支持C风格的注释,也就是说/和/之间的任何内容都被认为是注释。每当flex遇到注释时,它就将整个注释逐字复制到生成的源代码中。注释可能出现在任何地方,但有以下例外:
注释可能不会出现在flex期望正则表达式的规则部分。这意味着注释可能不会出现在一行的开头,或者紧跟在扫描器状态列表之后。
注释不能出现在定义部分的%option行上。
如果你想遵循一个简单的规则,那么总是在新行开始注释,在初始/之前使用一个或多个空白字符。该规则在输入文件的任何地方都适用。
以下示例中的所有注释都是有效的:
%{
/* code block */
%}
/* Definitions Section */
%x STATE_X
%%
/* Rules Section /
ruleA / after regex / { / code block / } / after code block /
/ Rules Section (indented) /
<STATE_X>{
ruleC ECHO;
ruleD ECHO;
%{
/ code block /
%}
}
%%
/ User Code Section */