boost.sprit用户手册翻译(30):循环

Loops

循环


So far we have introduced a couple of EBNF operators that deal with looping. We have the + positive operator, which matches the preceding symbol one (1) or more times, as well as the Kleene star * which matches the preceding symbol zero (0) or more times.

到目前为止我们已经介绍了一些针对循环的EBNF操作符。我们有+加号,匹配(1)到任意多次,我们也有克林星*,匹配零到任意多次。

Taking this further, we may want to have a generalized loop operator. To some this may seem to be a case of overkill. Yet there are grammars that are impractical and cumbersome, if not impossible, for the basic EBNF iteration syntax to specify. Examples:

更进一步,我们可能想要一个通用的循环操作符。某些人可能认为这是得不偿失的。但如果不悖离EBNF基本规范规范,某些语法可能会显得不切实际而笨拙。例子:

A file name may have a maximum of 255 characters only.

一个最大长度是255的文件名。
A specific bitmap file format has exactly 4096 RGB color information.

一种固定包含有4096 RGB点信息的特定位图格式。
A 32 bit binary string (1..32 1s or 0s).

一个32位二进制串(1..32 个1或0)。

Other than the Kleene star *, the Positive closure +, and the optional !, a more flexible mechanism for looping is provided for by the framework.

除了克林星*、加号+、选择!,框架还提供了更有弹性的循环机制:

Loop Constructs

循环构造

repeat_p (n) [p]

Repeat p exactly n times

重复执行np

repeat_p (n1, n2) [p]

Repeat p at least n1 times and at most n2 times

重复执行p至少n1至多n2

repeat_p (n, more) [p]

Repeat p at least n times, continuing until p fails or the input is consumed

重复执行p至少n次,并一直持续到p不匹配或者输入被完全耗尽。

Using the repeat_p parser, we can now write our examples above:

使用repeat_p分析器,现在我们可以把上面的例子写成:

A file name with a maximum of 255 characters:

一个最大有255个字符的文件名:

    valid_fname_chars = /*..*/;
    filename = repeat_p(1, 255)[valid_fname_chars];

A specific bitmap file format which has exactly 4096 RGB color information:

一种包含4096 RBG点的文件格式:

    uint_parser<unsigned, 16, 6, 6> rgb_p;
    bitmap = repeat_p(4096)[rgb_p];

As for the 32 bit binary string (1..32 1s or 0s), of course we could have easily used the bin_p numeric parser instead. For the sake of demonstration however:

虽然针对32位的二进制串(1...32个1或0),我们可以轻松地使用bin_p数值分析器,但出于示范的目的:

    bin32 = lexeme_d[repeat_p(1, 32)[ch_p('1') | '0']];

Loop parsers are run-time parametric.

循环分析器可以在运行时参数化

The Loop parsers can be dynamic. Consider the parsing of a binary file of Pascal-style length prefixed string, where the first byte determines the length of the incoming string. Here's a sample input:

循环分析器可以是动态的。考虑分析一个Pascal风格的字符串的二进制文件,第一个字节表明了接下来的字符串的长度。这里是输入样本:

11
h
e
l
l
o
_
w
o
r
l
d

This trivial example cannot be practically defined in traditional EBNF. Although some EBNF syntax allow more powerful repetition constructs other than the Kleene star, we are still limited to parsing fixed strings. The nature of EBNF forces the repetition factor to be a constant. On the other hand, Spirit allows the repetition factor to be variable at run time. We could write a grammar that accepts the input string above:

这个微不足道的例子实际上不能用传统的EBNF定义。虽然某些EBNF语法允许比克林星更强大的循环构造,我们仍然只能分析定长串。EBNF的习性要求循环的因数是一个常量。而在另一边,Spirit允许循环因数是一个运行时变量。我们可以写出能接受上面的字符串的语法:

    int c;
    r = anychar_p[assign_a(c)] >> repeat_p(boost::ref(c))[anychar_p];

The expression

表达式

    anychar_p[assign_a(c)]

extracts the first character from the input and puts it in c. What is interesting is that in addition to constants, we can also use variables as parameters to repeat_p, as demonstrated in

从输入中抽取第一个字符并且赋值给c。有趣的是除了常量,我们也可以把变量作为repeat_p的参数,正如下面所示范的:

    repeat_p(boost::ref(c))[anychar_p]

Notice that boost::ref is used to reference the integer c. This usage of repeat_p makes the parser defer the evaluation of the repetition factor until it is actually needed. Continuing our example, since the value 11 is already extracted from the input, repeat_p is is now expected to loop exactly 11 times.

注意boost::ref被用来引用整数c。这种用法使得repeat_p把循环因数的推演推迟到了真正需要时。继续我们的例子,由于值11已经被从输入中抽取,repeat_p现在知道该循环11次了。



Powered by Zoundry

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值