使用精神来分析类吗? [英] Using spirit to parse into classes?

查看:63
本文介绍了使用精神来分析类吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是booster spirit文档中的employee.cpp源文件.它是结构雇员",后跟一个宏,该宏告诉有关结构雇员"的融合,然后是雇员解析器.

我正在尝试为此目的进行调整,但我不想使用结构型员工",而是希望使用许多类来代替结构型员工".

我正在尝试尝试将"struct employee"替换为类,但是我没有看到宏在融合中做到这一点吗?我不想将其放入struct的原因是因为我随后不得不将其从struct复制到我的类中,这似乎是不必要的,更不用说对性能的影响了.

再多考虑一下之后,我可能不太了解Fusion和元组的用途,因此,也许我必须以这种方式使用它,然后将数据移入我自己的类结构中.

有指导吗?

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

    using boost::fusion::operator<<;
}}

// We need to tell fusion about our employee struct
// to make it a first-class fusion citizen. This has to
// be in global scope.

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

namespace client
{
    ///////////////////////////////////////////////////////////////////////////////
    //  Our employee parser
    ///////////////////////////////////////////////////////////////////////////////
    namespace parser
    {
        namespace x3 = boost::spirit::x3;
        namespace ascii = boost::spirit::x3::ascii;

        using x3::int_;
        using x3::lit;
        using x3::double_;
        using x3::lexeme;
        using ascii::char_;

        x3::rule<class employee, ast::employee> const employee = "employee";

        auto const quoted_string = lexeme['"' >> +(char_ - '"') >> '"'];

        auto const employee_def =
            lit("employee")
            >> '{'
            >>  int_ >> ','
            >>  quoted_string >> ','
            >>  quoted_string >> ','
            >>  double_
            >>  '}'
            ;

        BOOST_SPIRIT_DEFINE(employee);
    }
} 

解决方案

structclass¹之间没有区别.

顺便说一句,人们通常的意思是我想要没有直接数据成员(字段")访问权限的类".

现在,我可以直接指向增强精神:语义动作是邪恶的?"?),或者实际上具有干净的AST表示形式,您可以然后使用它来构建域对象图.

如果您做不起(因为有副本),那么您真的买不起Spirit V2 IMO. Spirit致力于在不产生残酷代码的情况下快速发展(改变)语法的原型.但是,如果您负担不起复印件,那么该是时候手动滚动解析器了(或移至Spirit X3)


¹从字面上唯一的区别是struct默认情况下将所有成员公开,但是您仍然可以使用private:protected:

²可能起源于Java的PoJo或"Bean"的历史

³ 伪类和拟类 混淆面向对象编程"

Below is the employee.cpp source file from the boost spirit documentation. It's 'struct employee' followed by a macro that tells fusion about 'struct employee', followed by the employee parser.

I am trying to adapt this for my purposes, but rather than use 'struct employee', I have a number of classes that I'd like to use in place of 'struct employee'.

I was looking at trying to replace 'struct employee' for classes, but I don't see the macros to do that in fusion? And the reason I don't want to put it in the struct is because I'd then have to copy it over from struct to my class, and that just seems unnecessary, not to mention the performance hit.

After thinking about it a bit more, I may not be understanding the purpose for Fusion and tuples, and therefore, maybe I have to use it that way and then move data into my own class structures.

Any guidance?

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

    using boost::fusion::operator<<;
}}

// We need to tell fusion about our employee struct
// to make it a first-class fusion citizen. This has to
// be in global scope.

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

namespace client
{
    ///////////////////////////////////////////////////////////////////////////////
    //  Our employee parser
    ///////////////////////////////////////////////////////////////////////////////
    namespace parser
    {
        namespace x3 = boost::spirit::x3;
        namespace ascii = boost::spirit::x3::ascii;

        using x3::int_;
        using x3::lit;
        using x3::double_;
        using x3::lexeme;
        using ascii::char_;

        x3::rule<class employee, ast::employee> const employee = "employee";

        auto const quoted_string = lexeme['"' >> +(char_ - '"') >> '"'];

        auto const employee_def =
            lit("employee")
            >> '{'
            >>  int_ >> ','
            >>  quoted_string >> ','
            >>  quoted_string >> ','
            >>  double_
            >>  '}'
            ;

        BOOST_SPIRIT_DEFINE(employee);
    }
} 

解决方案

There is no difference between struct and class¹.

With that out of the way, what people usually mean is "I want classes without direct data member ("field") access".

Now I could point you straight at BOOST_FUSION_ADAPT_ADT. That's what you are looking for.

However.

This implies that you have exposed setters for all your data members anyways. That's a giant anti-pattern², as it just leads to Quasi-Classes³.

Consider using factory functions (adapt them using Phoenix to call from semantic actions // but see Boost Spirit: "Semantic actions are evil"?) or, indeed having a clean AST representation which you then use to build the domain object graph from.

If you can't afford doing that (because of the copies) you can't really afford Spirit V2 IMO. Spirit is geared towards rapid development/prototyping of (changing) grammars while not generating atrocious code. But if you can't afford copies it's time to hand-roll your parser (or move to Spirit X3)


¹ literally the only difference is struct makes all members public by default, but you can still use private: and protected:

² likely originating in the history of Java's PoJo or "Bean"

³ "Pseudo-Classes and Quasi-Classes Confuse Object-Oriented Programming"

这篇关于使用精神来分析类吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