boost.spirit用户手册翻译(25):可储存规则

22 篇文章 0 订阅
 

Storable Rules

可保存规则


 

The rule is a weird C++ citizen, unlike any other C++ object. It does not have the proper copy and assignment semantics and cannot be stored and passed around by value. You cannot store rules in STL containers (vector, stack, etc) for later use and you cannot pass and return rules to and from functions by value.

规则是一个怪异的C++公民,和其他的C++对象不像。它没有恰当的拷贝和赋值语义,也不能被以值来传递和保存。你没法把规则保存在STL容器(比如vector、stack等)以在随后使用,也不能把规则以值语义从函数中返回。

EBNF is primarily declarative. Like in functional programming, an EBNF grammar is a static recipe and there's no notion of do this then that. However, in Spirit, we managed to coax imperative C++ to take in declarative EBNF. Hah! Fun!... We did that by masquerading the C++ assignment operator to mimic EBNF's ::=. To do that, we gave the rule class' assignment operator and copy constructor a different meaning and semantics. The downside is that doing so made the rule unlike any other C++ object. You can't copy it. You can't assign it.

EBNF本质上是声明式的。类似于函数式编程,一个EBNF语法就是一个静态的配方,而且也不需要除此以外的其他。然而,在Spirit中,我们要把命令式的C++和声明式的EBNF拧到一块。哈!有趣!……我们通过把C++的等号伪装起来模仿EBNF的::=来干这个事情,我们给予了规则类的赋值符以不同于拷贝构造函数的含义和语义。这样的缺点是使用起来与其他C++对象不同。你不能把它拷贝,你不能给他赋值。

We want to have the dynamic nature of C++ to our advantage. We've seen dynamic Spirit in action here and there. There are indeed some interesting applications of dynamic parsers using Spirit. Yet, we will not fully utilize the power of dynamic parsing, unless we have a rule that behaves like any other good C++ object. With such a beast, we can write full parsers that's defined at run time, as opposed to compile time.

我们希望拥有C++的动态行为以方便我们。我们已经在这里和那里见过动态的Spirit。的确有些使用Spirit的动态分析的应用。但,我们无法拥有动态分析的全部力量,除非我们有一个和其他C++对象有相似行为的规则。有了这个野兽,我们可以把整个分析器写成运行时定义,同时又在编译时压缩的。

We now have dynamic rules: stored_rules. Basically they are rules with perfect C++ assignment/copy-constructor semantics. This means that stored_rules can be stored in containers and/or dynamically created at run-time.

现在我们有了动态规则:stored_rules。基本上它们就是拥有完美的C++赋值/拷贝语义的规则。这意味着stored_rules可以保存在容器中且/或在运行时动态创建。

template< typename ScannerT = scanner<>, typename ContextT = parser_context<>, typename TagT = parser_address_tag> class stored_rule;

The interface is exactly the same as with the rule class (see the section on rules for more information regarding the API). The only difference is with the copy and assignment semantics. Now, with stored_rules, we can dynamically and algorithmically define our rules. Here are some samples...


接口与规则类完全相同( 规则一章中有关于API的更多信息)。现在,有了 stored_rule,我们可以动态而系统的定义我们的规则了。下面是一些例子……

Say I want to dynamically create a rule for:

比如我想动态创建如下规则:

    start = *(a | b | c);

I can write it dynamically step-by-step:

我可以以动态的形式一步步写成:

    stored_rule<>  start;

    start = a;
    start = start.copy() | b;
    start = start.copy() | c;
    start = *(start.copy());

Later, I changed my mind and want to redefine it (again dynamically) as:

之后,我改变主意,想把它重定义(动态赋值)为:

    start = (a | b) >> (start | b);

I write:

我写成:

    start = b;
    start = a | start.copy();
    start = start.copy() >> (start | b);

Notice the statement:

注意语句:

    start = start.copy() | b;

Why is start.copy() required? Well, because like rules, stored rules are still embedded by reference when found in the RHS (one reason is to avoid cyclic-shared-pointers). If we write:

为什么需要start.copy()?因为类似于规则,可储存规则在等式右边时依然是基于引用嵌入的(一个原因是避免环指针)。如果我们写:

    start = start | b;

We have left-recursion! Copying copy of start avoids self referencing. What we are doing is making a copy of start, ORing it with b, then destructively assigning the result back to start.

那我们就有左递归了!拷贝strat的副本避免了自我引用。我们所作的是创建一个start的拷贝,把它和b或起来,再把结果破坏性地复制回start(即start的原有值被取代)。

 


Powered by Zoundry

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值