分类: C/C++
2011-08-04 11:36:51
R1 + R2 表示顺序匹配:匹配 R1 成功后继续匹配 R2。编译原理中一般以 R1 R2 表示(很遗憾,C++没有operator空格)。这应该是使用最多的文法了。
例如:要匹配html标签开始,也就是
R1 | R2 表示如果 R1 匹配不成功,则匹配 R2。两者只要一个匹配成功就表示成功。
例如:要匹配C++中的类/结构体声明,也就是:
class/struct ClassName;
我们可以这样写:
(str("class") | str("struct")) + ws() + c_symbol() + skipws() + ';'
这里,ws()表示匹配>=1个空白字符,skipws()表示匹配>=0个空白字符。class/struct关键字和类名之间空白 是必须的,所以用ws(),而类名和;之间空白不是必须的,故而用skipws()。另外,str("class") | str("struct")可以缩写为str("class", "struct"),不过这不是我们要讨论的话题。
+R 表示匹配规则 R 1次以上。编译原理中习惯以 R+ 表示。
例如:要匹配一个无符号整数,我们这样写: +digit()。
当然,对于这个例子,你其实不需要用+,因为我们已经提供了 u_integer() 规则了。
!R 表示匹配规则 R 1次或0次。编译原理中习惯以 R? 表示,不过C++没有operator?,很遗憾。
例如:要匹配一个带符号整数,我们这样写:!(ch('+') | ch('-')) + u_integer()。
同str一样,ch('+') | ch('-') 可缩写为 ch('+', '-')。故此本例可简写为 !ch('+', '-') + u_integer()。
当然,对于这个例子,你其实不需要用!,因为我们已经提供了 integer() 规则了。
*R 表示匹配规则 R 0次以上。编译原理中习惯以 R* 表示。
R1 % R2 匹配一个列表。它等价于 R1 + *(R2 + R1)。
例如:要匹配一个空格分割的浮点数列表,如“1.2 1.3 2.4 3 23.01",你只需要用 real() % ws() 即可。这里用了 ws(),这就允许中间的空白可以是一个或多个。如果只允许一个空格,那么用 real() % ' ' 即可。
~R 表示匹配一个非R规则的字符。R规则要求是匹配单字符的规则。例如 ~(ch('+') | ch('-')) 表示匹配任一个非+或-的字符。
未完待续。。。
ch(Char) 规则用于匹配一个字符。例如ch('<')表示匹配单个字符'<'。当 ch(Char) 规则与其他规则连用时,可简写为 Char。
例如,我们前面介绍了匹配html标签开始,也就是
它只是 ch(Char1) | ch(Char2) 和 ch(Char1) | ch(Char2) | ch(Char3) 的简写。
ch_any() 规则匹配任意一个字符。除非当前已经到达文档结尾,否则该规则总返回成功。
ch_range
peek(Char) 规则用于向前看一个字符(但并不移动匹配的当前指针)。例如peek('<')表示要求文档当前位置的字符必须为'<'。
peek规则也允许传入任意的匹配单字符的规则。例如,peek(~ch('+', '-')) 要求文档当前位置的字符必须为非'+'或'-'的字符。 peek(Char1, Char2) 是 peek(ch(Char1) | ch(Char2)) 的缩写。peek(Char1, Char2, Char3) 类似。
str(String) 规则用于匹配一个常量字符串。你仍然可以理解为是 ch(Char) 的组合。例如 str("class") 等价于 ch('c') + ch('l') + ch('a') + ch('s') + ch('s')。同ch(Char)类似,当str(String)规则与其他规则连用时,可简写为 String。
find
find规则同样可以用ch规则实现。例如,find
find
以上介绍的ch, peek, str, find操作是TPL的基础规则。有了他们,你可以做出非常复杂的匹配模式。这里举一些例子进行说明。
匹配一个整数。它等价于: !ch('+', '-') + (+ch_range<'0', '9'>())。
匹配一个C符号(变量名)。它等价于:(ch_range<'a', 'z'>() | ch_range<'A', 'Z'>() | '_') + *(ch_range<'a', 'z'>() | ch_range<'A', 'Z'>() | ch_range<'0', '9'>() | '_')。
我们提供了很多很多的现成的规则,而且它们确确实实是这些基础规则的组合得到的,而不是通过实现一个自定义的匹配函数完成。虽然所有的匹配规则你都可以通过写匹配函数完成,但是那样的话就放弃了TPL最强悍的武器了。
目前已经提供的组合规则如下(不断更新中):
non_eol_space() | 匹配一个非行结束的空白字符。 |
space() | 匹配一个空白字符。 |
alpha() | 匹配一个字母。即[A-Za-z]。 |
lower() | 匹配一个小写字母。即[a-z]。 |
upper() | 匹配一个大写字母。即[A-Z]。 |
digit() | 匹配一个10进制数字。即[0-9]。 |
xdigit() | 匹配一个16进制数字。即[0-9a-fA-F]。 |
oct_digit() | 匹配一个8进制数字。即[0-7]。 |
bin_digit() | 匹配一个2进制数字。即[01]。 |
ws() | 匹配>=1个空白字符。 |
skipws() | 匹配>=0个空白字符。 |
non_eol_ws() | 匹配>=1个非行结束的空白字符。 |
skip_non_eol_ws() | 匹配>=0个非行结束的空白字符。 |
strict_eol() | 匹配一个行结束。行结束不一定是单字符的。可以是/r/n, /r, /n等情况。 |
eol() | 匹配一个行结束或文档结束。即 strict_eol() | eos()。 |
xml_symbol() | 匹配一个XML的符号。 |
u_integer() | 匹配一个无符号整数。 |
hex_integer() | 匹配一个16进制无符号整数。注意,它并不匹配C/C++中的16进制数0xXXXX的前缀0x。如果你希望这样,应该用c_hex_integer() 而不是 hex_integer()。 |
oct_integer() | 匹配一个8进制无符号整数。 |
bin_integer() | 匹配一个2进制无符号整数。 |
integer() | 匹配一个有符号整数。 |
u_strict_real() | 匹配一个无符号的实数/浮点数。该实数是严格的浮点数,不能是整数。 |
strict_real() | 匹配一个有符号的实数/浮点数。该实数是严格的浮点数,不能是整数。 |
u_real() | 匹配一个无符号的实数/浮点数。即 u_strict_real() | u_integer()。 |
real() | 匹配一个有符号的实数/浮点数。即 strict_real() | integer()。 |
t_year() | 匹配年份。即yyyy或者yy。其中y是[0-9]。 |
t_month() | 匹配月份。即mm或者m。其中m是[0-9]。目前我们并不限定其取值范围必须为1~12。但不排除以后可能会这样去限制。 |
t_day() | 匹配天。 |
t_hour() | 匹配小时。 |
t_minute() | 匹配分钟。 |
t_second() | 匹配秒。 |
c_symbol() | 匹配一个C/C++的符号。即 [A-Za-z_][A-Za-z0-9_]*。 |
cpp_single_line_comment |
匹配C++的//风格的注释。bEatEol为true时匹配行结束符,否则保留行结束符。和前面的find规则类似,默认bEatEol为false。 |
c_comment() | 匹配C的/* … */风格的注释。 |
cpp_comment |
匹配C/C++的注释。即c_comment() | cpp_single_line_comment |
c_skip() | 忽略空白或C风格注释。即 *(ws() | c_comment())。 |
c_skip_non_eol() | 忽略非行结束的空白字符或注释。即 *(non_eol_ws() | c_comment())。该规则适合于C预处理指令的匹配。 |
cpp_skip() | 忽略空白或C/C++注释。即 *(ws() | cpp_comment |
c_string() | 匹配C/C++的字符串常量。即 "…"。注意并不包括L"…"中的L。 |
c_char() | 匹配C/C++的字符常量。即 '…'。注意并不包括 L'…'中的L。 |
c_string_or_char() | 即c_string() | c_char()。 |
c_hex_integer() | C/C++中的16进制数常量。即0xXXXX。注意并不包括0xXXXXL中的L。 |
c_oct_integer() | C/C++中的8进制数常量。即0XXXX。注意并不包括0XXXXL中的L。 |
c_u_integer() | C/C++中的无符号整数。即 c_hex_integer() | c_oct_integer() | u_integer()。 |
c_integer() | C/C++中的带符号整数。即 c_hex_integer() | c_oct_integer() | integer()。 |
html_space() | 匹配一个HTML中的空白字符。 |
html_ws() | 即+html_space()。 |
html_skipws() | 即*html_space()。 |
html_symbol() | 匹配一个HTML的符号。 |
html_value() | 匹配HTML的属性值。 |
html_property() | 匹配HTML的属性。包括名和值的对。注意值是可选的,HTML中可能出现一个属性有名无值。如 这样的标签。 |
html_u_integer() | 匹配HTML的无符号整数。即#xXXXX(16进制)或者 #XXXX(10进制)。 |
html_entity() | 匹配HTML的一个实体。如< 等命名实体。注意它也可以匹配非命名的实体。如? 等。 |
html_comment() | 匹配一个HTML的注释。即 >。 |
html_uncommented_script_code() | 未被注释的script代码。 |
html_commented_script_code() | 被注释的script代码。注意不包含注释开始和结尾>。 |
html_script_code() | 匹配一个HTML的script段。即:html_uncommented_script_code() | "" + html_commented_script_code() + ">"。 |
html_script_codes() | 匹配多个HTML的script段。即 *html_script_code()。 |
关于 html script code。有些复杂的东西需要解释。看这样一段HTML代码:
这里包含了两段html script code。一段是未注释的,一段是被注释的。要匹配这段文本,可以用""。注意我们用的是html_script_codes(),不是html_script_code()。也就是说,