c++ - Spirit X3组合属性

标签 c++ boost-spirit

我正在尝试编写精神规则,但我无法弄清楚这个新规则的属性是什么。

以下代码按我预期的方式工作。

#include <iostream>
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/tuple.hpp>
namespace ast{
    struct Record{
       int id;
       std::string name;
    };
    struct Document{
        Record rec;
        Record rec2;
        //std::vector<Record> rec;
        std::string name;
    };
    using boost::fusion::operator<<;
}
BOOST_FUSION_ADAPT_STRUCT(ast::Record,
    name, id
)
BOOST_FUSION_ADAPT_STRUCT(ast::Document,
    rec, rec2, 
    //rec,
    name
)
namespace parser{
    namespace x3 = boost::spirit::x3;
    namespace ascii = boost::spirit::x3::ascii;
    using x3::lit;
    using x3::int_;
    using ascii::char_;

    const auto identifier = +char_("a-z");
    const x3::rule<class record, ast::Record> record = "record";
    const auto record_def = lit("record") >> identifier >> lit("{") >> int_ >> lit("}");
    const x3::rule<class document, ast::Document> document = "document";
    const auto document_def =
         record >> record
         //+record // This should generate a sequence
         >> identifier
         ;
    BOOST_SPIRIT_DEFINE(document, record);
}

namespace{
    constexpr char g_input[] = R"input(
                record foo{42}
                record bar{73}
                foobar
                )input";
}

int main(){
    using boost::spirit::x3::ascii::space;
    std::string str = g_input;
    ast::Document unit;
    bool r = phrase_parse(str.begin(), str.end(), parser::document, space, unit);
    std::cout << "Got: " << unit << "\n";
    return 0;
}

但是当我更改规则以解析多个记录(而不是恰好 2 个)时,我希望它有一个 std::vector<Record>作为一个属性。但是我得到的只是一个很长的编译器错误,对我没有太大帮助。 有人可以指出我做错了什么以便正确组合属性吗?

最佳答案

我认为它没有编译的全部原因是因为你试图打印结果......和std::vector<Record>不知道如何流式传输:

namespace ast {
    using boost::fusion::operator<<;
    static inline std::ostream& operator<<(std::ostream& os, std::vector<Record> const& rs) {
        os << "{ ";
        for (auto& r : rs) os << r << " ";
        return os << "}";
    }
}

一些注意事项:

  • 在绝对需要的地方添加词素 (!)
  • 简化(不需要 BOOST_SPIRIT_DEFINE 除非递归规则/单独的 TU)
  • 删除冗余 lit

我到了

Live On Coliru

#include <iostream>
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>

namespace ast {
    struct Record{
       int id;
       std::string name;
    };
    struct Document{
        std::vector<Record> rec;
        std::string name;
    };
}

BOOST_FUSION_ADAPT_STRUCT(ast::Record, name, id)
BOOST_FUSION_ADAPT_STRUCT(ast::Document, rec, name)

namespace ast {
    using boost::fusion::operator<<;
    static inline std::ostream& operator<<(std::ostream& os, std::vector<Record> const& rs) {
        os << "{ ";
        for (auto& r : rs) os << r << " ";
        return os << "}";
    }
}

namespace parser {
    namespace x3    = boost::spirit::x3;
    namespace ascii = x3::ascii;

    const auto identifier = x3::lexeme[+x3::char_("a-z")];
    const auto record     = x3::rule<class record, ast::Record> {"record"}
                          = x3::lexeme["record"] >> identifier >> "{" >> x3::int_ >> "}";
    const auto document   = x3::rule<class document, ast::Document> {"document"}
                          = +record
                          >> identifier
                          ;
}

int main(){
    std::string const str =  "record foo{42} record bar{73} foobar";
    auto f = str.begin(), l = str.end();

    ast::Document unit;
    if (phrase_parse(f, l, parser::document, parser::ascii::space, unit)) {
        std::cout << "Got: " << unit << "\n";
    } else {
        std::cout << "Parse failed\n";
    }

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

打印

Got: ({ (foo 42) (bar 73) } foobar)

关于c++ - Spirit X3组合属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47697146/

相关文章:

c++ - 是否可以使用 vs 2012 ultimate 在 Visual C++ 中创建窗口电话应用程序?

c++ - .idl 导入接口(interface)中的 coclass 在别处定义?

boost-spirit - 我如何使用 qi::symbols 解析器来匹配来自使用 no_case 的精神词法分析器的标记?

c++ - 使用类模板范围中的枚举而不指定模板参数

c++ - 使用xcode的c++应用程序中文件的相对路径

c++ - boostspirit编译错误

c++ - 将 Boost.Spirit.Qi 与自定义词法分析器结合使用

c++ - 如何在 boost::spirit::qi 中将某些语义 Action 排除在 AST 之外

c++ - 如何获取全局 Windows I/O 统计信息?

c++ - 如何使用 Boost Spirit 提取修剪后的文本?