C++ 提高精神分裂规则到不同的标题

C++ 提高精神分裂规则到不同的标题,c++,boost-spirit,boost-spirit-qi,C++,Boost Spirit,Boost Spirit Qi,我想解析以下结构(为了简单起见,我将只显示其中的一半,但结构的其余部分与所示的相同): 每个部分(以*)将被解析为一个结构。主截面点将包含子截面序号、材料和输出。它还将具有属性名称、任务和继承点 Sn部分将被解析为 struct序列号{ std::字符串名称/“Sn” 地图数据; } 材料进入 struct材质{ std::字符串名称//“材质” std::矢量数据; } Kt struct Kt{ std::字符串名称;//“kt” int值; } 输出 struct输出{ std::字符串

我想解析以下结构(为了简单起见,我将只显示其中的一半,但结构的其余部分与所示的相同):

每个部分(以*)将被解析为一个结构。主截面点将包含子截面序号、材料和输出。它还将具有属性名称、任务和继承点

  • Sn部分将被解析为
    struct序列号{
    std::字符串名称/“Sn”
    地图数据;
    }

  • 材料进入

    struct材质{
    std::字符串名称//“材质”
    std::矢量数据;
    }

  • Kt

    struct Kt{
    std::字符串名称;//“kt”
    int值;
    }

  • 输出

    struct输出{
    std::字符串名称;//“输出”
    std::矢量数据;
    }

为了分析这一部分,我使用了Boost Spirit中的一个示例,并对其进行了修改

由于要分析的部分很大,我正在考虑将语法规则拆分为单独的类。我的想法是为每个要分析的子部分制定一条规则,并为解析点部分制定一条主要规则。
每个
子规则
将被解析为其相应的结构。
为此,我需要能够将lexer传递给每个“子规则”,但我不知道该怎么做

这是我迄今为止所做的

从语法定义中可以看到,规则assignment_Rule2是在一个单独的文件中定义的,但我不知道如何将lexer传递给这个规则。而且它不编译

    #define BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
#define BOOST_SPIRIT_DEBUG

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/qi_real.hpp>
#include <boost/spirit/include/qi_eol.hpp>
#include <boost/spirit/include/phoenix.hpp>

#include <iostream>
#include <fstream>
#include <string>
#include <map>

#include "example.hpp"


using namespace boost::spirit;
using boost::phoenix::val;

///////////////////////////////////////////////////////////////////////////////
//  class definition
///////////////////////////////////////////////////////////////////////////////

namespace client {
    namespace qi = boost::spirit::qi;

    struct point
    {
        std::string name;
        std::string name2;
        std::string mission;
        std::string parent_point;
    };
}

BOOST_FUSION_ADAPT_STRUCT(client::point,
    (std::string, name),
    (std::string, name2),
    (std::string, mission),
    (std::string, parent_point)
)

namespace client {
    ///////////////////////////////////////////////////////////////////////////////
    //  Token id definitions
    ///////////////////////////////////////////////////////////////////////////////
    enum token_ids
    {
        ID_CONSTANT = 1000,
        ID_START_POINT,
        ID_END_POINT,
        ID_SN,
        ID_MATERIAL,
        ID_IDENTIFIER,
        ID_INTEGER,
        ID_FLOAT
    };

    ///////////////////////////////////////////////////////////////////////////////
    //  Token definitions
    ///////////////////////////////////////////////////////////////////////////////
    template <typename Lexer>
    struct example6_tokens : lex::lexer<Lexer>
    {
        example6_tokens()
        {
            // define the tokens to match
            identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
            constant = "[0-9]+";
            float_value = "-?\\d+(\\.\\d+)?";

            this->self = lex::token_def<>('(') | ')' | '=' | ',' | '*';

            this->self.add
            (constant, ID_CONSTANT)
                ("Point", ID_START_POINT)
                ("End Point", ID_END_POINT)
                ("Sn", ID_SN)
                ("Material", ID_MATERIAL)
                (identifier, ID_IDENTIFIER)
                (float_value, ID_FLOAT)
                ;

            this->self("WS")
                = lex::token_def<>("[ \\t\\n]+")
                | "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"
                ;
        }

        lex::token_def<std::string> identifier;
        lex::token_def<unsigned int> constant;
        lex::token_def<double> float_value;
    };
}

///////////////////////////////////////////////////////////////////////////////
//  Grammar definition
///////////////////////////////////////////////////////////////////////////////

namespace client {

    template <typename Iterator, typename Lexer>
    struct example6_grammar
        : qi::grammar<Iterator, point(), qi::in_state_skipper<Lexer> >
    {
        template <typename TokenDef>
        example6_grammar(TokenDef const& tok)
            : example6_grammar::base_type(start)
        {
            using boost::spirit::_val;
            using boost::spirit::qi::eol;
            using qi::on_error;
            using qi::fail;
            using qi::debug;


            start
                =   '*' 
                    >> token(ID_START_POINT)
                    >> ','
                    >> assignment2
                    >> ','
                    >> assignment2
                    >> ','
                    >> assignment2
                    >> *statement 
                    >> '*' 
                    >> token(ID_END_POINT)
                ;

            statement
                = sn_stmt
                | material_stmt
                ;

            assignment
                = tok.identifier >> '=' >> expression
            ;

            sn_stmt = ('*' >> token(ID_SN) >> +pair)
                [
                    std::cout << val("sn statement to: ")
                    << _1 << "\n"
                ]
            ;

            material_stmt = ('*' >> token(ID_MATERIAL) >> +list)
                [
                    std::cout << val("material statement to: ")
                    << _1 << "\n"
                ]
            ;

            list = token(ID_FLOAT) % ',';

            pair
                = token(ID_CONSTANT) >> ',' >> token(ID_FLOAT)
                ;

            expression
                = tok.identifier[_val = _1]
                | tok.constant[_val = _1]
                ;

            sn_stmt.name("sn_stmt");
            material_stmt.name("material_stmt");
            debug(sn_stmt);
            debug(material_stmt);
        }

        typedef boost::variant<unsigned int, std::string> expression_type;

        qi::rule<Iterator, point(), qi::in_state_skipper<Lexer> > start;
        qi::rule<Iterator, qi::in_state_skipper<Lexer> > statement, material_stmt, pair, list, assignment;
        qi::rule<Iterator, qi::in_state_skipper<Lexer>> sn_stmt;

        qi::rule<Iterator, expression_type(), qi::in_state_skipper<Lexer> >  expression;
        Assigment_Rule2<Iterator> assignment2;
    };
}

///////////////////////////////////////////////////////////////////////////////
int main()
{
    typedef std::string::iterator base_iterator_type;

    typedef lex::lexertl::token<
        base_iterator_type, boost::mpl::vector<unsigned int, std::string, double>
    > token_type;

    typedef lex::lexertl::lexer<token_type> lexer_type;
    typedef client::example6_tokens<lexer_type> example6_tokens;
    typedef example6_tokens::iterator_type iterator_type;

    typedef client::example6_grammar<iterator_type, example6_tokens::lexer_def> example6_grammar;

    example6_tokens tokens;                         // Our lexer
    example6_grammar calc(tokens);                  // Our parser

    std::string str(read_from_file("ReadMe.txt"));

    std::string::iterator it = str.begin();
    iterator_type iter = tokens.begin(it, str.end());
    iterator_type end = tokens.end();

    std::string ws("WS");
    client::point my_point;

    bool r = qi::phrase_parse(iter, end, calc, qi::in_state(ws)[tokens.self], my_point);

    if (r && iter == end)
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing succeeded\n";
        std::cout << "-------------------------\n";
    }
    else
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing failed\n";
        std::cout << "-------------------------\n";
    }

    std::cout << "Bye... :-) \n\n";
    return 0;
}
\define BOOST\u VARIANT\u USE\u RELAXED\u GET\u默认
#定义BOOST_SPIRIT_调试
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“example.hpp”
使用名称空间boost::spirit;
使用boost::phoenix::val;
///////////////////////////////////////////////////////////////////////////////
//类定义
///////////////////////////////////////////////////////////////////////////////
命名空间客户端{
名称空间qi=boost::spirit::qi;
结构点
{
std::字符串名;
std::字符串名称2;
字符串任务;
std::字符串父节点;
};
}
BOOST_FUSION_ADAPT_STRUCT(客户端::点,
(std::string,name),
(标准::字符串,名称2),
(标准:字符串,任务),
(标准::字符串,父点)
)
命名空间客户端{
///////////////////////////////////////////////////////////////////////////////
//令牌id定义
///////////////////////////////////////////////////////////////////////////////
枚举令牌标识
{
ID_常数=1000,
ID\u起点,
ID\u END\u POINT,
身份证号码,
ID_材料,
ID_标识符,
ID_整数,
浮点数
};
///////////////////////////////////////////////////////////////////////////////
//令牌定义
///////////////////////////////////////////////////////////////////////////////
模板
结构示例6_标记:lex::lexer
{
示例6_代币()
{
//定义要匹配的标记
identifier=“[a-zA-Z][a-zA-Z0-9\]*”;
常量=“[0-9]+”;
浮点值=“-?\\d+(\.\\d+)”;
this->self=lex::token_def(“(”)|“)”|“=”|“,”|“*”;
此->self.add
(常数,ID_常数)
(“点”,ID\u起点)
(“终点”,ID\U End\U Point)
(“序号”,识别号)
(“材料”,ID_材料)
(标识符,ID\U标识符)
(浮动\u值,ID\u浮动)
;
这个->自我(“WS”)
=lex::token_def(“[\\t\\n]+”)
| "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"
;
}
lex::token_def标识符;
lex::token_def常量;
lex::token_def float_值;
};
}
///////////////////////////////////////////////////////////////////////////////
//语法定义
///////////////////////////////////////////////////////////////////////////////
命名空间客户端{
模板
结构示例6_语法
:qi::语法
{
模板
示例6_语法(TokenDef const&tok)
:示例6语法::基本类型(开始)
{
使用boost::spirit::\u val;
使用boost::spirit::qi::eol;
使用qi::on_错误;
使用qi::失败;
使用qi::调试;
开始
=   '*' 
>>令牌(ID\u起点\u点)
>> ','
>>转让2
>> ','
>>转让2
>> ','
>>转让2
>>*声明
>> '*' 
>>令牌(ID\U结束点)
;
陈述
=sn_stmt
|材料试验
;
分配
=tok.identifier>>'='>>表达式
;
序列号stmt=('*'>>令牌(ID\u序列号)>>+对)
[
标准::cout>+列表)
[
标准::cout>token(ID\u FLOAT)
;
表达
=tok.identifier[\u val=\u 1]
|托克常数[_val=_1]
;
序号名称(“序号”);
材料名称(“材料”);
调试(序列号stmt);
调试(材料测试);
}
typedef boost::变量表达式类型;
qi::规则开始;
qi::规则语句、材质、配对、列表、赋值;
qi::规则序列号;
qi:规则表达;
分配规则2转让2;
};
}
///////////////////////////////////////////////////////////////////////////////
int main()
{
typedef std::string::迭代器
    #define BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
#define BOOST_SPIRIT_DEBUG

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/qi_real.hpp>
#include <boost/spirit/include/qi_eol.hpp>
#include <boost/spirit/include/phoenix.hpp>

#include <iostream>
#include <fstream>
#include <string>
#include <map>

#include "example.hpp"


using namespace boost::spirit;
using boost::phoenix::val;

///////////////////////////////////////////////////////////////////////////////
//  class definition
///////////////////////////////////////////////////////////////////////////////

namespace client {
    namespace qi = boost::spirit::qi;

    struct point
    {
        std::string name;
        std::string name2;
        std::string mission;
        std::string parent_point;
    };
}

BOOST_FUSION_ADAPT_STRUCT(client::point,
    (std::string, name),
    (std::string, name2),
    (std::string, mission),
    (std::string, parent_point)
)

namespace client {
    ///////////////////////////////////////////////////////////////////////////////
    //  Token id definitions
    ///////////////////////////////////////////////////////////////////////////////
    enum token_ids
    {
        ID_CONSTANT = 1000,
        ID_START_POINT,
        ID_END_POINT,
        ID_SN,
        ID_MATERIAL,
        ID_IDENTIFIER,
        ID_INTEGER,
        ID_FLOAT
    };

    ///////////////////////////////////////////////////////////////////////////////
    //  Token definitions
    ///////////////////////////////////////////////////////////////////////////////
    template <typename Lexer>
    struct example6_tokens : lex::lexer<Lexer>
    {
        example6_tokens()
        {
            // define the tokens to match
            identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
            constant = "[0-9]+";
            float_value = "-?\\d+(\\.\\d+)?";

            this->self = lex::token_def<>('(') | ')' | '=' | ',' | '*';

            this->self.add
            (constant, ID_CONSTANT)
                ("Point", ID_START_POINT)
                ("End Point", ID_END_POINT)
                ("Sn", ID_SN)
                ("Material", ID_MATERIAL)
                (identifier, ID_IDENTIFIER)
                (float_value, ID_FLOAT)
                ;

            this->self("WS")
                = lex::token_def<>("[ \\t\\n]+")
                | "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"
                ;
        }

        lex::token_def<std::string> identifier;
        lex::token_def<unsigned int> constant;
        lex::token_def<double> float_value;
    };
}

///////////////////////////////////////////////////////////////////////////////
//  Grammar definition
///////////////////////////////////////////////////////////////////////////////

namespace client {

    template <typename Iterator, typename Lexer>
    struct example6_grammar
        : qi::grammar<Iterator, point(), qi::in_state_skipper<Lexer> >
    {
        template <typename TokenDef>
        example6_grammar(TokenDef const& tok)
            : example6_grammar::base_type(start)
        {
            using boost::spirit::_val;
            using boost::spirit::qi::eol;
            using qi::on_error;
            using qi::fail;
            using qi::debug;


            start
                =   '*' 
                    >> token(ID_START_POINT)
                    >> ','
                    >> assignment2
                    >> ','
                    >> assignment2
                    >> ','
                    >> assignment2
                    >> *statement 
                    >> '*' 
                    >> token(ID_END_POINT)
                ;

            statement
                = sn_stmt
                | material_stmt
                ;

            assignment
                = tok.identifier >> '=' >> expression
            ;

            sn_stmt = ('*' >> token(ID_SN) >> +pair)
                [
                    std::cout << val("sn statement to: ")
                    << _1 << "\n"
                ]
            ;

            material_stmt = ('*' >> token(ID_MATERIAL) >> +list)
                [
                    std::cout << val("material statement to: ")
                    << _1 << "\n"
                ]
            ;

            list = token(ID_FLOAT) % ',';

            pair
                = token(ID_CONSTANT) >> ',' >> token(ID_FLOAT)
                ;

            expression
                = tok.identifier[_val = _1]
                | tok.constant[_val = _1]
                ;

            sn_stmt.name("sn_stmt");
            material_stmt.name("material_stmt");
            debug(sn_stmt);
            debug(material_stmt);
        }

        typedef boost::variant<unsigned int, std::string> expression_type;

        qi::rule<Iterator, point(), qi::in_state_skipper<Lexer> > start;
        qi::rule<Iterator, qi::in_state_skipper<Lexer> > statement, material_stmt, pair, list, assignment;
        qi::rule<Iterator, qi::in_state_skipper<Lexer>> sn_stmt;

        qi::rule<Iterator, expression_type(), qi::in_state_skipper<Lexer> >  expression;
        Assigment_Rule2<Iterator> assignment2;
    };
}

///////////////////////////////////////////////////////////////////////////////
int main()
{
    typedef std::string::iterator base_iterator_type;

    typedef lex::lexertl::token<
        base_iterator_type, boost::mpl::vector<unsigned int, std::string, double>
    > token_type;

    typedef lex::lexertl::lexer<token_type> lexer_type;
    typedef client::example6_tokens<lexer_type> example6_tokens;
    typedef example6_tokens::iterator_type iterator_type;

    typedef client::example6_grammar<iterator_type, example6_tokens::lexer_def> example6_grammar;

    example6_tokens tokens;                         // Our lexer
    example6_grammar calc(tokens);                  // Our parser

    std::string str(read_from_file("ReadMe.txt"));

    std::string::iterator it = str.begin();
    iterator_type iter = tokens.begin(it, str.end());
    iterator_type end = tokens.end();

    std::string ws("WS");
    client::point my_point;

    bool r = qi::phrase_parse(iter, end, calc, qi::in_state(ws)[tokens.self], my_point);

    if (r && iter == end)
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing succeeded\n";
        std::cout << "-------------------------\n";
    }
    else
    {
        std::cout << "-------------------------\n";
        std::cout << "Parsing failed\n";
        std::cout << "-------------------------\n";
    }

    std::cout << "Bye... :-) \n\n";
    return 0;
}
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/qi_real.hpp>
#include <boost/spirit/include/qi_eol.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi_char_.hpp>
#include <boost/spirit/include/qi_lexeme.hpp>

using namespace boost::spirit;
using boost::phoenix::val;

namespace client {
    template <typename Iterator>
    struct Assigment_Rule2
        : qi::grammar<Iterator, std::string()>
    {
        Assigment_Rule2()
            : Assigment_Rule2::base_type(start)
        {
            using boost::spirit::double_;
            using boost::spirit::lexeme;
            using boost::spirit::ascii::char_;

            start = ( "2">> '=' >> "2" )
                [
                    _val = _2
                ]
            ;
        }

        qi::rule<Iterator, std::string()> start;
    };
}