Re: Boost::Spirit: Application SUCCESS, crash at: printer(ast) ... why?

Philipp Schwaha <[email protected]>
Newsgroups gmane.comp.parsers.spirit.general
Message-ID <[email protected]>
Hi Jens,

On 07/15/2016 01:56 AM, Jens Kallup wrote:
> Hello,
>
> I have the problem, that the visitor does endless
> loop, and crash after a while.
> The problem is on:
>
> void operator()(expression_ast const& ast) const
> {
>    boost::apply_visitor(*this, ast.expr);
> }
>
> How can this be fixed?

I noticed that you define a 'nil' type, but use qi::info::nil in the 
visitor. Is there a particular reason for this?
I modified the code so it compiles for me (with both g++ and clang++ in 
c++11 mode). The visitor will not crash in this form.
Did you have a look at 
http://www.boost.org/doc/libs/1_61_0/libs/spirit/doc/html/spirit/support/utree.html 
for representing the ast?

Best regards
	Philipp


>
> Thanks for helping
> Jens
>
> here the run/compileable source:
>
> #include "includes/mainwindow.h"
>
> #define BOOST_SPIRIT_USE_PHOENIX_V3
> #include <boost/config/warning_disable.hpp>
> #include <boost/spirit/include/lex_lexertl.hpp>
> #include <boost/spirit/include/qi.hpp>
> #include <boost/spirit/include/lex_lexertl.hpp>
> #include <boost/spirit/include/phoenix.hpp>
> #include <boost/spirit/include/phoenix_operator.hpp>
> #include <boost/spirit/include/phoenix_container.hpp>
> #include <boost/spirit/include/phoenix_function.hpp>
> #include <boost/spirit/include/karma.hpp>
> #include <boost/fusion/include/adapt_struct.hpp>
> #include <boost/fusion/include/std_pair.hpp>
> #include <boost/variant/recursive_variant.hpp>
> #include <boost/variant/apply_visitor.hpp>
> #include <boost/variant/get.hpp>
>
> #include <boost/algorithm/string.hpp>
> #include <boost/shared_ptr.hpp>
> #include <boost/make_shared.hpp>
> #include <boost/lexical_cast.hpp>
>
> #include <boost/bind.hpp>
> #include <boost/ref.hpp>
>
> #include <iostream>
> #include <fstream>
> #include <string>
> #include <set>
> #include <utility>
>
> int lineno = 1;
>
>
> using namespace std;
> using namespace boost::spirit;
>
> namespace bs    = boost::spirit;
> namespace phx   = boost::phoenix;
> namespace ascii = boost::spirit::ascii;
>
> using boost::spirit::ascii::space; // use the ASCII space parser
> using boost::spirit::ascii::char_;
> using boost::spirit::_val;
>
> using boost::phoenix::val;
>
> struct print_testclass
> {
>      print_testclass() {}
>      print_testclass(std::string str1, std::string str2)
>      {
>          cout << str1 << " = " << str2 << endl;
>      }
> };
>
> namespace dBaseParser
> {
>      // -----------------
>      // AST for dBase ...
>      // -----------------
>      struct binary_op;
>      struct unary_op;
>      struct nil {};
>
>      struct expression_ast
>      {
>          typedef
>              boost::variant<
>                  nil // can't happen!
>                , int
>                , 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;
>      }
>
>      std::ostream& operator << (std::ostream& os, const expression_ast& as)
>      {
>          return os
>                  << boost::get<binary_op>(as.expr).left
>                  //<< " = "
>                  //<< boost::get<binary_op>(as.expr).right;
>                  << endl;
>      }
>
>      // ------------------------------------------------------------
>      // We should be using expression_ast::operator-. There's a bug
>      // in phoenix type deduction mechanism that prevents us from
>      // doing so. Phoenix will be switching to BOOST_TYPEOF. In the
>      // meantime, we will use a 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));
>          }
>      };
>
>      boost::phoenix::function<negate_expr> neg;
>
>      // -----------------------
>      // walk throug the AST ...
>      // -----------------------
>      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);
>
>              //int i = boost::get<int>(ast.expr);
>              //cout << "1 = " << (int)i << endl;
>          }
>
>          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 << ')';
>          }
>      };
>
>      template <typename Lexer>
>      struct dbase_tokens : lex::lexer<Lexer>
>      {
>          // ----------------------------
>          // tokens with no attributes...
>          // ----------------------------
>          lex::token_def<lex::omit> whitespace;
>          lex::token_def<lex::omit> cpcomment;
>          lex::token_def<lex::omit> d_comment;
>          lex::token_def<lex::omit> c_comment;
>
>          lex::token_def<lex::omit> kw_class;
>          lex::token_def<lex::omit> kw_of;
>          lex::token_def<lex::omit> kw_endclass;
>
>          // --------------------------
>          // tokens with attributes ...
>          // --------------------------
>          lex::token_def<char> printLn;
>
>          lex::token_def<int>         number_digit;
>          lex::token_def<std::string> identifier;
>          lex::token_def<std::string> quoted_string;
>
>          dbase_tokens()
>          {
>              // ------------
>              // keywords ...
>              // ------------
>              kw_class        = "(?i:class)";
>              kw_endclass     = "(?i:endclass)";
>              kw_of           = "(?i:of)";
>
>              printLn   = "\\\?";
>
>              // Values.
>              number_digit      = "[0-9]+";
>              quoted_string     = "\\\"(\\\\.|[^\\\"])*\\\""; //
> \"(\\.|[^\"])*\"
>
>              // Identifier.
>              identifier        = "[a-zA-Z][a-zA-Z0-9_]*";
>
>              cpcomment = "\\/\\/[^\\n]*\\n";                    //
> single line comment
>              d_comment = "\\*\\*[^\\n]*\\n";                    //
> dBase  line comment
>              c_comment = "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"; //
> c-style comments
>
>              whitespace = "[ \\t\\n]+";
>
>              this->self += lex::token_def<>
>                      ('(') | ')'
>                      | '+' | '-'
>                      | '*' | '/'
>                      | ',' | '.';
>              this->self +=
>                  printLn
>                  ;
>              this->self +=
>                  kw_class | kw_of | kw_endclass
>                  ;
>              this->self +=
>                    identifier
>                  | number_digit
>                  | quoted_string
>                  ;
>
>              this->self +=
>                    whitespace [ lex::_pass = lex::pass_flags::pass_ignore ]
>                  | cpcomment
>                  | c_comment
>                  | d_comment
>                  ;
>          }
>      };
>
>      template <typename Iterator, typename Lexer>
>      struct dbase_grammar
>      :   public qi::grammar<Iterator>
>      {   template <typename TokenDef>
>
>          dbase_grammar(TokenDef const& tok) :
>          dbase_grammar::base_type(start, "start")
>          {
>              using qi::_val;
>
>              start
>                  = +symsbols
>                  ;
>
>              expression =
>                  term                            [_val  = qi::_1]
>                  >> *(   ('+' >> term            [_val += qi::_1])
>                      |   ('-' >> term            [_val -= qi::_1])
>                      )
>                  ;
>
>              term =
>                  factor                          [_val  = qi::_1]
>                  >> *(   ('*' >> factor          [_val *= qi::_1])
>                      |   ('/' >> factor          [_val /= qi::_1])
>                      )
>                  ;
>
>              factor =
>                  tok.number_digit                [_val = qi::_1]
>                  |  '('   >> expression          [_val = qi::_1] >> ')'
>                  |   ('-' >> factor              [_val = neg(qi::_1)])
>                  |   ('+' >> factor              [_val = qi::_1])
>                  ;
>
>              symsbols
>                  = printLn
>                  | comments
>                  | class_definition
>                  | expression
>                  ;
>
>              comments
>                  = tok.cpcomment
>                  | tok.c_comment
>                  | tok.d_comment
>                  ;
>
>              printLn
>                  = tok.printLn >> *comments >> tok.quoted_string
>                  | tok.printLn >> tok.quoted_string
>                  ;
>
>              class_definition
>                  = (tok.kw_class          >> *comments
>                      >> tok.identifier    >> *comments
>                      >> tok.kw_of         >> *comments
>                      >> tok.identifier    >> *comments >> class_body
>                      >> tok.kw_endclass)
>                      [
>                          qi::_val = phx::construct<print_testclass>(
>                          phx::construct<std::string>(qi::_1),
>                          phx::construct<std::string>(qi::_2))
>                      ]
>                  ;
>              class_body
>                  = *comments
>                  ;
>
>              start.name("start");
>              symsbols.name("symsbols");
>              comments.name("comments");
>              expression.name("expression");
>              term.name("term");
>              factor.name("factor");
>              printLn.name("printLn");
>              class_definition.name("class_definition");
>              class_body.name("class_body");
>
>              BOOST_SPIRIT_DEBUG_NODE(start);
>              BOOST_SPIRIT_DEBUG_NODE(symsbols);
>              BOOST_SPIRIT_DEBUG_NODE(comments);
>              BOOST_SPIRIT_DEBUG_NODE(printLn);
>              BOOST_SPIRIT_DEBUG_NODE(class_definition);
>              BOOST_SPIRIT_DEBUG_NODE(class_body);
>              BOOST_SPIRIT_DEBUG_NODE(factor);
>              BOOST_SPIRIT_DEBUG_NODE(term);
>              BOOST_SPIRIT_DEBUG_NODE(expression);
>
>              using namespace qi::labels;
>              qi::on_error<qi::fail>
>              (
>                  start,
>                  std::cout
>                      << phx::val("Error! Expecting ")
>                      << bs::_4 // what failed?
>                      << phx::val(" here: \"")
>                      << phx::construct<std::string>(bs::_3, bs::_2)   //
> iterators to error-pos, end
>                      << phx::val("\"")
>                      << std::endl
>              );
>          }
>
>          typedef qi::unused_type skipper_type;
>          typedef qi::rule<Iterator, skipper_type> simple_rule;
>
>          simple_rule start, symsbols, comments, printLn;
>          simple_rule class_body;
>
>          qi::rule<Iterator, print_testclass()> class_definition;
>          qi::rule<Iterator, expression_ast()> expression, term, factor;
>      };
> }
>
> bool parseText(QString text)
> {
>      std::string data(text.toStdString().c_str());
>      if (data.size() < 1) {
>          QMessageBox::information(0,"Error","No Data for parser.\nABORT.");
>          return false;
>      }
>
>      using dBaseParser::expression_ast;
>      using dBaseParser::ast_print;
>
>      typedef std::string::iterator base_iterator_type;
>      typedef lex::lexertl::token<
>          base_iterator_type, boost::mpl::vector<char, int, std::size_t,
> std::string>
>      > token_type;
>      typedef lex::lexertl::actor_lexer<token_type> lexer_type;
>
>      typedef dBaseParser::dbase_tokens<lexer_type> dbase_tokens;
>      typedef dbase_tokens::iterator_type iterator_type;
>      typedef dBaseParser::dbase_grammar<iterator_type,
> dbase_tokens::lexer_def> dbase_grammar;
>
>      dbase_tokens  tokens;
>      dbase_grammar dbase(tokens);
>
>      base_iterator_type it = data.begin();
>      iterator_type iter    = tokens.begin(it, data.end());
>      iterator_type end     = tokens.end();
>
>      dBaseParser::expression_ast ast;
>      dBaseParser::ast_print  printer;
>
>      bool r = qi::parse(iter, end, dbase, ast);
>
>      if (r && iter == end) {
>          QMessageBox::information(w,"text parser","SUCCESS");
> printer(ast); } else
>          QMessageBox::information(w,"text parser","ERROR");
>
>      return 0;
> }
>
>
> ------------------------------------------------------------------------------
> What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
> patterns at an interface-level. Reveals which users, apps, and protocols are
> consuming the most bandwidth. Provides multi-vendor support for NetFlow,
> J-Flow, sFlow and other flows. Make informed decisions using capacity planning
> reports.http://sdm.link/zohodev2dev
> _______________________________________________
> Spirit-general mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/spirit-general
>

