ack/lang/cem/cemcom/declar.g

537 lines
10 KiB
Plaintext
Raw Normal View History

/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
1986-03-10 13:07:55 +00:00
/* $Header$ */
/* DECLARATION SYNTAX PARSER */
{
#include "lint.h"
1991-11-08 15:12:28 +00:00
#include "dbsymtab.h"
#include <alloc.h>
1986-03-10 13:07:55 +00:00
#include "nobitfield.h"
#include "debug.h"
#include "arith.h"
#include "LLlex.h"
1988-08-19 13:55:22 +00:00
#include "label.h"
#include "code.h"
1986-03-10 13:07:55 +00:00
#include "idf.h"
#include "type.h"
#include "struct.h"
#include "field.h"
#include "decspecs.h"
#include "def.h"
1986-03-10 15:10:56 +00:00
#include "declar.h"
1986-03-10 13:07:55 +00:00
#include "label.h"
#include "expr.h"
#include "sizes.h"
1987-03-25 23:14:43 +00:00
#include "level.h"
#ifdef LINT
#include "l_lint.h"
#endif LINT
1986-03-10 13:07:55 +00:00
extern char options[];
}
/* 8 */
declaration
{struct decspecs Ds;}
:
{Ds = null_decspecs;}
decl_specifiers(&Ds)
[%default /* missing identifier derailed parser */
init_declarator_list(&Ds)
|
empty
]
1986-03-10 13:07:55 +00:00
';'
;
/* A `decl_specifiers' describes a sequence of a storage_class_specifier,
an unsigned_specifier, a size_specifier and a simple type_specifier,
which may occur in arbitrary order and each of which may be absent;
at least one of them must be present, however, since the totally
empty case has already be dealt with in `external_definition'.
This means that something like:
unsigned extern int short xx;
is perfectly good C.
1991-11-08 15:12:28 +00:00
1986-03-10 13:07:55 +00:00
On top of that, multiple occurrences of storage_class_specifiers,
unsigned_specifiers and size_specifiers are errors, but a second
type_specifier should end the decl_specifiers and be treated as
the name to be declared (see the thin ice in RM11.1).
Such a language is not easily expressed in a grammar; enumeration
of the permutations is unattractive. We solve the problem by
having a regular grammar for the "soft" items, handling the single
occurrence of the type_specifier in the grammar (we have no choice),
collecting all data in a `struct decspecs' and turning that data
structure into what we want.
1991-11-08 15:12:28 +00:00
1986-03-10 13:07:55 +00:00
The existence of declarations like
short typedef yepp;
makes all hope of writing a specific grammar for typedefs illusory.
*/
decl_specifiers /* non-empty */ (register struct decspecs *ds;)
1986-03-10 13:07:55 +00:00
/* Reads a non-empty decl_specifiers and fills the struct
decspecs *ds.
*/
:
[
other_specifier(ds)+
[%if (DOT != IDENTIFIER || AHEAD == IDENTIFIER)
/* the thin ice in R.M. 11.1 */
1986-03-10 13:07:55 +00:00
single_type_specifier(ds) other_specifier(ds)*
|
empty
]
|
single_type_specifier(ds) other_specifier(ds)*
]
{do_decspecs(ds);}
;
/* 8.1 */
other_specifier(register struct decspecs *ds;):
1986-03-10 13:07:55 +00:00
[ AUTO | STATIC | EXTERN | TYPEDEF | REGISTER ]
{ if (ds->ds_sc_given)
error("repeated storage class specifier");
1987-03-25 23:14:43 +00:00
ds->ds_sc_given = 1;
ds->ds_sc = DOT;
1986-03-10 13:07:55 +00:00
}
|
[ SHORT | LONG ]
{ if (ds->ds_size)
error("repeated size specifier");
1987-03-25 23:14:43 +00:00
ds->ds_size = DOT;
1986-03-10 13:07:55 +00:00
}
|
UNSIGNED
{ if (ds->ds_unsigned)
error("unsigned specified twice");
1987-03-25 23:14:43 +00:00
ds->ds_unsigned = 1;
1986-03-10 13:07:55 +00:00
}
;
/* 8.2 */
type_specifier(struct type **tpp;)
/* Used in struct/union declarations and in casts; only the
type is relevant.
*/
{struct decspecs Ds; Ds = null_decspecs;}
:
decl_specifiers(&Ds)
{
if (Ds.ds_sc_given)
error("storage class ignored");
if (Ds.ds_sc == REGISTER)
error("register ignored");
}
{*tpp = Ds.ds_type;}
;
single_type_specifier(register struct decspecs *ds;):
%default TYPE_IDENTIFIER /* this includes INT, CHAR, etc. */
1986-03-10 13:07:55 +00:00
{idf2type(dot.tk_idf, &ds->ds_type);}
|
IDENTIFIER
{
error("%s is not a type identifier", dot.tk_idf->id_text);
1988-08-19 13:55:22 +00:00
ds->ds_type = error_type;
if (dot.tk_idf->id_def) {
1988-08-19 13:55:22 +00:00
dot.tk_idf->id_def->df_type = error_type;
dot.tk_idf->id_def->df_sc = TYPEDEF;
}
}
1986-03-10 13:07:55 +00:00
|
struct_or_union_specifier(&ds->ds_type)
|
enum_specifier(&ds->ds_type)
;
/* 8.3 */
init_declarator_list(struct decspecs *ds;):
init_declarator(ds)
[ ',' init_declarator(ds) ]*
;
init_declarator(register struct decspecs *ds;)
1986-03-10 13:07:55 +00:00
{
struct declarator Dc;
}
:
{
Dc = null_declarator;
}
[
declarator(&Dc)
{
reject_params(&Dc);
declare_idf(ds, &Dc, level);
#ifdef LINT
lint_declare_idf(Dc.dc_idf, ds->ds_sc);
#endif LINT
1986-03-10 13:07:55 +00:00
}
1987-03-25 23:14:43 +00:00
[
initializer(Dc.dc_idf, ds->ds_sc)
|
{ code_declaration(Dc.dc_idf, (struct expr *) 0, level, ds->ds_sc); }
]
1986-03-10 13:07:55 +00:00
]
1988-08-19 13:55:22 +00:00
{
#ifdef LINT
add_auto(Dc.dc_idf);
#endif LINT
1988-08-19 13:55:22 +00:00
remove_declarator(&Dc);
}
1986-03-10 13:07:55 +00:00
;
1987-03-25 23:14:43 +00:00
/* 8.6: initializer */
initializer(struct idf *idf; int sc;)
{
struct expr *expr = (struct expr *) 0;
int globalflag = level == L_GLOBAL ||
1987-08-28 09:56:00 +00:00
(level >= L_LOCAL && sc == STATIC);
1987-03-25 23:14:43 +00:00
}
:
{ if (idf->id_def->df_type->tp_fund == FUNCTION) {
error("illegal initialization of function");
idf->id_def->df_type->tp_fund = ERRONEOUS;
1987-03-25 23:14:43 +00:00
}
if (level == L_FORMAL2)
warning("illegal initialization of formal parameter (ignored)");
1987-03-25 23:14:43 +00:00
}
'=' /* used to be optional because of V6 */
1988-08-19 13:55:22 +00:00
{
#ifdef LINT
lint_statement();
#endif LINT
1988-08-19 13:55:22 +00:00
if (globalflag) {
1987-03-25 23:14:43 +00:00
struct expr ex;
code_declaration(idf, &ex, level, sc);
1988-08-19 13:55:22 +00:00
}
1987-03-25 23:14:43 +00:00
}
initial_value(globalflag ? &(idf->id_def->df_type) : (struct type **)0,
&expr)
{ if (! globalflag) {
if (idf->id_def->df_type->tp_fund == FUNCTION) {
free_expression(expr);
expr = 0;
}
#ifdef DEBUG
print_expr("initializer-expression", expr);
#endif DEBUG
#ifdef LINT
change_state(idf, SET);
#endif LINT
1991-11-08 15:12:28 +00:00
#ifdef DBSYMTAB
if (options['g'] && level >= L_LOCAL && expr) {
db_line(expr->ex_file, (unsigned) expr->ex_line)
;
}
#endif /* DBSYMTAB */
code_declaration(idf, expr, level, sc);
1988-08-19 13:55:22 +00:00
}
1991-11-08 15:12:28 +00:00
#ifdef DBSYMTAB
if (options['g'] && globalflag) {
stb_string(idf->id_def, sc, idf->id_text);
}
#endif /* DBSYMTAB */
1988-08-19 13:55:22 +00:00
init_idf(idf);
1987-03-25 23:14:43 +00:00
}
;
1986-03-10 13:07:55 +00:00
/*
Functions yielding pointers to functions must be declared as, e.g.,
int (*hehe(par1, par2))() char *par1, *par2; {}
Since the function heading is read as a normal declarator,
we just include the (formal) parameter list in the declarator
description list dc.
*/
declarator(register struct declarator *dc;)
1986-03-10 13:07:55 +00:00
{
arith count;
struct formal *fm = 0;
1986-03-10 13:07:55 +00:00
}
:
primary_declarator(dc)
[
1986-03-10 13:07:55 +00:00
'('
formal_list(&fm) ? /* semantic check later... */
1986-03-10 13:07:55 +00:00
')'
{
add_decl_unary(dc, FUNCTION, (arith)0, fm);
fm = 0;
1986-03-10 13:07:55 +00:00
}
|
arrayer(&count)
{add_decl_unary(dc, ARRAY, count, NO_PARAMS);}
]*
|
'*' declarator(dc)
{add_decl_unary(dc, POINTER, (arith)0, NO_PARAMS);}
;
primary_declarator(register struct declarator *dc;) :
1986-03-10 13:07:55 +00:00
identifier(&dc->dc_idf)
|
'(' declarator(dc) ')'
;
arrayer(arith *sizep;)
{ struct expr *expr; }
:
'['
[
constant_expression(&expr)
{
1986-09-28 20:33:15 +00:00
check_array_subscript(expr);
1986-03-10 13:07:55 +00:00
*sizep = expr->VL_VALUE;
free_expression(expr);
}
|
empty
{ *sizep = (arith)-1; }
]
']'
;
formal_list (struct formal **fmp;)
1986-03-10 13:07:55 +00:00
:
formal(fmp) [ %persistent ',' formal(fmp) ]*
1986-03-10 13:07:55 +00:00
;
formal(struct formal **fmp;)
1986-03-10 13:07:55 +00:00
{struct idf *idf; }
:
identifier(&idf)
{
register struct formal *new = new_formal();
1991-11-08 15:12:28 +00:00
new->fm_idf = idf;
new->next = *fmp;
*fmp = new;
1986-03-10 13:07:55 +00:00
}
;
/* Change 2 */
enum_specifier(register struct type **tpp;)
1986-03-10 13:07:55 +00:00
{
struct idf *idf;
arith l = (arith)0;
}
:
ENUM
[
{declare_struct(ENUM, (struct idf *) 0, tpp);}
enumerator_pack(*tpp, &l)
|
identifier(&idf)
[
{declare_struct(ENUM, idf, tpp);}
enumerator_pack(*tpp, &l)
1991-11-08 15:12:28 +00:00
{
#ifdef DBSYMTAB
if (options['g']) {
stb_tag(idf->id_enum, idf->id_text);
}
#endif /*DBSYMTAB */
}
1986-03-10 13:07:55 +00:00
|
{apply_struct(ENUM, idf, tpp);}
empty
]
]
;
enumerator_pack(register struct type *tp; arith *lp;) :
1986-03-10 13:07:55 +00:00
'{'
enumerator(tp, lp)
[%while(AHEAD != '}') /* >>> conflict on ',' */
','
enumerator(tp, lp)
]*
','? /* optional trailing comma */
'}'
{tp->tp_size = int_size;}
/* fancy implementations that put small enums in 1 byte
or so should start here.
*/
;
enumerator(struct type *tp; arith *lp;)
{
struct idf *idf;
struct expr *expr;
}
:
identifier(&idf)
[
'='
constant_expression(&expr)
{
*lp = expr->VL_VALUE;
free_expression(expr);
}
]?
{declare_enum(tp, idf, (*lp)++);}
;
/* 8.5 */
struct_or_union_specifier(register struct type **tpp;)
1986-03-10 13:07:55 +00:00
{
int fund;
struct idf *idfX;
register struct idf *idf;
1986-03-10 13:07:55 +00:00
}
:
[ STRUCT | UNION ]
{fund = DOT;}
[
{
declare_struct(fund, (struct idf *)0, tpp);
}
struct_declaration_pack(*tpp)
|
identifier(&idfX) { idf = idfX; }
1986-03-10 13:07:55 +00:00
[
{
declare_struct(fund, idf, tpp);
(idf->id_struct->tg_busy)++;
}
struct_declaration_pack(*tpp)
{
(idf->id_struct->tg_busy)--;
1991-11-08 15:12:28 +00:00
#ifdef DBSYMTAB
if (options['g']) {
stb_tag(idf->id_struct, idf->id_text);
}
#endif /*DBSYMTAB */
1986-03-10 13:07:55 +00:00
}
|
{apply_struct(fund, idf, tpp);}
empty
]
]
;
struct_declaration_pack(register struct type *stp;)
1986-03-10 13:07:55 +00:00
{
struct sdef **sdefp = &stp->tp_sdef;
arith size = (arith)0;
}
:
/* The size is only filled in after the whole struct has
been read, to prevent recursive definitions.
*/
'{'
struct_declaration(stp, &sdefp, &size)+
'}'
{stp->tp_size = align(size, stp->tp_align);}
;
struct_declaration(struct type *stp; struct sdef ***sdefpp; arith *szp;)
{struct type *tp;}
:
type_specifier(&tp)
struct_declarator_list(tp, stp, sdefpp, szp)
[ /* in some standard UNIX compilers the semicolon
is optional, would you believe!
*/
';'
|
empty
{warning("no semicolon after declarator");}
]
;
1991-11-29 14:11:31 +00:00
struct_declarator_list(struct type *tp; struct type *stp;
1986-03-10 13:07:55 +00:00
struct sdef ***sdefpp; arith *szp;)
:
struct_declarator(tp, stp, sdefpp, szp)
[ ',' struct_declarator(tp, stp, sdefpp, szp) ]*
;
struct_declarator(struct type *tp; struct type *stp;
struct sdef ***sdefpp; arith *szp;)
{
struct declarator Dc;
struct field *fd = 0;
}
:
{
Dc = null_declarator;
}
[
declarator(&Dc)
{reject_params(&Dc);}
bit_expression(&fd)?
|
{Dc.dc_idf = gen_idf();}
bit_expression(&fd)
]
{add_sel(stp, declare_type(tp, &Dc), Dc.dc_idf, sdefpp, szp, fd);}
{remove_declarator(&Dc);}
;
bit_expression(struct field **fd;)
{ struct expr *expr; }
:
{
*fd = new_field();
}
':'
constant_expression(&expr)
{
(*fd)->fd_width = expr->VL_VALUE;
free_expression(expr);
#ifdef NOBITFIELD
error("bitfields are not implemented");
#endif NOBITFIELD
}
;
/* 8.7 */
cast(struct type **tpp;) {struct declarator Dc;} :
{Dc = null_declarator;}
'('
type_specifier(tpp)
abstract_declarator(&Dc)
')'
{*tpp = declare_type(*tpp, &Dc);}
{remove_declarator(&Dc);}
;
/* This code is an abject copy of that of 'declarator', for lack of
a two-level grammar.
*/
abstract_declarator(register struct declarator *dc;)
1986-03-10 13:07:55 +00:00
{arith count;}
:
primary_abstract_declarator(dc)
[
'(' ')'
{add_decl_unary(dc, FUNCTION, (arith)0, NO_PARAMS);}
|
arrayer(&count)
{add_decl_unary(dc, ARRAY, count, NO_PARAMS);}
]*
|
'*' abstract_declarator(dc)
{add_decl_unary(dc, POINTER, (arith)0, NO_PARAMS);}
;
primary_abstract_declarator(struct declarator *dc;) :
[%if (AHEAD == ')')
empty
|
'(' abstract_declarator(dc) ')'
]
;
empty:
;
/* 8.8 */
/* included in the IDENTIFIER/TYPE_IDENTIFIER mechanism */