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