簡體   English   中英

提升精神x3:解析結構

[英]Boost Spirit x3: parse into structs

來自Boost Spirit X3教程:

首先,讓我們創建一個代表員工的結構:

 namespace client { namespace ast { struct employee { int age; std::string surname; std::string forename; double salary; }; }} 

然后,我們需要告訴Boost.Fusion我們的員工結構,使其成為語法可以利用的一流融合公民。

 BOOST_FUSION_ADAPT_STRUCT( client::ast::employee, (int, age) (std::string, surname) (std::string, forename) (double, salary) )` 

[...]在fusion的視圖中,結構只是元組的一種形式。 您可以將任何結構調整為完全符合的融合元組。 [...]應用我們的折疊規則,RHS的屬性為: fusion::vector<int, std::string, std::string, double> struct employee IS與fusion :: vector兼容。 因此,start的RHS在其工作時就地使用start的屬性(struct employee)。

如果我很好理解,這個邏輯很大程度上依賴於屬性的順序。

現在,我處在一種需要解析類似問題的情況

Layer "L1" {
    number = 23
    color = green
    visible = true
}

成為一個結構

struct LayerInfo
{
    std::string layerName;
    int layerNumber;
    std::string color;
    bool visible;
}

問題是, 層屬性的順序可能會改變 ,這與上面所述的邏輯相反。

解析為這樣的結構的正確方法是什么? 我是否需要使用語義操作?

我喜歡@llonesmiz在評論中的做法。

盡管如此,我還是“不得不”嘗試使用功能性合成的X3。 這是解析和傳播值的方法的草圖。

缺少對財產存在/唯一性的檢查。 (我認為這樣的事情是可行的,使用x3::with<>上下文添加,基本上包含一個std::set<VT::*> 。當然這樣的東西需要(依賴於實現?)強制轉換或刪除包裝器) 。

目前,沒有發表評論:

住在Coliru

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

struct LayerInfo
{
    std::string layerName;
    int layerNumber = 0;
    std::string color;
    bool visible = false;
};

namespace Parser {
    namespace x3 = boost::spirit::x3;

    // custom type parsers
    auto quoted = rule<std::string>("quoted", x3::lexeme [ '"' >> *('\\' >> x3::char_ | ~x3::char_('"')) >> '"' ]);
    struct colors_type : x3::symbols<char> {
        colors_type() {
            this->add("red")("blue")("green")("black");
        }
    } static const colors;

    namespace detail {
        template <typename T> auto propagate(T member) {
            return [=](auto& ctx){ x3::traits::move_to(x3::_attr(ctx), x3::_val(ctx).*member); };
        }

        template <typename T> auto make_member_parser(int T::* const member) { return x3::int_ [propagate(member)]; }
        template <typename T> auto make_member_parser(bool T::* const member) { return x3::bool_ [propagate(member)]; }
        template <typename T> auto make_member_parser(std::string T::* const member) { return x3::raw[colors] [propagate(member)]; }

        template <typename T = LayerInfo, typename P>
            auto rule(const char* debug, P p) { return x3::rule<struct _, T> {debug} = x3::skip(x3::space)[p]; };

        auto property = [](auto label, auto member) {
            return rule(label, x3::as_parser(label) >> '=' >> make_member_parser(member));
        };
    }

    using detail::rule;
    using detail::propagate;
    using detail::property;

    auto name       = rule("name", "Layer" >> quoted [propagate(&LayerInfo::layerName)]);

    auto number     = property("number", &LayerInfo::layerNumber);
    auto color      = property("color", &LayerInfo::color);
    auto visible    = property("visible", &LayerInfo::visible);

    auto layer_info = name >> '{' >> +(number | color | visible) >> '}';

    auto grammar    = rule("layer_info", layer_info);
}

std::ostream& operator<<(std::ostream& os, LayerInfo const& li) {
    return os << "LayerInfo \"" << li.layerName << "\"{"
        << "number="  << li.layerNumber   << " "
        << "color="   << li.color         << " "
        << "visible=" << std::boolalpha << li.visible 
        << "}\n";
}

int main() {
    std::string const sample = R"(Layer "L1" {
    number = 23
    color = green
    visible = true
})";

    LayerInfo v;
    auto f = sample.begin(), l = sample.end();
    bool ok = parse(f, l, Parser::grammar, v);


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

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

打印

Parsed: LayerInfo "L1"{number=23 color=green visible=true}

Wit調試信息: Live On Coliru

<layer_info>
  <try>Layer "L1" {\n    num</try>
  <name>
    <try>Layer "L1" {\n    num</try>
    <quoted>
      <try> "L1" {\n    number =</try>
      <success> {\n    number = 23\n </success>
      <attributes>[L, 1]</attributes>
    </quoted>
    <success> {\n    number = 23\n </success>
    <attributes>LayerInfo "L1"{number=0 color= visible=false}
</attributes>
  </name>
  <number>
    <try>\n    number = 23\n   </try>
    <success>\n    color = green\n </success>
    <attributes>LayerInfo "L1"{number=23 color= visible=false}
</attributes>
  </number>
  <number>
    <try>\n    color = green\n </try>
    <fail/>
  </number>
  <color>
    <try>\n    color = green\n </try>
    <success>\n    visible = true\n</success>
    <attributes>LayerInfo "L1"{number=23 color=green visible=false}
</attributes>
  </color>
  <number>
    <try>\n    visible = true\n</try>
    <fail/>
  </number>
  <color>
    <try>\n    visible = true\n</try>
    <fail/>
  </color>
  <visible>
    <try>\n    visible = true\n</try>
    <success>\n}</success>
    <attributes>LayerInfo "L1"{number=23 color=green visible=true}
</attributes>
  </visible>
  <number>
    <try>\n}</try>
    <fail/>
  </number>
  <color>
    <try>\n}</try>
    <fail/>
  </color>
  <visible>
    <try>\n}</try>
    <fail/>
  </visible>
  <success></success>
  <attributes>LayerInfo "L1"{number=23 color=green visible=true}
</attributes>
</layer_info>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM