Re: boost and stl problem - std::string

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

The new code:
I have problem with visitor - at original code on line 178
the application can be compiled, but if I give input data:
2+3
SUCCESS came out, but printer(ast) produce infinite loop,
and the application crash :-(

TIA
Jens

#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()(qi::info::nil) const {}
         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(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();

     expression_ast ast;
     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
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.