c++ - 提振 spirit ,为什么需要 as<> 指令? (又名帮助我理解属性兼容性规则)

标签 c++ boost boost-spirit

此代码按预期编译和工作;像“{a;b}”这样的输入被解析并存储在自定义类中

#include <vector>
#include <string>
#include <iostream>
#include <boost/spirit/include/qi.hpp>

namespace t {
    using std::vector;
    using std::string;
    namespace qi = boost::spirit::qi;

    struct Block {
        Block() = default;
        Block(vector<string> const& s) : value(s) {}
        vector<string> value;
    };

    template <typename Iterator, typename Skipper=qi::space_type>
    struct G1 : qi::grammar<Iterator, Block(), Skipper> {

        template <typename T>
        using rule = qi::rule<Iterator, T, Skipper>;

        rule<Block()> start;
        G1() : G1::base_type(start, "G1") {
            start = qi::as<vector<string>>()[
                qi::lit('{')
                >> *(+(qi::char_ - ';') >> ';')
                >> '}'
            ];
        }
    };

    Block parse(string const input) {
        G1<string::const_iterator> g;
        Block result;
        phrase_parse(begin(input), end(input), g, qi::standard::space, result);
        return result;
    }
};

int main() {
    using namespace std;
    auto r = t::parse("{a;b;}");
    for (auto& s : r.value) {
        cout << s << endl;
    }
}

我不明白的是为什么需要 as<> 指令;从文档中我可以推断出,原始解析器的合成属性应该已经是一个字符串 vector 。

我读过 this article关于属性传播和属性兼容性,但我错过了大局;当(不)使用 as 指令时会发生什么?

最佳答案

否则

*(+(qi::char_ - ';') >> ';')

只会暴露一个 std::vector<char> (每个 kleene-+ 都会附加到同一个属性中)。根据经验,kleene-operators 总是直接推回引用的属性,这也意味着它期望该属性是容器类型(boost::spirit::traits::container_value<> 特征用于检测重复解析器表达式的属性应该转换什么到)。

在这种情况下,您可能会发现与 qi::as_string 的 fusion 适应更优雅: Live On Coliru

struct Block {
    vector<string> value;
};

BOOST_FUSION_ADAPT_STRUCT(t::Block,(std::vector<std::string>,value))
// ...

start = 
    qi::lit('{')
    >> *qi::as_string [ +(qi::char_ - ';') >> ';' ]
    >> '}'
;

有了这个,小心

关于c++ - 提振 spirit ,为什么需要 as<> 指令? (又名帮助我理解属性兼容性规则),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24440753/

相关文章:

c++ - 我无法在 Boost Spirit 的词法分析器功能中获得语义操作来编译

c++ - 为什么我不能增加枚举类型的变量?

c++ - 具有 C++ 性能问题/滞后峰值的 Lua

c++ - 如何在 RHEL 上为新的 Boost 版本构建/部署 RPM?

c++ - 使用 boost::spirit 的简单表达式

c++ - 如何为用户提供针对给定 boost::spirit 语法的高级自动完成建议?

c++ - 辅助函数 : static in cpp or define as static helper class method

c++ - G++ & Clang++ - 命名空间 std _GLIBCXX_VISIBILITY(默认)

c++ - 在磁盘上使用循环缓冲区

c++ - 为什么 regex_match 与我的正则表达式不匹配?