C++ Boost Spirit X3代数解析器(带变量)

C++ Boost Spirit X3代数解析器(带变量),c++,boost-spirit,boost-spirit-x3,C++,Boost Spirit,Boost Spirit X3,我一直在用spirit x3为代数表达式编写解析器。我的目标是在calc4c示例解析器的基础上进行构建,以便它包含带有变量、指数和括号的表达式作为乘法运算符。我在这方面已经做了很长时间了,我完全没有主意了 我从“move.hpp”、“move_to.hpp”和“transform_attribute.hpp”中得到了各种各样的错误,但它们没有帮助。然而,这可能是因为我对boost的了解相当有限 这是我得到的,任何帮助都将不胜感激 AST: 命名空间客户端{namespace ast { //AS

我一直在用spirit x3为代数表达式编写解析器。我的目标是在calc4c示例解析器的基础上进行构建,以便它包含带有变量、指数和括号的表达式作为乘法运算符。我在这方面已经做了很长时间了,我完全没有主意了

我从“move.hpp”、“move_to.hpp”和“transform_attribute.hpp”中得到了各种各样的错误,但它们没有帮助。然而,这可能是因为我对boost的了解相当有限

这是我得到的,任何帮助都将不胜感激

AST:

命名空间客户端{namespace ast
{
//AST
结构nil{};
结构指数;
结构letNum;
结构签名;
结构参数;
结构程序;
typedefx3::variant<
无
浮动
烧焦
,std::list
,x3::向前
,x3::向前
,x3::向前
,x3::向前
,x3::向前
>
操作数;
结构指数
{
操作数优先;
操作数秒;
};
结构letNum
{
浮点数;
std::列表let;
};
结构签名_
{
字符符号;
操作数操作数;
};
结构参数
{
std::列表参数列表;
};
结构操作
{
字符算子;
操作数操作数;
};
结构程序
{
操作数优先;
std::列出其余部分;
};
}}
BOOST\u FUSION\u ADAPT\u STRUCT(客户机::ast::指数、第一、第二)
BOOST\u FUSION\u ADAPT\u STRUCT(client::ast::letNum,num,let)
BOOST\u FUSION\u ADAPT\u结构(客户机::ast::有符号、有符号、操作数)
BOOST\u FUSION\u ADAPT\u STRUCT(客户机::ast::paren,parenList)
BOOST\u FUSION\u ADAPT\u结构(客户端::ast::操作、运算符、操作数)
BOOST\u FUSION\u ADAPT\u STRUCT(客户机::ast::程序,第一,rest)
}
语法:

namespace client
{
    //Simplify Grammar
    namespace simplify_grammar
    {
        using x3::float_;
        using x3::char_;
        using x3::alpha;

        x3::real_parser<float, x3::ureal_policies<float> > const ureal_float_ = {};

        x3::rule<class expression, ast::program> const expression("expression");
        x3::rule<class term, ast::program> const term("term");
        x3::rule<class exponent, ast::exponential> const exponent("exponent");

        x3::rule<class factor, ast::operand> const factor("factor");
        x3::rule<class factorSigned, ast::signed_> const factorSigned("factorSigned");
        x3::rule<class factorParen, ast::paren> const factorParen("factorParen");

        x3::rule<class letters, std::list<char> > const letters("letters");
        x3::rule<class combo, ast::letNum> const combo("combo");

        auto const expression_def =
                term >> *(  (char('+') >> term)
                         |  (char('-') >> term))
                ;

        auto const term_def =
                (exponent | factor | factorSigned | factorParen) >> *(   (char('*') >> (exponent | factor | factorSigned | factorParen))
                                                                     |   (char('/') >> (exponent | factor | factorSigned | factorParen))
                                                                     )
                ;

        auto const exponent_def =
                (   (   (ureal_float_ | alpha | ('(' >> expression >> ')'))
                        >> '^'
                        >> (factor | ('(' >> expression >> ')')))
                |   (   char('-')
                        >> (ureal_float_ | alpha | ('(' >> expression >> ')'))
                        >> '^'
                        >> (factor | ('(' >> expression >> ')')))
                )
                ;

        auto const factor_def =
                    combo
                |   ureal_float_
                |   letters
                ;

        auto const factorSigned_def =
                char('-') >> factor
                ;

        auto const factorParen_def =
                (   (factor | factorSigned) >> +('(' >> expression >> ')'))
                |
                (   '(' >> expression >> ')' >> +('(' >> expression >> ')'))
                ;

        auto const letters_def =
                +alpha
                ;

        auto const combo_def =
                ureal_float_ >> letters
                ;

        BOOST_SPIRIT_DEFINE(
                expression
              , term
              , exponent
              , factor
              , factorSigned
              , factorParen
              , letters
              , combo
        );

        parser_type simplify()
        {
            return expression;
        }
    }
}
命名空间客户端
{
//简化语法
名称空间简化语法
{
使用x3::float_2;;
使用x3::char\ux;
使用x3::alpha;
x3::real_parser const ureal_float_={};
x3::规则常量表达式(“表达式”);
x3::规则常量术语(“术语”);
x3::规则常数指数(“指数”);
x3::规则常量因子(“因子”);
x3::规则常量factorSigned(“factorSigned”);
x3::规则常量factorParen(“factorParen”);
x3::规则常量字母(“字母”);
x3::规则常量组合(“组合”);
自动常量表达式=
术语>>*((字符(+')>>术语)
|(字符('-'>>术语))
;
自动常数项=
(指数|因子|因子|因子设计|因子设计|因子设计|因子设计|因子设计|因子设计|因子设计|因子设计)
|(字符(“/”)>>(指数|因子|因子签名|因子页))
)
;
自动常数指数=
(((ureal_float|alpha |)('('>>表达式>>')))
>> '^'
>>(因子|('('>>表达式>>')))
|(字符('-'))
>>(ureal_float|alpha |('('>>表达式>>'))
>> '^'
>>(因子|('('>>表达式>>')))
)
;
自动常数因子=
联合体
|乌拉尔浮球_
|信件
;
自动常数因子已指定=
字符('-')>>因子
;
自动常数系数=
((factor | factorSigned)>>+('('>>表达式>>'))
|
('('>>表达式>>')'>>+('('>>表达式>>')'))
;
自动常量字母=
+阿尔法
;
自动常量组合定义=
ureal_float_>>字母
;
提升精神(
表达
学期
,指数
因素
,系数化
,factorpain
,信件
,组合
);
解析器_type simplify()
{
返回表达式;
}
}
}
编辑: 解析器类型定义:

namespace client
{
    ///////////////////////////////////////////////////////////////////////////////
    //  The calculator grammar
    ///////////////////////////////////////////////////////////////////////////////
    namespace calculator_grammar
    {
        using parser_type =
            x3::any_parser<
                std::string::const_iterator
              , ast::program
              , decltype(x3::make_context<x3::skipper_tag>(x3::ascii::space))
            >;

        parser_type calculator();
    }
    
    auto const calculator = calculator_grammar::calculator();
}
命名空间客户端
{
///////////////////////////////////////////////////////////////////////////////
//计算器语法
///////////////////////////////////////////////////////////////////////////////
名称空间计算器语法
{
使用parser\u类型=
x3::任何_解析器<
std::string::const_迭代器
,ast::程序
,decltype(x3::生成上下文(x3::ascii::空格))
>;
解析器_类型计算器();
}
自动常量计算器=计算器\语法::计算器();
}

什么是解析器类型?您要解析的输入是什么?@sehe我在帖子中包含了parser_type的定义。我没有具体的输入,但能够解析像“2x(3xy)^2+2x/y”这样复杂的东西是我的目标。你想解析它什么/as/,因为它看起来不是要反映表达式结构,而是词汇输入?我看了一遍,但我真的不知道如何开始阅读语法。我不习惯生成与数学结构不匹配的AST(嵌套的二进制/一元运算)。我在这个网站上有很多不同方法的表达式解析器示例,所以您可以比较一下。否则,我建议你减少产量,直到你只有一个问题。所以,基本上,不要只写200行非常复杂的C++,然后点击编译。相反,从10行开始,绿色条,添加简单的测试用例,让它们通过,
namespace client
{
    ///////////////////////////////////////////////////////////////////////////////
    //  The calculator grammar
    ///////////////////////////////////////////////////////////////////////////////
    namespace calculator_grammar
    {
        using parser_type =
            x3::any_parser<
                std::string::const_iterator
              , ast::program
              , decltype(x3::make_context<x3::skipper_tag>(x3::ascii::space))
            >;

        parser_type calculator();
    }
    
    auto const calculator = calculator_grammar::calculator();
}