C++ 使用boost spirit将语义动作附加到解析器

C++ 使用boost spirit将语义动作附加到解析器,c++,parsing,boost,boost-spirit,boost-spirit-qi,C++,Parsing,Boost,Boost Spirit,Boost Spirit Qi,我试图理解将语义动作“附加”到解析器到底意味着什么,更确切地说,我想理解语义动作绑定到解析器的时间和持续时间 为此,我以以下方式略微修改了boost spirit库的employee.cpp示例: 1°/添加了一个print()函数,其输出仅在调用时跟踪: void print(const struct employee & e) { std::cout << e.surname << "\n"} 尽管我认为我已经将start解析器与语义动作print连接在一起

我试图理解将语义动作“附加”到解析器到底意味着什么,更确切地说,我想理解语义动作绑定到解析器的时间和持续时间

为此,我以以下方式略微修改了boost spirit库的employee.cpp示例:

1°/添加了一个
print()
函数,其输出仅在调用时跟踪:

void print(const struct employee & e) { std::cout << e.surname << "\n"}

尽管我认为我已经将
start
解析器与语义动作
print
连接在一起,但如文档中所示,
print()
函数从未被调用。语义动作需要附加在解析器定义的右端,与解析器在同一定义中出现的次数相同。有人能详细说明一下吗?

从精神上讲,解析器是一个函数对象,在大多数情况下,重载的运算符允许您创建新的解析器,例如
>
等等,它们返回不同的函数对象,而不是修改原始的函数对象

如果您曾经使用过java并遇到过java的不可变字符串,您可以这样认为

当你有这样的表情

rule1 = lit("employee");
rule2 = (rule1 >> lit(",") >> rule1) [ &print ];
所发生的事情是生成一个新的解析器对象并将其分配给变量rule2,并且该解析器对象附加了语义操作

事实上,表达式中的每个运算符都有一个新的临时解析器对象。在构造解析器时,开销只有一次,在解析时这并不重要

当你有

start[&print];
这类似于生成一个立即被丢弃的临时值。它对
start
变量中的值没有副作用。这就是为什么从未调用print

如果不是这样的话,那么语法的制作可能会复杂得多

当您在spirit qi中定义语法时,通常该定义基本上是在语法对象的构造函数中完成的。首先给出规则的原型,指定它们的类型、跳过程序等。然后逐个构造规则。在初始化另一个规则之前,必须确保没有在该规则的定义中使用该规则。但是在初始化之后,就语法而言,它基本上不会改变。(不过,您可以修改调试信息等内容。)

如果所有规则在初始化后都可能发生更改,那么它们都必须相互更新更改,这将更加复杂


您可能会想象,通过让规则存储彼此的引用而不是值,可以避免这种情况。但这意味着指针和动态分配afaik,而且速度会更慢。精神上的一部分要点是它是表达式模板——据我所知,所有这些“指针解引用”都应该在编译时得到解决。

精神上,解析器是一个函数对象,而在大多数情况下,运算符是重载的,以允许您创建新的解析器,例如
等等,返回不同的函数对象,而不是修改原始函数对象

如果您曾经使用过java并遇到过java的不可变字符串,您可以这样认为

当你有这样的表情

rule1 = lit("employee");
rule2 = (rule1 >> lit(",") >> rule1) [ &print ];
所发生的事情是生成一个新的解析器对象并将其分配给变量rule2,并且该解析器对象附加了语义操作

事实上,表达式中的每个运算符都有一个新的临时解析器对象。在构造解析器时,开销只有一次,在解析时这并不重要

当你有

start[&print];
这类似于生成一个立即被丢弃的临时值。它对
start
变量中的值没有副作用。这就是为什么从未调用print

如果不是这样的话,那么语法的制作可能会复杂得多

当您在spirit qi中定义语法时,通常该定义基本上是在语法对象的构造函数中完成的。首先给出规则的原型,指定它们的类型、跳过程序等。然后逐个构造规则。在初始化另一个规则之前,必须确保没有在该规则的定义中使用该规则。但是在初始化之后,就语法而言,它基本上不会改变。(不过,您可以修改调试信息等内容。)

如果所有规则在初始化后都可能发生更改,那么它们都必须相互更新更改,这将更加复杂


您可能会想象,通过让规则存储彼此的引用而不是值,可以避免这种情况。但这意味着指针和动态分配afaik,而且速度会更慢。spirit的一部分要点是它是表达式模板——据我所知,所有这些“指针解引用”都应该在编译时得到解决。

注意:我不是spirit内部的专家,这只是我从阅读文档和使用它中学到的。如果有人能给出比我更深入的解释,或者能解决我答案中的一些紧张问题,我会喜欢读它。注意:我不是spirit内部的专家,这正是我从阅读文档和使用它中学到的。如果有人能给出比我更深入的解释,或者能解决我答案中的一些紧张问题,我会喜欢读它。