boost.spirit用户手册翻译(28):跳转分析器

The Switch Parser

跳转分析器


Switch parsers may be used to simplify certain alternation constructs. Consider the following code:

跳转分析器可用来简化选择的构建。考虑下面的代码:

    rule<> rule_overall =
            ch_p('a') >> parser_a
        |   ch_p('b') >> parser_b
            // ...
        |   ch_p('n') >> parser_n
        ;

Each of the alternatives are evaluated normally in a sequential manner. This tend to be inefficient, especially for a large number of alternatives. To avoid this inefficiency and to make it possible to write such constructs in a more readable form, Spirit contains the switch_p family of parsers. The switch_p parser allows us to rewrite the previous construct as:

这些选项被线性地依次调用。这是很低效的,尤其在有大量选择的时候。为了避免这种低效并且把这样的代码写成更加可读的形式,Spirit包含了switch_p分析器族。switch_p分析器使得我们可以把上面的构造重写为:

    rule<> rule_overall =
            switch_p
            [
                case_p<'a'>(parser_a),
                case_p<'b'>(parser_b),
                // ...
                case_p<'n'>(parser_n)
            ]
        ;

This switch_p parser takes the next character (or token) from the input stream and tries to match it against the given integral compile time constants supplied as the template parameters to the case_p parsers. If this character matches one of the case_p branches, the associated parser is executed (i.e. if 'a' is matched, parser_a is executed, if 'b' is matched, parser_b is executed and so on) . If no case_p branch matches the next input character, the overall construct does not match at all.

switch_p分析器从输入中取出下一个要分析的字符并且尝试把它与经由case_p分析器模板参数给定的编译期整形常量匹配。如果字符匹配任意一个case_p分支,则相关联的分析器将被执行(比如,如果'a'匹配,parser_a被执行;如果匹配'b',parser_b被执行;如此等等)。如果没有那个case_p分支匹配下一个输入字符,则整个结构都不匹配。

Nabialek trick
Nabialek 戏法

The "Nabialek trick" (from the name of its inventor, Sam Nabialek), can also improve the rule dispatch from linear non-deterministic to deterministic. This is similar to the switch_p parser, yet, can handle grammars where a keyword (operator, etc), instead of a single character or token, precedes a production.
"Nabialek 戏法" (来源于发明者的名字,Sam Nabialek),同样可以把规则分配过程从线性的不确定改进为确定的。这与switch_p类似,但,在语法中它可以先于产生式处理一个关键字(运算符,等等),而不是单独一个字符。

Sometimes it is desireable to add handling of the default case (none of the case_p branches matched). This may be achieved with the help of a default_p branch:

有时我们希望添加对默认情况(没有任何case_p分支匹配)的处理。这可以借由default_p的帮助而完成:

    rule<> rule_overall =
            switch_p
            [
                case_p<'a'>(parser_a),
                case_p<'b'>(parser_b),
                // ...
                case_p<'n'>(parser_n),
                default_p(parser_default)
            ]
        ;

This form chooses the parser_default parser if none of the cases matches the next character from the input stream. Please note that, obviously, only one default_p branch may be added to the switch_p parser construct.

这一形式中如果输入流中的下一个字符没有匹配任何分支则其将选择parser_default分析器。请注意,很明显,只允许在switch_p构造中加入一个default_p分支。

Moreover, it is possible to omit the parentheses and body from the default_p construct, in which case, no additional parser is executed and the overall switch_p construct simply returns a match on any character of the input stream, which does not match any of the case_p branches:

此外,可以把default_p构造的括号和分析体拿掉,在这种情况下,不再执行其他分析器,并且switch_p构造返回一个对输入流中任意字符的匹配,这个字符没有和任何case_p匹配。

    rule<> rule_overall =
            switch_p
            [
                case_p<'a'>(parser_a),
                case_p<'b'>(parser_b),
                // ...
                case_p<'n'>(parser_n),
                default_p
            ]
        ;

There is another form of the switch_p construct. This form allows us to explicitly specify the value to be used for matching against the case_p branches:

这是switch_p构造的另一个形式。这个形式允许我们显式地指定用于匹配case_p的值:

    rule<> rule_overall =
            switch_p(cond)
            [
                case_p<'a'>(parser_a),
                case_p<'b'>(parser_b),
                // ...
                case_p<'n'>(parser_n)
            ]
        ;

where cond is a parser or a nullary function or function object (functor). If it is a parser, then it is tried and its return value is used to match against the case_p branches. If it is a nullary function or functor, then its return value will be used.

这里cond是一个分析器或者无参函数或者函数对象(仿函数)。如果它是分析器,那么它将被测试并且测试返回值将用来与case_p分支匹配。如果是无参函数或者仿函数,那么将直接使用它的返回值。

Please note that during its compilation, the switch_p construct is transformed into a real C++ switch statement. This makes the runtime execution very efficient.

请注意,在编译期,switch_p构造被转换成真正的C++的switch语句。这使得运行时的效率相当高。

BOOST_SPIRIT_SWITCH_CASE_LIMIT

The number of possible case_p/default_p branches is limited by the Spirit compile time constant BOOST_SPIRIT_SWITCH_CASE_LIMIT, which defaults to 3. There is no theoretical upper limit for this constant, but most compilers won't allow you to specify a very large number.

case_p/default_p分支的最大数目受限于Spirit编译期常量BOOST_SPIRIT_SWITCH_CASE_LIMIT,其默认值为3。这个常量理论上没有限制,但大多数编译器都不会允许你指定很大的数目。

Example:

例子:

// Define these before including switch.hpp
#define BOOST_SPIRIT_SWITCH_CASE_LIMIT 10





Powered by Zoundry

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值