------------------------------------------------------------------------------
What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
patterns at an interface-level. Reveals which users, apps, and protocols are 
consuming the most bandwidth. Provides multi-vendor support for NetFlow, 
J-Flow, sFlow and other flows. Make informed decisions using capacity planning
reports.http://sdm.link/zohodev2dev

_______________________________________________
Spirit-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spirit-general
test.cpp (text/x-c++src, 13 KB)

// #include "includes/mainwindow.h"

#define BOOST_SPIRIT_USE_PHOENIX_V3
#define BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_container.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/get.hpp>

#include <boost/algorithm/string.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/lexical_cast.hpp>

//#include <boost/proto/proto.hpp>
//#include <boost/typeof/std/ostream.hpp>

//#include <boost/bind.hpp>
//#include <boost/ref.hpp>

//#include <boost/phoenix/bind/bind_member_function.hpp>

#include <iostream>
#include <fstream>
#include <string>
#include <set>
#include <utility>

int lineno = 1;


using namespace std;
using namespace boost::spirit;

namespace bs    = boost::spirit;
namespace phx   = boost::phoenix;
namespace ascii = boost::spirit::ascii;

using boost::spirit::ascii::space; // use the ASCII space parser
using boost::spirit::ascii::char_;
using boost::spirit::_val;

