c++ - 在精神气中解析嵌套层次结构 - 语法不正确

标签 c++ parsing boost-spirit boost-spirit-qi

我精神不振::气急,需要一些帮助。我正在尝试解析以下形式的短语:

( wheels=4 & chassis=metal & engine=( cylinders=8 & volume=6209 ) )

...进入嵌套结构:

class dict : public std::map<std::string, boost::variant<dict, std::string>>

...其中 car_dict["wheels"] 返回“4”,car_dict[“engine”] 返回另一个字典,其中 engine_dict[“cylinders”] 返回“8”。

这是我的语法,我希望在这方面有丰富经验的人能指出我哪里出错了。

struct qi_car_grammar : qi::grammar<std::string::const_iterator, dict()>
{
    qi::rule<std::string::const_iterator, dict()> car_dict;
    qi::rule<std::string::const_iterator, std::string()> car_key;
    qi::rule<std::string::const_iterator, boost::variant<dict, std::string>()> car_variant_value;

    qi_car_grammar()
        : qi_car_grammar::base_type(car_dict)
    {
        // RULES
        car_key %= *(qi::lit(' ')) >> *(~qi::lit('='));

        car_variant_value %= car_dict | *(~qi::char_("&)"));

        car_dict = qi::lit('(')
            >> car_key >> qi::lit('=') >> car_variant_value
            >> *(qi::lit('&') >> car_key >> qi::lit('=') >> car_variant_value)
            >> qi::lit(')');
    }
}

感谢任何帮助。在任何人提出建议之前,不,我对要解析的结构没有太多控制权。

最佳答案

嗯。我刚刚完成了一般清理通行证¹。

你们已经很接近了。

您可能只是错过了 boost/fusion/adapted/std_pair.hpp header ,这是将已解析的元组转换为 std::pair<K,V> 所必需的自动地。

这是工作示例(我花了大部分时间创建 dict pretty-print ......):

Live On Coliru

#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/include/qi.hpp>
#include <map>

namespace qi = boost::spirit::qi;

class dict : public std::map<std::string, boost::variant<dict, std::string>>
{
};

template <typename It = std::string::const_iterator, typename Skipper = qi::space_type>
struct qi_car_grammar : qi::grammar<It, dict(), Skipper>
{
    qi_car_grammar()
        : qi_car_grammar::base_type(car_dict)
    {
        // RULES
        car_key   = *~qi::char_("=");
        car_value = *~qi::char_("&)");

        car_variant_value = car_dict | car_value;

        car_dict = '(' >> (car_key >> '=' >> car_variant_value) % '&' >> ')';
    }

  private:
    qi::rule<It, dict(), Skipper> car_dict;
    qi::rule<It, std::string()> car_key, car_value;
    qi::rule<It, boost::variant<dict, std::string>(), Skipper> car_variant_value;
};

// for debug
static inline std::ostream& operator<<(std::ostream& os, dict const& d) {
    struct vis {
        using result_type = void;
        std::ostream& _os;
        std::string indent;

        void operator()(std::string const& s) const { _os << s; }
        void operator()(dict const& d) const { 
            _os << "(\n";
            for (auto& entry: d) {
                _os << indent << "    " << entry.first << " = ";
                boost::apply_visitor(vis{_os, indent+"    "}, entry.second);
                _os << "\n";
            }
            _os << indent << ")\n";
        }
    } v { os, "" };

    v(d);
    return os;
}

int main()
{
    std::string const input = "( wheels=4 & chassis=metal & engine=( cylinders=8 & volume=6209 ) )";

    dict parsed;
    qi_car_grammar<> g;

    auto f = input.begin(), l = input.end();
    bool ok = qi::phrase_parse(f, l, g, qi::space, parsed);

    if (ok)
        std::cout << "Parsed: " << parsed << "\n";
    else
        std::cout << "Parsed failed\n";

    if (f!=l)
        std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}

打印:

Parsed: (
    chassis = metal 
    engine = (
        cylinders = 8 
        volume = 6209 
    )

    wheels = 4 
)

¹(就像我在阅读代码示例时经常做的那样,它有助于我的理解)

关于c++ - 在精神气中解析嵌套层次结构 - 语法不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32889154/

相关文章:

尝试插入 map 时出现 C++ 编译问题

python - 使用 Python,我如何评估压缩前缀符号形式的表达式?

c++ - boost spirit qi解析器发布失败,调试通过

c++ - Boost.Spirit.Qi 在将规则分配给包括自身在内的序列时崩溃

c++ - 使用不同的符号表重新计算 Boost Spirit 解析的属性的最有效方法是什么?

c++ - 汇编中的位填充未按预期工作

c++ - 如何覆盖自定义委托(delegate)类的 'paint'函数来绘制QSpinBox

c++ - 从用户输入创建多个类实例

java - java中的 boolean 表达式解析器

php - 删除从最后一次出现的特定字符序列开始的所有字符