原文:https://blog.csdn.net/hczhiyue/article/details/20483209
(1)单字符匹配
* ‘x’ 匹配字符 x。
* ‘.’ 匹配任意一个字符(字节),除了换行符。
* ‘[xyz]’ 匹配单个字符,这个字符是方括号中给出的字符类(character class)中的一个。
* ‘[abj-oZ]’ 匹配单个字符,这个字符是方括号中给出的字符类中的一个。与上一方式的区别是指定字符类时用到了一个范围表示法:j-o,这表示按照 26 个英文字母的顺序,从字母 j 开始一直到字母 o 共 6 个字母。这里减号(-)表示范围。如果减号本身也要作为一个匹配字符时,最好用转义字符()去除其特殊含义。由于花括号({})在模式中用来引用名字,以及作为模式定义之后的动作(Action)定义块的首尾界定符,因此如果要在字符类中匹配花括号,必须用转义字符()去除其特殊含义。下面这个例子定义了一个所有可打印字符的字符类:
[[:alnum:][:blank:]] +-*/&!_'?@^`~$\()%|.;[]{}:,#<>=]
* ‘[^A-Z]’ 匹配单个字符,这个字符必须是方括号中给定字符类以外的字符。在方括号内开始处的特殊符号(^)表示否定。当字符 ^ 不在字符类的开始处时,并不具有特殊含义,而是一个普通字符。
* ‘[^A-Z
]’ 匹配单个字符,这个字符不可以是方括号中给出的字符类中的字符。与上一方式的不同在于,这里多了一个换行符,也就是说所匹配的字符不能是 26 个大写字母,也不能是换行符。
根据上面的描述,在表达字符分类时,除了直接用字符以及字符范围来表达外,还有一种叫做字符类表达式的,也有同样的作用,常见的一些表达式如下:
[:alnum:] [:alpha:] [:blank:] [:cntrl:] [:digit:] [:graph:]
[:lower:] [:print:] [:punct:] [:space:] [:upper:] [:xdigit:]
每一个表达式都指示了一个字符分类,而且其名称与标准 C 函数 isXXXX 的名字对应。例如,[:alnum:]就指示了那些经由函数 isalnum()检查后返回 true 的字符,也就是任何的字母或者数字。注意,有些系统上没有给出 C 函数 isblank()的定义,所以 flex 自己定义了 [:blank:] 为一个空格或者一个 tab。
下面所举的几个例子,都是等价的:
[[:alnum:]]
[[:alpha:][:digit:]]
[[:alpha:]0-9]
[a-zA-Z0-9]
应该注意字符类表达式的写法。一个字符类表达式是由一对 [: 和:] 包住的,作为一个整体,在书写时不可与外层的 [] 混淆。
(2)重复模式的匹配
* ‘r*’ r 是一个正则表达式,特殊字符 `*'表示 0 个或多个。因此这个模式表示匹配 0 个或多个 r。
* ‘r+’ r 是一个正则表达式,特殊字符 `+'表示 1 个或多个。因此这个模式表示匹配 1 个或多个 r。
* ‘r?’ r 是一个正则表达式,特殊字符 `?'表示 0 个或 1 个。因此这个模式表示匹配 0 个或 1 个 r。(从另一个角度看,就是说模式 r 是可选的)
* ‘r{2,5}’ r 是一个正则表达式,{2,5} 表示 2 个到 5 个。因此这个模式表示匹配 2 个到 5 个 r。也就是说可以匹配 `rr',`rrr',`rrrr',`rrrrr'四种重复的模式。
* ‘r{2,}’ r 是一个正则表达式,{2,} 省略了第二个数字,表示至少 2 个,不设上限。因此这个模式表示匹配 2 个及以上个 r。也就是说至少可以匹配 `rr',还可以匹配 `rrr',`rrrr'等无限多种重复的模式。
* ‘r{4}’ r 是一个正则表达式,{4} 只有一个数字,表示 4 个。因此这个模式确切地匹配 4 个 r,即 `rrrr'。
(3)名字替换
* ‘{name}’ 这里 name 就是在前面的定义段给出的名字。这个模式将用这个名字的定义来匹配。
(4)平凡(plain)文本串的匹配
* ‘“[xyz]″foo”’ 这个模式用来确切地匹配文本串:[xyz]″foo。注意最外层的单引号所包含的是整个模式表达式,也就是说,当希望匹配字串 [xyz]″foo 时,在书写规则时该字串必须用双引号括住。
(5)特殊单字符的匹配
* ‘x’ 当 x 是一个 `a',`b',`f',`n',`r',`t'或 `v'时,它就解释为 ANSI-C 中的 x。否则就仍然作为一个普通字符 x(一般用于诸如 `*'字符的转义字符)。
* ‘ ’ 匹配一个 NUL 字符(ASCII 码值为 0)。
* ‘123’ 匹配一个字符,其值用八进制表示为 123。
* ‘x2a’ 匹配一个字符,其值用十六进制表示为 2a。
(6)组合模式的匹配
* ‘(r)’ 匹配规则表达式 r,圆括号可以提高其优先级。
* ‘rs’ 匹配规则表达式 r,其后紧跟着表达式 s。这称为联接 (concatenation)。
* ‘r|s’ 或者匹配规则表达式 r,或者匹配表达式 s。
* ‘r/s’ 匹配模式 r,但是要求其后紧跟着模式 s。当需要判断本次匹配是否为 “最长匹配(longest match)时,模式 s 匹配的文本也会被包括进来,但完成判断后开始执行对应的动作(action)之前,这些与模式 s 相配的文本会被返还给输入。所以动作(action)只能看到模式 r 匹配到的文本。这种模式类型叫做尾部上下文(trailing context)。(有些‘r/s’组合是 flex 不能识别的;请参看后面 deficiencies/bugs 一节中的 dangerous trailing context 的内容。)
* ‘^r’ 匹配模式 r,但是这个模式只出现在一行的开始处。也就是说,刚开始扫描时遇到的,或者说在刚扫描完一个换行字符后紧接着遇到的。
* ‘r$’ 匹配模式 r,但是这个模式只在一行的尾部。也就是说,该模式就出现在换行之前。这个模式等价于 r/
。注意,flex 中的换行(newline)的概念,就是 C 编译器中所使用的 n,flex 也采用同样的符号和解释。在 DOS 系统中,可能必须由你自己滤除输入中的 r,或者明确地在模式中写成 r/
来代替 r$。(在 unix 系统中换行是用一个字节
表示的,而 DOS/Windows 则采用两个字节
来表示换行。)
(7)有启动条件(Start Condition)的模式匹配(也有人称为“多重入口”)
* ‘<s>r’ 匹配模式 r,但需要启动条件 s(后面后关于启动条件的讨论)。模式‘<s1,s2,s3>r’是类似的,匹配模式 r,只要有三个启动条件 s1,s2,s3 中的任一个即可。(启动条件简单来说,类似于 C 语言中的条件编译,满足了某个条件才启动这个模式参与匹配,否则不会启动该模式参与匹配。)
* ‘<*>r’ 匹配模式 r,在任何启动条件下都参与匹配,即使是排斥性的条件。
(8)文件尾匹配
* ‘<<EOF>>’ 匹配文件尾,即遇到了文件尾部。一般说来,都应该在模式中加入文件尾模式。这样可以有机会在文件扫描完成时增加一些额外的处理。
* ‘<s1,s2><<EOF>>’ 在有启动条件 s1 或者 s2 的情况下,匹配文件尾部。
例如,可用来检验多行注释是否完整。使用多重入口进入注释匹配中,如果遇到EOF则可报错
一些常见规则的编写(待续)
(1)双引号字符串。
["]({SAFECHAR}|{RESTCHAR}|[_])*["]