using boost::phoenix::val;

struct print_testclass
{
     print_testclass() {}
     print_testclass(std::string str1, std::string str2)
     {
         cout << str1 << " = " << str2 << endl;
     }
};

namespace dBaseParser
{
     // -----------------
     // AST for dBase ...
     // -----------------
     struct binary_op;
     struct unary_op;
     struct nil { };

     struct expression_ast
     {
         typedef
             boost::variant<
                   nil
                 , int
                 , boost::recursive_wrapper<expression_ast>
                 , boost::recursive_wrapper<binary_op>
                 , boost::recursive_wrapper<unary_op>
             >
         type;
         type expr;

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

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

     // We should be using expression_ast::operator-. There's a bug
     // in phoenix type deduction mechanism that prevents us from
     // doing so. Phoenix will be switching to BOOST_TYPEOF. In the
     // meantime, we will use a 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));
         }
     };

     boost::phoenix::function<negate_expr> neg;

     // -----------------------
     // walk throug the AST ...
     // -----------------------
     struct ast_print
     {
         typedef void result_type;

         void operator()(nil) const {
           std::cerr << " empty " << std::endl ;
         }
         void operator()(int n) const { std::cout << n; }

         void operator()(expression_ast const& ast) const
         {
           cout << "-> "
                << ast.expr.type().name()
                << endl;

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

     template <typename Lexer>
     struct dbase_tokens : lex::lexer<Lexer>
     {
         // ----------------------------
         // tokens with no attributes...
         // ----------------------------
         lex::token_def<lex::omit> whitespace;
         lex::token_def<lex::omit> cpcomment;
         lex::token_def<lex::omit> d_comment;
         lex::token_def<lex::omit> c_comment;

         lex::token_def<lex::omit> kw_class;
         lex::token_def<lex::omit> kw_of;
         lex::token_def<lex::omit> kw_endclass;

         // --------------------------
         // tokens with attributes ...
         // --------------------------
         lex::token_def<char> printLn;

         lex::token_def<int>         number_digit;
         lex::token_def<std::string> identifier;
         lex::token_def<std::string> quoted_string;

         dbase_tokens()
         {
             // ------------
             // keywords ...
             // ------------
             kw_class        = "(?i:class)";
             kw_endclass     = "(?i:endclass)";
             kw_of           = "(?i:of)";

             printLn   = "\\\?";

             // Values.
             number_digit      = "[0-9]";
             quoted_string     = "\\\"(\\\\.|[^\\\"])*\\\""; // \"(\\.|[^\"])*\"

             // Identifier.
             identifier        = "[a-zA-Z][a-zA-Z0-9_]*";

             cpcomment = "\\/\\/[^\\n]*\\n";                    // single line comment
             d_comment = "\\*\\*[^\\n]*\\n";                    // dBase  line comment
             c_comment = "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"; // c-style comments

             whitespace = "[ \\t\\n]+";

             this->self += lex::token_def<>
                     ('(') | ')'
                     | '+' | '-'
                     | '*' | '/'
                     | ',' | '.';
             this->self +=
                 printLn
                 ;
             this->self +=
                 kw_class | kw_of | kw_endclass
                 ;
             this->self +=
                   identifier
                 | number_digit
                 | quoted_string
                 ;

             this->self +=
                   whitespace [ lex::_pass = lex::pass_flags::pass_ignore ]
                 | cpcomment
                 | c_comment
                 | d_comment
                 ;
         }
     };

     template <typename Iterator, typename Lexer>
     struct dbase_grammar
     :   public qi::grammar<Iterator>
     {   template <typename TokenDef>

         dbase_grammar(TokenDef const& tok) :
         dbase_grammar::base_type(start, "start")
         {
             using qi::_val;

             start
                 = +symsbols
                 ;

             expression =
                 term                            [ _val  = qi::_1 ]
                 >> *(   ('+' >> term            [ _val += qi::_1 ])
                     |   ('-' >> term            [ _val -= qi::_1 ])
                     )
                 ;

             term =
                 factor                          [ _val  = qi::_1]
                 >> *(   ('*' >> factor          [ _val *= qi::_1])
                     |   ('/' >> factor          [ _val /= qi::_1])
                     )
                 ;

             factor =
                 +tok.number_digit               [ _val = qi::_1 ]
                 |  '('   >> expression          [ _val = qi::_1 ] >> ')'
                 |   ('-' >> factor              [ _val = neg(qi::_1)])
                 |   ('+' >> factor              [ _val = qi::_1 ] )
                 ;

             symsbols
                 = printLn
                 | comments
                 | class_definition
                 | expression
                 ;

             comments
                 = tok.cpcomment
                 | tok.c_comment
                 | tok.d_comment
                 ;

             printLn
                 = tok.printLn >> *comments >> tok.quoted_string
                 | tok.printLn >> tok.quoted_string
                 ;

             class_definition
                 = (tok.kw_class          >> *comments
                     >> tok.identifier    >> *comments
                     >> tok.kw_of         >> *comments
                     >> tok.identifier    >> *comments >> class_body
                     >> tok.kw_endclass)
                     [
                         qi::_val = phx::construct<print_testclass>(
                         phx::construct<std::string>(qi::_1),
                         phx::construct<std::string>(qi::_2))
                     ]
                 ;
             class_body
                 = *comments
                 ;

             start.name("start");
             symsbols.name("symsbols");
             comments.name("comments");
             expression.name("expression");
             term.name("term");
             factor.name("factor");
             printLn.name("printLn");
             class_definition.name("class_definition");
             class_body.name("class_body");

             BOOST_SPIRIT_DEBUG_NODE(start);
             BOOST_SPIRIT_DEBUG_NODE(symsbols);
             BOOST_SPIRIT_DEBUG_NODE(comments);
             BOOST_SPIRIT_DEBUG_NODE(printLn);
             BOOST_SPIRIT_DEBUG_NODE(class_definition);
             BOOST_SPIRIT_DEBUG_NODE(class_body);
             BOOST_SPIRIT_DEBUG_NODE(factor);
             BOOST_SPIRIT_DEBUG_NODE(term);
             BOOST_SPIRIT_DEBUG_NODE(expression);

             using namespace qi::labels;
             qi::on_error<qi::fail>
             (
                 start,
                 std::cout
                     << phx::val("Error! Expecting ")
                     << bs::_4                               // what failed?
                     << phx::val(" here: \"")
                     << phx::construct<std::string>(bs::_3, bs::_2)   // iterators to error-pos, end
                     << phx::val("\"")
                     << std::endl
             );
         }

         typedef qi::unused_type skipper_type;
         typedef qi::rule<Iterator, skipper_type> simple_rule;

         simple_rule start, symsbols, comments, printLn;
         simple_rule class_body;

         qi::rule<Iterator, print_testclass()> class_definition;
         qi::rule<Iterator, expression_ast()> expression, term, factor;
     };
}

bool parseText(std::string const& text)
{
     // std::string data(text.toStdString().c_str());
     std::string data(text) ;
     if (data.size() < 1) {
         // QMessageBox::information(0,"Error","No Data for parser.\nABORT.");
         std::cerr << "Error\n\tNo Data for parser.\nABORT.\n" ;
         return false;
     }

     using dBaseParser::expression_ast;
     using dBaseParser::ast_print;

     typedef std::string::iterator base_iterator_type;
     typedef lex::lexertl::token<
         base_iterator_type, boost::mpl::vector<char, int, std::size_t, std::string>
     > token_type;
     typedef lex::lexertl::actor_lexer<token_type> lexer_type;

     typedef dBaseParser::dbase_tokens<lexer_type> dbase_tokens;
     typedef dbase_tokens::iterator_type iterator_type;
     typedef dBaseParser::dbase_grammar<iterator_type, dbase_tokens::lexer_def> dbase_grammar;

     dbase_tokens  tokens;
     dbase_grammar dbase(tokens);

     base_iterator_type it = data.begin();
     iterator_type iter    = tokens.begin(it, data.end());
     iterator_type end     = tokens.end();

     expression_ast ast;
     ast_print  printer;

     bool r = qi::parse(iter, end, dbase, ast);

     if (r && iter == end) {
       // QMessageBox::information(w,"text parser","SUCCESS");
       std::cerr << "success\n\n" ;
       printer(ast);
     } else {
       // QMessageBox::information(w,"text parser","ERROR");
       std::cerr << "fail\n\n" ;
     }
     return 0;
}


int main() {
  parseText("2+3") ;
  return 0 ;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.