2

I'am trying to attach a simple semantic action to my grammar using boost spirit.

This is my code:

#define  BOOST_SPIRIT_NO_REGEX_LIB

#include "regex.h"
#include "spirit.hpp"
#include "spirit/actor/assign_actor.hpp"
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/support_utree.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/config/warning_disable.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <string>


using namespace std;
using namespace boost::spirit;
using boost::phoenix::bind;



    // A plain function
    void dummy( )
    {
    int i=20;
        std::cout << i << std::endl;
    }





struct my_enum : public grammar<my_enum>
    {

    template <typename ScannerT>
      struct definition
        {
        definition(my_enum const& self)
          { 

          enum_specifier = enum_p >> '{' >> enum_list >> '}' [boost::phoenix::bind(dummy)];
          enum_p = str_p("enum");
          enum_list = +id_p >> *(',' >> +id_p);
          id_p = range_p('a','z');
          }

          rule<ScannerT> enum_specifier, enum_p, enum_list, id_p;
          rule<ScannerT> const& start() const { return enum_specifier; }
        };
    };

string input = "enum { ah, bk, ss  }";

int main ()
  {     
  my_enum e;
  int status = parse(input.c_str(), e, space_p).hit;
  cout << status << endl;
  return 0;
}

I get an infinite error that I am not able to understand. COuld someone can give me some advice/Example about how to map semantic functions?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Franconet
  • 41
  • 5
  • What is an infinite error? Why not post the relevant parts/in full? Also, I smell [XY problem](http://xyproblem.info/), I see nothing there that calls for a semantic action. – sehe Jun 30 '16 at 09:20
  • A very long (in terms of line) error difficult to post here on stackoverflow. I just want to associate a routine with enum_specifier detection. I made some research on google, but i found nothing that is equal to my case. I tried to calls semantic actions here: [boost::phoenix::bind(dummy)] – Franconet Jun 30 '16 at 09:24
  • Not here, "test.cpp|4 col 22| fatal error: spirit.hpp: No such file or directory" – sehe Jun 30 '16 at 09:28
  • @sehe Yes, probably I am confused. My final goal is to create a language translator. The source language contains enum and classes. So I would like to start creating a parser that can recognize enum structure and his name/elements and print something differents out. Example: INPUT: enum pippo { pluto=0, dog}; --> OUTPUT: enum pippo { PIPPO_pluto=0, PIPPO_dog=1}; Since, in a second step, the parser will become more complicated. I would like to have a different couple of parser/output function for every kind of object. How can i modify your code to move out output function? – Franconet Jun 30 '16 at 09:46
  • 1
    this makes me cry: `using namespace std; using namespace boost::spirit; using boost::phoenix::bind;` – Chris Beck Jun 30 '16 at 18:40

1 Answers1

4

I'm not sure what to make of this example. You combine pieces of Spirit "Classical" v1 (obsolete for over a decade), Karma headers (that's Spirit V2 and has nothing to do with parsing) and then some things Utree (that's V2-only and deprecated.

And then Boost Lambda and Boost Phoenix too, for good measure? Oh. Aaaaand the kitchen sink Boost Bind.

Then you mix all namespaces using

using namespace std;
using namespace boost::spirit;

I'm not sure what you expect to happen.

Let me read you sample and see whether I can come up with a fixed version.


10 minutes down the road:


Spirit Qi Demo

I'm assuming you really want to parse those values, and you were going to use the semantic action to store them (in a vector, e.g.).

Here's the Qi version that leverages

  1. automatic attribute propagation (Boost Spirit: "Semantic actions are evil"?)

  2. skippers (Boost spirit skipper issues)

  3. List operator (%)

Live On Coliru

#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

template<typename Iterator, typename Skipper = qi::space_type>
struct my_enum : public qi::grammar<Iterator, std::vector<std::string>(), Skipper> {

    my_enum() : my_enum::base_type(enum_specifier)
    {
        id_p           = +qi::alpha;
        enum_specifier = qi::lit("enum") >> '{' >> (id_p % ',') >> '}';
    }

  private:
    qi::rule<Iterator, std::vector<std::string>(), Skipper> enum_specifier;
    // lexeme (no skipper):
    qi::rule<Iterator, std::string()> id_p;
};

int main() {
    typedef std::string::const_iterator Iterator;

    std::string const input = "enum { ah, bk, ss  }";
    my_enum<Iterator> parser;

    std::vector<std::string> parsed;

    Iterator iter = input.begin(), end = input.end();
    bool ok = qi::phrase_parse(iter, end, parser, qi::space, parsed);
    if (ok) {
        std::cout << "Parse succes\n";
        for (auto& value : parsed)
        {
            std::cout << " -- " << value << "\n";
        }
    } else {
        std::cout << "Parse succes\n";
    }

    if (iter != end) {
        std::cout << "Remaining unparsed input: '" << std::string(iter, end) << "'\n";
    }

    return ok? 0 : 1;
}

Prints

Parse succes
 -- ah
 -- bk
 -- ss
Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633