Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Boost.x3:属性在备选方案之间累积_C++_Parsing_Boost Spirit_Boost Spirit X3 - Fatal编程技术网

C++ Boost.x3:属性在备选方案之间累积

C++ Boost.x3:属性在备选方案之间累积,c++,parsing,boost-spirit,boost-spirit-x3,C++,Parsing,Boost Spirit,Boost Spirit X3,我有一个解析器用于解析标识符,比如foo,bar,baz,还有一个解析器用于解析嵌套标识符,比如foo::bar,foo::bar.baz,foo::bar.baz 它们都解析到相同的ast结构中,如下所示: struct identifier : x3::position_tagged{ std::vector <std::string> namespaces; std::vector <std::string> classes; std::st

我有一个解析器用于解析标识符,比如
foo,bar,baz
,还有一个解析器用于解析嵌套标识符,比如
foo::bar,foo::bar.baz,foo::bar.baz
它们都解析到相同的ast结构中,如下所示:

struct identifier : x3::position_tagged{
    std::vector <std::string> namespaces;
    std::vector <std::string> classes;
    std::string identifier;

};
#define VEC_ATR x3::attr(std::vector<std::string>({})) //ugly hack

auto const identifier_def =
                VEC_ATR
                >> VEC_ATR
                >> id_string;
auto const nested_identifier_def =
        x3::lexeme[
                (+(id_string >> "::") >> +(id_string >> ".") > id_string)
                | (+(id_string >> "::") >> VEC_ATR > id_string)
                | (VEC_ATR >> +(id_string >> ".") > id_string)
                | identifier

        ];
对于
嵌套的\u标识符
,如下所示:

struct identifier : x3::position_tagged{
    std::vector <std::string> namespaces;
    std::vector <std::string> classes;
    std::string identifier;

};
#define VEC_ATR x3::attr(std::vector<std::string>({})) //ugly hack

auto const identifier_def =
                VEC_ATR
                >> VEC_ATR
                >> id_string;
auto const nested_identifier_def =
        x3::lexeme[
                (+(id_string >> "::") >> +(id_string >> ".") > id_string)
                | (+(id_string >> "::") >> VEC_ATR > id_string)
                | (VEC_ATR >> +(id_string >> ".") > id_string)
                | identifier

        ];
我知道我为宏感到羞耻。 标识符解析器工作正常,但是
嵌套的_标识符
有一种奇怪的行为 如果我尝试解析像
foo::bar::baz
这样的东西,那么从解析器中掉出来的ast对象拥有所有的名称空间,在本例中
foo
bar
两次位于
名称空间
向量中。 我有一个这种奇怪行为的小例子 .
有人能解释一下为什么会发生这种情况,以及我如何避免这种情况吗?

产生这种行为的原因是,当外部属性的一个分支出现故障时,替代解析器不会自动回滚对外部属性所做的更改

在您的情况下,会发生以下情况:

  • 最初属性是
    [{},{},“]
  • 尝试第一个备选分支
  • id\u string>>::“
    匹配两次并将
    foo
    bar
    添加到第一个向量->
    [{foo,bar},{},”]
  • id\u string>>“
    匹配失败->序列失败->替代分支失败(保持属性不变)
  • 尝试第二个备选分支
  • id\u string>>::“
    匹配两次并将
    foo
    bar
    添加到第一个向量->
    [{foo,bar,foo,bar},{},”]
  • attr(vector({}))
    成功(
    attr
    始终成功),并用空字符串替换空的第二个向量->
    [{foo,bar,foo,bar},{”“},“]
  • id\u字符串
    匹配并将
    baz
    添加到属性->
    [{foo,bar,foo,bar},{'},baz]
  • 第二个备选分支成功
这种情况下的解决方案非常简单,只需使用。不幸的是,该指令尚未在Spirit.X3中实施。一种可能的替代方法是将每个替代分支明确地或通过sehe那样的
x3::rule
放入自己的
。是一个简化的示例,它将
显示为
方法

另一种可能是执行
hold
指令,下面是我的尝试()

#包括
#包括
#包括
名称空间提升{名称空间精神{名称空间x3
{
模板
结构hold_指令:一元语法分析器
{
typedef一元语法分析器基本类型;
静态布尔常数为通过一元数=真;
静态bool const handles\u container=Subject::handles\u container;
hold_指令(主体常量和主体)
:基本类型(主题){}
模板
布尔解析(迭代器&第一,迭代器常量&最后
,上下文常量和上下文,RContext和RContext,属性和属性)常量
{
属性复制(attr);
if(this->subject.parse(first、last、context、rcontext、copy))
{
特征::移动到(复制,属性);
返回true;
}
返回false;
}
};
结构保持根
{
模板
hold_指令
操作员[](主体常量和主体)常量
{
返回{as_解析器(subject)};
}
};
auto const hold=hold_gen{};
}}}

请注意,从Boost1.70开始,@sehe提出的解决方案不再有效(请参阅)


现在唯一的解决办法是重构语法,这样就不需要回滚了。

区分类和名称空间有什么用处?例如,C++中,类是命名空间。你说得对,我希望AST拥有尽可能多的信息。这就是为什么我将后跟一个点的id解析为类向量。也许classes不是最好的名字,但我找不到另一个Quick,我以前从未像使用过这个
。它是如何工作的?非常感谢你的帮助,我没想到会有这样的行为。我想这与解释的地方有关:)哦,很抱歉,我是这么做的fast@Exagon这是一个简化的例子,显示了
作为
的方法。@sehe和jv_ui如果没有你们两个会被搞砸的,谢谢你们一直以来对我的精神帮助