typename TagT = parser_address_tag> class rule; 模版参数:
ScannerT 扫描器类型 scanner<>
ContextT 分析器上下文 parser_context<> TagT 规则标签 parser_address_tag<>
在1.8.0这个版本中, ScannerT,ContextT和TagT可以以任意顺序排列 。如果某个模板参数缺失,则适用默认的参数。
在1.8.0中,规则可以使用一个或者多个扫描器类。引入多扫描器是为了支持语法层面和词法层面的不同分析操作。
typedef scanner_list
assert( parse(\
为了支持多扫描器,必须在boost头文件引用前定义宏
# define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 3 // 多扫描器最大限制
当规则在EBNF表达式右边引用时,表达式使用的是规则的引用。规则是C++的一个特例,它没有拷贝和赋值语义,不能以值进行存储和引用。必须显示调用copy()函数来实现拷贝操作。规则是动态的,对一个规则进行二次赋值会引起它的析构和重定义。
规则本质上来说是一个动态分析器。
为了识别,可以给规则加上标签(Tag),尤其是在分析树和AST树中要判断是那条规则产生该结点时。每条规则都有一个类型为parser_id的ID,通过成员函数id()获取。
parser_address_tag 使用rule的内存地址作为rule tag parser_tag
5.4 空串 (Epsilon)
epsilon_p , eps_p Epsilon空串 空串用途: 1. 零长度匹配
通常用于无条件触发一个语义动作。如:
R = A | B | C | eps_p[ error ] ; // error if A, B or C fails to match 2. 语义断言 Semantic Predicate
语义断言允许你在语法的任意点上挂接函数,eps_p接受零元函数对象,该函数对象通常用于解决语法二义性的一个测试。如果函数对象的结果为false,则分析失败。 eps_p(f) >> rest; // 函数f触发调用,检测一个符号是否在符号表中,如果返回true,则继续分析
3. 语法断言(句意断言) Syntactic Predicate
类似于语义断言,语法断言在推演后续产生式之前检测语法断言。这时eps_p的输入为条件分析器,如:
eps_p(p) >> rest ; // 分析器p进行语法检测,如果输入匹配p,则进行后续推演。eps_p空串不消耗任何输入。
eps_p( '0' ) >> oct_p ; // 匹配前导'0'的八进制数值,如果发现一个'0',epsilon_p将报告一个零长度的成功匹配。 4. 基本类型参数
eps_p接受c++内置类型作为参数。如char, wchar_t, char *, wchar *。 5. 抑制语义动作 Inhibiting Semantic Actions
在语法断言中,直接或间接作用于条件分析器的语义动作都不会调用,但是作用于eps_p的语义动作总是被调用(因为eps_p总是返回true)。如:
eps_p( p[f] ) // f not called eps_p( p ) [f] // f is called eps_p[f] // f is called
作为条件分析器要求必须不具有副作用(语义动作)。条件分析器的作用是通过 前向匹配(forward-match) 输入来消除语法二义性。二义性和语义动作不能够很好的结合使用,在一个二义性文法中,会产生回溯。当回溯产生时,已触发的语义动作无法回溯。 6. 反操作符 Negation
~eps_p ~~eps_p 对 结果 进行取反操作。
5.5 Directives ( 指示器)
形式: directive[expression]
Spirit预定义少量directives,框架使用者可以自定义directive. Directive控制expression的行为。 lexeme_d
功能:禁用空格忽略。
在短语级别,分析器将忽略空格和注释。当我们想在字符界别而不是短语级别操作时,使用lexeme_d。将分析器封闭在lexeme_d[]中初始分析器在字符级别工作。如: integer = lexeme_d[ !(ch_p('+') | '-') >> +digit ];
lexeme _d指定使得封闭的分析器处于字符界别进行操作。如果没有使用lexeme_d的话,rule( !(ch_p('+') | '-') >> +digit ) 将会把\分析为\,允许数字之间出现的不正确的空格。 as_lower_d
功能:忽略大小写,将所有字符转换为小写字符处理。 例子: as_lower_d[ \匹配 begin, BEGIN ....。
注意:as_lower_d只是将输入转换为小写字符处理,它不能够将[]中的字符转换为小写字符处理。如果as_lower_d[ ]中出现大写字符,则会出现分析错误。如:as_lower_d[ 'X' ],该分析器永远无法匹配成功,因为分析器想要匹配大写字符'X',但是as_lower_d不支持这种功能。 no_actions_d
功能:禁止语义动作的触发。
directive工作原理:
lexeme_d,as_lower_d和no_actions_d的原理主要时通过将 扫描器策略(Sanner Policy) 组合起来实现不同的功能。规则rule属于一个特殊的分析器(更精确的说是一个或多个分析器),如果将规则放到lexeme_d,as_lower_d或no_actions_d当中,除非你将扫描器和规则关联起来,否则编译器会出现扫描器不匹配错误。( why?) longest_d
功能:匹配所有可选项,获取一个最长匹配。(仅对于或运算符)
或运算符在spirit框架当中采取短路匹配方式来进行匹配。也就是说对于规则: rule<> r1 = p1 | p2 | p3 ... | pn, 对于i <= n,如果对于任意的j < i,pj都无法匹配输入,但是pi匹配输入,那么后续的分析器就无需进行匹配。虽然spirit或运算符的短路行为对于具有优先情况的匹配操作可能是非常好的, 但是也存在这样一种情况, 如:
rule<> r2 = real_p | int_p;
对于输入为\由于整数本身也是实数, 因此该输入永远只匹配real_p,不会匹配int_p;但是如果将规则转变为:
rule<> r2 = int_p | real_p ;
对于输入为\,这时输入永远只匹配int_p,不会匹配real_p。但如果输入为: \,这种情况下由于或运算符的短路行为,只会用int_p来匹配输入的前部分\(\分隔)。这并不是我们想要的结果,通过使用longest_d将规则封装起来,这样就会用所有的选择项来匹配输入并选取一个最长匹配项real_p。 shortest_d
功能:与longest_d相反
limit_d ,min_limit_d和max_limit_d 功能:限定分析器结果范围(对于数值分析器)
虽然数值分析器可以通过模版参数限定数值位数,但是要限定结果范围只能通过limit_d,min_limit_d和max_limit_d来限定。使用方法如下:
limit_d(min, max)[expression]
min_limit_d(min) [expression] min_limit_d(1900u)[uint_p] >= 1900u
max_limit_d(max) [expression] max_limit_d(1900u)[uint_p] <= 1900u
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库boost spirit介绍(3)在线全文阅读。
相关推荐: