c++ - Boost spirit parser not compiling -


i tried write simple expression parser boost::spirit. started calculator example (see: http://www.boost.org/doc/libs/1_41_0/libs/spirit/example/qi/calc2_ast.cpp) , tried add "ref" rule denoting reference variable. here code:

#include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/variant/recursive_variant.hpp> #include <boost/variant/apply_visitor.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <boost/spirit/include/phoenix_function.hpp>  #include <iostream> #include <vector> #include <string> namespace client{       namespace qi = boost::spirit::qi;     namespace ascii = boost::spirit::ascii;      ///////////////////////////////////////////////////////////////////////////     //  our ast     ///////////////////////////////////////////////////////////////////////////     struct binary_op;     struct unary_op;     struct ref {        std::string name;        ref(const std::string& name) : name(name){}     };     struct nil {};      struct expression_ast     {         typedef             boost::variant<                 nil // can't happen!               , unsigned int               , ref               , boost::recursive_wrapper<expression_ast>               , boost::recursive_wrapper<binary_op>               , boost::recursive_wrapper<unary_op>             >         type;          expression_ast()           : expr(nil()) {}          template <typename expr>         expression_ast(expr const& expr)           : expr(expr) {}          expression_ast& operator+=(expression_ast const& rhs);         expression_ast& operator-=(expression_ast const& rhs);         expression_ast& operator*=(expression_ast const& rhs);         expression_ast& operator/=(expression_ast const& rhs);          type expr;     };        struct binary_op     {         binary_op(             char op           , expression_ast const& left           , expression_ast const& right)         : op(op), left(left), right(right) {}          char op;         expression_ast left;         expression_ast right;     };      struct unary_op     {         unary_op(             char op           , expression_ast const& subject)         : op(op), subject(subject) {}          char op;         expression_ast subject;     };      expression_ast& expression_ast::operator+=(expression_ast const& rhs)     {         expr = binary_op('+', expr, rhs);         return *this;     }      expression_ast& expression_ast::operator-=(expression_ast const& rhs)     {         expr = binary_op('-', expr, rhs);         return *this;     }      expression_ast& expression_ast::operator*=(expression_ast const& rhs)     {         expr = binary_op('*', expr, rhs);         return *this;     }      expression_ast& expression_ast::operator/=(expression_ast const& rhs)     {         expr = binary_op('/', expr, rhs);         return *this;     }      // should using expression_ast::operator-. there's bug     // in phoenix type deduction mechanism prevents     // doing so. phoenix switching boost_typeof. in     // meantime, use phoenix::function below:     struct negate_expr     {         template <typename t>         struct result { typedef t type; };          expression_ast operator()(expression_ast const& expr) const         {             return expression_ast(unary_op('-', expr));         }     };     struct ref_maker    {       template <typename t>       struct result { typedef t type; };        ref operator()(std::string const& expr) const       {           return expr;       }    };       boost::phoenix::function<negate_expr> neg;     boost::phoenix::function<ref_maker> make_ref;  /////////////////////////////////////////////////////////////////////////// //  walk tree /////////////////////////////////////////////////////////////////////////// struct ast_print {    typedef void result_type;     void operator()(qi::info::nil) const {    }    void operator()(int n) const {       std::cout << n;    }     void operator()(expression_ast const& ast) const {       boost::apply_visitor(*this, ast.expr);    }     void operator()(binary_op const& expr) const {       std::cout << "op:" << expr.op << "(";       boost::apply_visitor(*this, expr.left.expr);       std::cout << ", ";       boost::apply_visitor(*this, expr.right.expr);       std::cout << ')';    }     void operator()(unary_op const& expr) const {       std::cout << "op:" << expr.op << "(";       boost::apply_visitor(*this, expr.subject.expr);       std::cout << ')';    }     void operator()(ref const& expr) const {       std::cout << "ref:" << expr.name ;    } };      ///////////////////////////////////////////////////////////////////////////     //  our calculator grammar     ///////////////////////////////////////////////////////////////////////////     template <typename iterator>     struct calculator : qi::grammar<iterator, expression_ast(), ascii::space_type>     {         calculator() : calculator::base_type(expression)         {             using qi::_val;             using qi::_1;             using qi::uint_;             using qi::lit;             using ascii::alnum;              identifier = (alnum [_val += _1]);              expression =                 term                            [_val = _1]                 >> *(   ('+' >> term            [_val += _1])                     |   ('-' >> term            [_val -= _1])                     )                 ;              term =                 factor                          [_val = _1]                 >> *(   ('*' >> factor          [_val *= _1])                     |   ('/' >> factor          [_val /= _1])                     )                 ;              factor =                 uint_                           [_val = _1]                 | identifier                    [_val = make_ref(_1)]                 |   '(' >> expression           [_val = _1] >> ')'                 |   ('-' >> factor              [_val = neg(_1)])                 |   ('+' >> factor              [_val = _1])                 ;         }         qi::rule<iterator, std::string(), ascii::space_type> identifier;         qi::rule<iterator, expression_ast(), ascii::space_type>  expression, term, factor;     }; }  /////////////////////////////////////////////////////////////////////////////// //  main program /////////////////////////////////////////////////////////////////////////////// int main() {     std::cout << "/////////////////////////////////////////////////////////\n\n";     std::cout << "expression parser...\n\n";     std::cout << "/////////////////////////////////////////////////////////\n\n";     std::cout << "type expression...or [q or q] quit\n\n";      using client::ascii::space;     using client::expression_ast;     using client::ast_print;      typedef std::string::const_iterator iterator_type;     typedef client::calculator<iterator_type> calculator;      calculator calc; // our grammar      std::string str;     while (std::getline(std::cin, str))     {         if (str.empty() || str[0] == 'q' || str[0] == 'q')             break;          std::string::const_iterator iter = str.begin();         std::string::const_iterator end = str.end();         expression_ast ast;         ast_print printer;         bool r = phrase_parse(iter, end, calc, space, ast);          if (r && iter == end)         {             std::cout << "-------------------------\n";             std::cout << "parsing succeeded\n";             printer(ast);             std::cout << "\n-------------------------\n";         }         else         {             std::string rest(iter, end);             std::cout << "-------------------------\n";             std::cout << "parsing failed\n";             std::cout << "stopped at: \": " << rest << "\"\n";             std::cout << "-------------------------\n";         }     }      std::cout << "bye... :-) \n\n";     return 0; } 

the changes made example following:

  1. add ref struct , entry in variant.
  2. add identifier rule reads single variable name string
  3. create functor , phoenix function make_ref making ref string
  4. add identifier option factor rule calls make_ref transform identifier string ref.

the code not work. there following type error:

/usr/include/boost/spirit/home/phoenix/core/detail/function_eval.hpp:135:69: error: not convert ‘bench::expr::ref_maker::operator()(const string&) const((*(const string*)boost::phoenix::detail::help_rvalue_deduction<std::basic_string<char> >((* &(& _0)->boost::spirit::argument<n>::eval<boost::phoenix::basic_environment<boost::fusion::vector1<std::basic_string<char>&>, boost::spirit::context<boost::fusion::cons<bench::expr::expression_ast&, boost::fusion::nil>, boost::fusion::vector0<> >, bool, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >((* & env))))))’ ‘bench::expr::ref’ ‘std::basic_string<char>’ 

it seems phoenix wants make_ref return string instead of ref, not want. doing wrong here?

the result of ref_maker ref, not same input argument. make it

struct ref_maker {    template <typename t>    struct result { typedef ref type; }; // <-- here.     ref operator()(std::string const& expr) const    {        return expr;    } }; 

also, replace bench::expr:: in main client::, or you'll errors namespace bench::expr doesn't exist.


Comments

Popular posts from this blog

matlab - "Contour not rendered for non-finite ZData" -

delphi - Indy UDP Read Contents of Adata -

javascript - Any ideas when Firefox is likely to implement lengthAdjust and textLength? -