Flex2.5用户手册(三)
Flex可识别的输入文件格式(用于描述要生成的扫描器)
Flex的输入文件包括如下的三个部分,通过%%分隔开,如下所示:
定义
%%
规则
%%
用户代码
定义段包括简单的名字声明,和为简化扫描器的描述而进行的宏定义,还有起始条件的声明,关于起始条件稍后将介绍。
定义名称的形式如下:
名称 定义
名称是以字母或下划线’_’开始,后跟零个或多个字母、数字、_或者-(dash)。定义部分整体做为一个记号(token),从名称后的首个非空字符开始一直到该行的结束都是定义部分。
随后,就可通过名称来引用定义(definition)。例如:
DIGIT [0-9]
ID [a-z][a-z0-9]*
"DIGIT"被定义为一个正则表达式,该表达式可以匹配单个数字,"ID"也代表一个正规表达式,它可匹配这样的字符串:“以字母开头,随后为零个或多个字母和数字的组合”。
通过名字来引用:
{DIGIT}+"."{DIGIT}*
上述表达式和下面的完全等价
([0-9])+"."([0-9])*
上式可匹配这样的字符串:“小数点前有一个或多个数字,小数点后有零个或多个数字”。
规则段中的规则定义采用如下形式:
模式 动作
模式必须顶头开始写,不能有空格,并且动作必须从同一行开始。后面,我们在进一步讨论模式和动作,这里先简单介绍一下。
最后,用户代码段的内容将被直接复制到’lex.yy.c’,做为扫描器的子程序来使用。该段是可选的;如果没有提供该段,那么第二个’%%’将被跳过。
位于定义段和规则段的任何文字以及位于’%{’和’%}’中内容都会被复制到输出中。
在规则段,出现在第一条规则之前的任何行或包含于%{}中的文字可以用于声明在扫描器例程中使用的局部变量和代码,只要进入扫描器例程就会执行这些代码。位于规则段的其它的多行或者%{}中的文字将被复制到lex.yy.c中,但是这种定义并不是很明确,可能会引起编译时错误(这种特性是为了符合POSIX规范,下面将讨论其他特性)。
在定义段,单行注释(例如,以"/*"开头的一行)将被直接复制到lex.yy.c中。(注意:在规则段不会遵循上述规定。)
模式(Patterns)
模式是对正则表达式的扩展,如下:
`x'
匹配字符’x’
`.'
除换行之外的任何字符(字节)。
`[xyz]'
说明了一个“字符类”;此时,模式匹配`x'、`y'或`z'中的任何一个。
`[abj-oZ]'
带有范围的“字符类”;匹配’a’、’b’,’j’到’o’之间的任何字母,或者’Z’。
`[^A-Z]'
“非字符类”(negated character class),可匹配除“非字符类”中声明的字符以外的所有字符,本例中,匹配除大写字母外的所有任何字符。
`[^A-Z\n]'
除大写字母和换行外的任何字符。
`r*'
零个或多个r,r可以是任意的正则表达式。
`r+'
一个或多个r
`r?'
零个或一个r
`r{2,5}'
2到5个r
`r{2,}'
2到无穷个r
`r{4}'
匹配恰好4个r
`{name}'
此处将按照前面关于"name"的定义进行展开。(see above)
`"[xyz]\"foo"'
将foo按照字面意思匹配,等同于:`[xyz]"foo',’\’ 为转义符号
`\x'
如果x是`a',`b',`f',`n',`r',`t',或者`v',那么\x将被解释为ANSIC-C字符,否则,将按字面意思解释`x'(该形式用于转义像`*'这样的操作符)
`\0'
a NUL character (ASCII code 0)
`\123'
以八进制数123表示的字符
`\x2a'
以十六进制数2a表示的字符
`(r)'
匹配一个r;圆括号用于改变原有字符的优先级(see below)
`rs'
在正则表式r之后匹配正则表达式s;这种方式称为:“连接”
`r|s'
表示匹配正则表达式r或者正则表达式s
`r/s'
表示仅当s被匹配时,才匹配r。'/'本身不匹配任何字符,当需要确定那个规则是最长匹配时,由s匹配的文本将被包括进来,需要注意的是,在动作(action)被执行之前,由s匹配的文本将被退回到输入缓冲区中。因此,在执行动作时仅能看到匹配r的文本(译注:这意味着yytext将不包含匹配s的字符,而且它们也不会记入yyleng中)。这种类型的模式称为右上下文模式(trailing context)。(flex不能正确识别某些`r/s'的组合;请参看后面的“flex的不足之处和它的Bugs”一节,那里将讨论“右上下文的危险性”)
`^r'
仅在行首位置匹配r(即扫描开始的位置,或者扫描到一个换行符之后)。(译注:'^'不匹配任何字符,有时,我们也将此种模式称为左上下文模式)
<待续>