help-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: User-defined classes in C++ Bison grammar


From: Wouter Beek
Subject: Re: User-defined classes in C++ Bison grammar
Date: Wed, 26 Dec 2018 15:39:30 +0100

Thanks for your help Akim!  I've been using Bison for a while now
without issues (except for building from sources, but I'll write a
separate email about that later).

---
Best regards,
Wouter Beek.

Email: address@hidden
WWW: https://triply.cc
Tel: +31647674624

On Tue, Dec 4, 2018 at 6:30 AM Akim Demaille <address@hidden> wrote:
>
> Hi Wouter!
>
> > Le 3 déc. 2018 à 22:38, Wouter Beek <address@hidden> a écrit :
> >
> > Dear Bison devs,
> >
> > I really like the recent developments in Bison 3.1 and 3.2 that improve the
> > support for modern C++ programming techniques.
>
> Thanks for saying this!
>
> > As a result, I'm writing my
> > first C++ Bison parser, but run into some issues that may or may not be
> > limitations of the current state of C++ support:
> >
> >  1. When I use a user-defined class in my Bison parser, I *must* define a
> > default constructor.  Is this an inherent requirement/limitation of Bison?
>
> Well, it's a limitation inherent to the Yacc model I guess.
>
> The way Yacc works is by letting the user write actions as code,
> involving the "input" ($1, $2, etc.), to compute and store the output
> in $$.
>
> exp
> : exp "+" exp { $$ = $1 + $3; }
> | exp "*" exp { $$ = $1 * $3; }
> | "number"    { $$ = $1; }
> ;
>
> So $$ must be constructed before we hand it over to the user action.
>
> In some other world, it would have been possible to require that
> the user action is not a statement, but an expression, something
> like
>
> exp
> : exp "+" exp ($1 + $3)
> | exp "*" exp ($1 * $3)
> | "number"    ($1)
> ;
>
> in which case I guess it would have been possible to build $$ instead
> of assigning to it.
>
> But anyway C, C++ and Java (the languages currently supported by Bison)
> offering a really poor support for rich expressions, I very much doubt
> there would be enough interest to justify this new model of actions.
>
> > While it is always possible to define a ‘dummy’ default constructor in
> > combination with using pointers for all member values, this sometimes makes
> > the code less logical/pretty.  Specifically, when I use a user-defined
> > class `A' with no default constructor the compiler emits the following
> > errors:
>
> I'll see if I can get a better error message in modern C++.
>
> >  2. When I use a user-defined sub-class (`B') of a virtual class (`A'), I
> > get the following errors during compilation.  Could it be that Bison does
> > not (yet) support sub-classes / virtual classes?
>
> I don't really see in what way Bison is concerned by the inheritance.
> Note that you have to use the super classes in your %type.  Don't do
> this (provide Sum derived from Exp):
>
> %type <Exp*> exp
> %type <Sum*> sum
> sum: exp "+" exp { $$ = new Sum{$1, $3}; }
> exp: sum
>
> do this:
>
> %type <Exp*> exp sum
> sum: exp "+" exp { $$ = new Sum{$1, $3}; }
> exp: sum
>
> This is ok too:
>
> %type <Exp*> exp
> %type <Sum*> sum
> sum: exp "+" exp { $$ = new Sum{$1, $3}; }
> exp: sum         { $$ = $1; }
>
> but your problem seems to be elsewhere.
>
> >   Or is this something one
> > can work around in some way?  I have an actual use case for this: I would
> > like to define a pure virtual `Term' with sub-classes `BlankNode', `Iri',
> > and `Literal'.
> >
> >     In file included from
> > /usr/include/c++/8/x86_64-redhat-linux/bits/c++allocator.h:33,
> >                      from /usr/include/c++/8/bits/allocator.h:46,
> >                      from /usr/include/c++/8/string:41,
> >                      from /usr/include/c++/8/bits/locale_classes.h:40,
> >                      from /usr/include/c++/8/bits/ios_base.h:41,
> >                      from /usr/include/c++/8/ios:42,
> >                      from /usr/include/c++/8/ostream:38,
> >                      from /usr/include/c++/8/iostream:39,
> >                      from parser.yy:14,
> >                      from parser.cpp:40:
>
> Guessing your grammar file from the compiler errors is too hard for me
> to be able to help you.
>
> Of course, if Exp is an abstract class (A in your case) you cannot
> do this:
>
> %type <Exp> exp
>
> you must go through a pointer (raw or not).
>
>
> >  3. I regularly run into compilation issues due to the definition of the
> > driver's methods `scan_begin()' and `scan_end()' in the parser source file
> > `scanner.ll'.  Is it possible to make these methods part of `driver.cpp'?
>
> It would make sense, sure, but these functions often need to call
> functions of the scanner that are not exposed in a header file.
> If it works for you to put them in the driver's implementation, that's
> fine by me.
>
>
> > The way in which the code is currently spread over files seems a bit
> > unorganized.
> >
> > PS: I have published the accompanying code over at
> > https://github.com/wouterbeek/bison-cpp
>
> Doh.  I should have started there...
>
> Well, I believe the problem is here:
>
> > class driver {
> > public:
> >   int parse(std::string& file_name);
> >   std::string file_name;
> >   yy::location location;
> >   bool trace_parser {false};
> >   bool trace_scanner {false};
> >   std::vector<A> values;        <=============
> >   void scan_begin();
> >   void scan_end();
> > };
>
> Don't try to make vectors of abstract classes.  You need a pointer
> or some indirection.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]