[Top][All Lists]

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

Bison, C++, types, and all that

From: Hans Aberg
Subject: Bison, C++, types, and all that
Date: Fri, 21 Dec 2001 01:30:28 +0100

As union's under C++ cannot contain classes with non-trivial constructors,
I started to think about a replacement for Bison's %union option that can
be used with a C++ polymorphic variable. I found a very simple patch, which
also generalizes the %union option. It might be implemented as an
experimental option once 1.31 has been releseased, because one can then
start experimenting with C++ constructions.


- I introduce a new option %typed, which indicates that nonterminals must
be typed, but does nothing else; a slimmed down %union option thus. One
should be able to have at most one %typed or %union option in a program.

- I introduce four macros YYVAL, YYVAL_CAST, YYVSP, YYVSP_CAST which are
used to write out the $ variable variables in the actions of the generated
  When:                     Macro written:
  $$ untyped                YYVAL(yyval)
  $$ typed to cast_name     YYVAL_CAST(yyval, cast_name)
  $n untyped                YYVSP(yyvsp, n, stack_offset)
  $n typed to cast_name     YYVSP_CAST(yyvsp, n, stack_offset, cast_name)

The motivation is this:

The definitions for untyped and %union typed variables:
#define YYVAL(x) x
#define YYVAL_CAST(x, cast_name) x.cast_name
#define YYVSP(x, n, stack_offset) x[n-stack_offset]
#define YYVSP_CAST(x, n, stack_offset, cast_name) x[n-stack_offset].cast_name

But the definitions for a C++ polymorphic (object) class, still using old
Bison stacks, might typically be:
#define YYVAL_CAST(x, cast_name) dynamic_cast<cast_name&>(*x.data())
#define YYVSP_CAST(x, n, stack_offset, cast_name) \

In addition, when replacing the old Bison stack with say std::stack, one
may need to redefine these macros further (the x[...] syntax and the

So I was led to introduce those four macros.

The implementation is easy:

- File lex.c, struct percent_table_struct percent_table[], after the
"union" line, add:
  { "typed",            NULL,                   tok_typed },

- File lex.h, typedef enum token_e, after tok_union, add tok_typed.

- File reader.c:
 - In read_declarations(), after
          case tok_union:
              parse_union_decl ();
            case tok_typed:
              if (typed)
                complain (_("multiple %s declarations"), "%union or %typed");
              typed = 1;

 - In parse_union_decl(), change line in beginning to:
   if (typed)
    complain (_("multiple %s declarations"), "%union or %typed");
(adding the %typed complaint).

 - In copy_dollar(), change the $$, $n write-out segment to:
  if (c == '$')
    if (!type_name)
            type_name = get_type_name (0, rule);
    if (!type_name)
      obstack_sgrow (oout, "YYVAL(yyval)");
      obstack_fgrow1 (oout, "YYVAL_CAST(yyval, %s)", type_name);

    if (!type_name && typed)
        complain (_("$$ of `%s' has no declared type"),
  else if (isdigit (c) || c == '-')
      int n;
      ungetc (c, fin);
      n = read_signed_integer (fin);

      if (!type_name && n > 0)
        type_name = get_type_name (n, rule);

      if (!type_name)
        obstack_fgrow2 (oout, "YYVSP(yyvsp, %d, %d)", n, stack_offset);
        obstack_fgrow3 (oout, "YYVSP_CAST(yyvsp, %d, %d, %s)", \
          n, stack_offset, type_name);

      if (!type_name && typed)
        complain (_("$%d of `%s' has no declared type"),
                  n, rule->sym->tag);

- In bison.simple, write in the segment:
#ifndef YYVAL
# define YYVAL(x) x
#ifndef YYVAL_CAST
# define YYVAL_CAST(x, cast_name) x.cast_name
#ifndef YYVSP
# define YYVSP(x, n, stack_offset) x[n-stack_offset]
#ifndef YYVSP_CAST
# define YYVSP_CAST(x, n, stack_offset, cast_name) x[n-stack_offset].cast_name

  Hans Aberg

reply via email to

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