[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.
Descriptions:
- 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
file:
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) \
dynamic_cast<cast_name&>(*x[n-stack_offset].data())
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
n-stack_offset
expression).
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 ();
break;
add
case tok_typed:
if (typed)
complain (_("multiple %s declarations"), "%union or %typed");
typed = 1;
break;
- 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)");
else
obstack_fgrow1 (oout, "YYVAL_CAST(yyval, %s)", type_name);
if (!type_name && typed)
complain (_("$$ of `%s' has no declared type"),
rule->sym->tag);
}
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);
else
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);
}
else
...
- In bison.simple, write in the segment:
#ifndef YYVAL
# define YYVAL(x) x
#endif
#ifndef YYVAL_CAST
# define YYVAL_CAST(x, cast_name) x.cast_name
#endif
#ifndef YYVSP
# define YYVSP(x, n, stack_offset) x[n-stack_offset]
#endif
#ifndef YYVSP_CAST
# define YYVSP_CAST(x, n, stack_offset, cast_name) x[n-stack_offset].cast_name
#endif
Hans Aberg
- Bison, C++, types, and all that,
Hans Aberg <=