help-bison
[Top][All Lists]
Advanced

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

User-defined classes in C++ Bison grammar


From: Wouter Beek
Subject: User-defined classes in C++ Bison grammar
Date: Mon, 3 Dec 2018 22:38:30 +0100

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.  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?
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:

     parser.hpp:576:33: error: no matching constructor for initialization
of 'A'
           return *new (yyas_<T> ()) T ();
                                     ^
     parser.cpp:559:21: note: in instantiation of function template
specialization
           'yy::variant<32>::emplace<A>' requested here
             yylhs.value.emplace< A > ();
                         ^
     ./A.hpp:9:3: note: candidate constructor not viable: requires single
argument 'value', but no
           arguments were provided
       A(const std::string& value)
       ^
     ./A.hpp:7:7: note: candidate constructor (the implicit copy
constructor) not viable: requires
           1 argument, but 0 were provided
     class A {
           ^
     ./A.hpp:7:7: note: candidate constructor (the implicit move
constructor) not viable: requires
           1 argument, but 0 were provided

  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?  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:
     /usr/include/c++/8/ext/new_allocator.h: In instantiation of ‘void
__gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = A;
_Args = {const A&}; _Tp = A]’:
     /usr/include/c++/8/bits/alloc_traits.h:475:4:   required from ‘static
void std::allocator_traits<std::allocator<_CharT>
>::construct(std::allocator_traits<std::allocator<_CharT>
>::allocator_type&, _Up*, _Args&& ...) [with _Up = A; _Args = {const A&};
_Tp = A; std::allocator_traits<std::allocator<_CharT> >::allocator_type =
std::allocator<A>]’
     /usr/include/c++/8/bits/stl_vector.h:1079:30:   required from ‘void
std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = A;
_Alloc = std::allocator<A>; std::vector<_Tp, _Alloc>::value_type = A]’
     parser.yy:40:56:   required from here
     /usr/include/c++/8/ext/new_allocator.h:136:4: error: invalid
new-expression of abstract class type ‘A’
       { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     In file included from B.hpp:6,
                      from parser.yy:17,
                      from parser.cpp:40:
     A.hpp:7:7: note:   because the following virtual functions are pure
within ‘A’:
      class A {
            ^
     A.hpp:10:25: note: ‘virtual std::ostream& A::print(std::ostream&)
const’
        virtual std::ostream& print(std::ostream& os) const = 0;
                              ^~~~~
     In file included from /usr/include/c++/8/vector:62,
                      from parser.yy:16,
                      from parser.cpp:40:
     /usr/include/c++/8/bits/stl_construct.h: In instantiation of ‘void
std::_Construct(_T1*, _Args&& ...) [with _T1 = A; _Args = {A}]’:
     /usr/include/c++/8/bits/stl_uninitialized.h:83:18:   required from
‘static _ForwardIterator
std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator,
_InputIterator, _ForwardIterator) [with _InputIterator =
std::move_iterator<A*>; _ForwardIterator = A*; bool _TrivialValueTypes =
false]’
     /usr/include/c++/8/bits/stl_uninitialized.h:134:15:   required from
‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator,
_ForwardIterator) [with _InputIterator = std::move_iterator<A*>;
_ForwardIterator = A*]’
     /usr/include/c++/8/bits/stl_uninitialized.h:289:37:   required from
‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator,
_InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with
_InputIterator = std::move_iterator<A*>; _ForwardIterator = A*; _Tp = A]’
     /usr/include/c++/8/bits/stl_uninitialized.h:311:2:   required from
‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator,
_InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = A*;
_ForwardIterator = A*; _Allocator = std::allocator<A>]’
     /usr/include/c++/8/bits/vector.tcc:447:6:   required from ‘void
std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp,
_Alloc>::iterator, _Args&& ...) [with _Args = {const A&}; _Tp = A; _Alloc =
std::allocator<A>; std::vector<_Tp, _Alloc>::iterator =
__gnu_cxx::__normal_iterator<A*, std::vector<A> >; typename
std::_Vector_base<_Tp, _Alloc>::pointer = A*]’
     /usr/include/c++/8/bits/stl_vector.h:1085:4:   required from ‘void
std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = A;
_Alloc = std::allocator<A>; std::vector<_Tp, _Alloc>::value_type = A]’
     parser.yy:40:56:   required from here
     /usr/include/c++/8/bits/stl_construct.h:75:7: error: invalid
new-expression of abstract class type ‘A’
          { ::new(static_cast<void*>(__p))
_T1(std::forward<_Args>(__args)...); }

^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  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'?
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

---
Best regards,
Wouter Beek.

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


reply via email to

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