0

In the boost::spirit documentation, grammars are defined by using struct. For example,

template <typename Iterator>
struct my_grammar
    : qi::grammar<Iterator, qi::locals<std::string>, ascii::space_type >
{
    my_grammar() 
      : my_grammar::base_type(start, "start")
    {
       // using this and that
       // rules and action etc.
    }
 };

I am wondering if I can write it using class (if not then why?). I am doing this.

In header file

 template<typename Iterator>
 class my_grammar
 {
     public:
        my_grammar();
        // rules declaration goes here.
  };

and in source file

 template<typename Iterator>
 my_grammar::my_grammar()
       : qi::grammar::base_type(start, "start")
  {
        // write grammar and actions.
  }

Name-space has been shorted using typedefs. I am writing using above method and compiler is giving me too much of errors which are hard to understand. Is it fundamentally ok or I am doing something odd?

Can you point me to some code where someone has used class instead of struct to write grammar?

UPDATE :

I am not able to link now. It says that undefined reference todimacs_grammar<__gnu_cxx::__normal_iterator, std::allocator > > >::my_grammar()` . The problem is that while using struct, I was writing

 my_grammar() 
  : my_grammar::base_type(start, "start")

I am not sure how to write equivalent class declaration and definition for this?

Dilawar
  • 5,438
  • 9
  • 45
  • 58

2 Answers2

4

Classes & structs are equivalent except for the default visibility of members (public for structs, private for classes).

It looks like you forgot to make your my_grammar class derive from the qi::grammar<> base class that you used for your struct. Thus, the base class initializer in your class constructor implementation will look like nonsense to the compiler.

In short, change your class definition to:

template<typename Iterator>
class my_grammar
  : public qi::grammar<Iterator, qi::locals<std::string>, ascii::space_type >
{
  public:
    my_grammar();
    // rules declaration goes here.
};

(Note the added public inheritance).

EDIT (re: linker errror):

With templates, generally the implementation should live in the header file rather than a source (.cpp) file (though there are exceptions). In your header file, the constructor definition syntax should be:

template<typename Iterator>
my_grammar<Iterator>::my_grammar()
  : qi::grammar::base_type(start, "start")
{
    // write grammar and actions.
}

(difference is the <Iterator> bit as pointed out by Ken Wayne VanderLinde below).

Drew Hall
  • 28,429
  • 12
  • 61
  • 81
  • Also note Ken Wayne VanderLinde's answer below--I didn't notice the missing template parameter in the constructor definition but don't want to step on his toes here.... – Drew Hall Jan 05 '12 at 21:52
  • It is almost working except for some linking problem. Thank you! I'll accept it as soon as I get it working. 'public' did the trick. – Dilawar Jan 05 '12 at 22:00
  • I have added an update to my problem. Please see if you can help! – Dilawar Jan 05 '12 at 23:05
  • @Dilawar: Don't put templates in .cpp files. Search SO, there are many questions on this. – Xeo Jan 05 '12 at 23:23
0

The only problem I see is that

template my_grammar::my_grammar()
         : qi::grammar::base_type(start, "start")
{
      // write grammar and actions.
}

should be

template<typename Iterator>
my_grammer<Iterator>::my_grammer()
: my_grammar<Iterator>::base_type(start, "start")
{
}

if you want it to be the same as for your struct.

Also, your class should probably be like

template <typename Iterator>
class my_grammar
    : public qi::grammar<Iterator, qi::locals<std::string>, ascii::space_type >
Ken Wayne VanderLinde
  • 18,915
  • 3
  • 47
  • 72