Boost Spirit X3 Algebra Parser (With variables)

191 Views Asked by At

I've been writing a parser for algebraic expressions with spirit x3. My goal is to build upon the calc4c example parser so that it includes expressions with variables, exponents, and parentheses as a multiplication operator. I've been working on this for quite some time and I'm completely out of ideas.

I'm getting all sorts of errors from "move.hpp" "move_to.hpp" and "transform_attribute.hpp" but they aren't helpful. This could be due to my rather limited knowledge of boost, however.

Here's what I've got, any help would be much appreciated.

AST:

namespace client { namespace ast
{
    //AST
    struct nil {};
    struct exponential;
    struct letNum;
    struct signed_;
    struct paren;
    struct program;

    typedef x3::variant<
            nil
          , float
          , char
          , std::list<char>
          , x3::forward_ast<exponential>
          , x3::forward_ast<letNum>
          , x3::forward_ast<signed_>
          , x3::forward_ast<paren>
          , x3::forward_ast<program>
        >
    operand;

    struct exponential
    {
        operand first;
        operand second;
    };

    struct letNum
    {
        float num;
        std::list<char> let;
    };

    struct signed_
    {
        char sign_;
        operand operand_;
    };

    struct paren
    {
        std::list<operand> parenList;
    };

    struct operation
    {
        char operator_;
        operand operand_;
    };

    struct program
    {
        operand first;
        std::list<operation> rest;
    };

}}

BOOST_FUSION_ADAPT_STRUCT(client::ast::exponential, first, second)
BOOST_FUSION_ADAPT_STRUCT(client::ast::letNum, num, let)
BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_, sign_, operand_)
BOOST_FUSION_ADAPT_STRUCT(client::ast::paren, parenList)
BOOST_FUSION_ADAPT_STRUCT(client::ast::operation, operator_, operand_)
BOOST_FUSION_ADAPT_STRUCT(client::ast::program, first, rest)

}

Grammar:

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;
        }
    }
}

EDIT: parser_type definition:

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();
}
0

There are 0 best solutions below