123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540 |
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /* $Id$ */
- /* DECLARATION SYNTAX PARSER */
- {
- #include "lint.h"
- #include "dbsymtab.h"
- #include <alloc.h>
- #include "nobitfield.h"
- #include "debug.h"
- #include "arith.h"
- #include "LLlex.h"
- #include "label.h"
- #include "code.h"
- #include "idf.h"
- #include "type.h"
- #include "struct.h"
- #include "field.h"
- #include "decspecs.h"
- #include "def.h"
- #include "declar.h"
- #include "label.h"
- #include "expr.h"
- #include "sizes.h"
- #include "level.h"
- #ifdef LINT
- #include "l_lint.h"
- #endif /* LINT */
- extern char options[];
- }
- /* 8 */
- declaration
- {struct decspecs Ds;}
- :
- {Ds = null_decspecs;}
- decl_specifiers(&Ds)
- [%default /* missing identifier derailed parser */
- init_declarator_list(&Ds)
- |
- empty
- ]
- ';'
- ;
- /* 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.
- 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.
- 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;)
- /* 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 */
- 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;):
- [ AUTO | STATIC | EXTERN | TYPEDEF | REGISTER ]
- { if (ds->ds_sc_given)
- error("repeated storage class specifier");
- ds->ds_sc_given = 1;
- ds->ds_sc = DOT;
- }
- |
- [ SHORT | LONG ]
- { if (ds->ds_size)
- error("repeated size specifier");
- ds->ds_size = DOT;
- }
- |
- UNSIGNED
- { if (ds->ds_unsigned)
- error("unsigned specified twice");
- ds->ds_unsigned = 1;
- }
- ;
- /* 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. */
- {idf2type(dot.tk_idf, &ds->ds_type);}
- |
- %erroneous
- IDENTIFIER
- {
- error("%s is not a type identifier", dot.tk_idf->id_text);
- ds->ds_type = error_type;
- if (dot.tk_idf->id_def) {
- dot.tk_idf->id_def->df_type = error_type;
- dot.tk_idf->id_def->df_sc = TYPEDEF;
- }
- }
- |
- %illegal
- IDENTIFIER
- |
- 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;)
- {
- 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 */
- }
- [
- initializer(Dc.dc_idf, ds->ds_sc)
- |
- { code_declaration(Dc.dc_idf, (struct expr *) 0, level, ds->ds_sc); }
- ]
- ]
- {
- #ifdef LINT
- add_auto(Dc.dc_idf);
- #endif /* LINT */
- remove_declarator(&Dc);
- }
- ;
- /* 8.6: initializer */
- initializer(struct idf *idf; int sc;)
- {
- struct expr *expr = (struct expr *) 0;
- int globalflag = level == L_GLOBAL ||
- (level >= L_LOCAL && sc == STATIC);
- }
- :
- { if (idf->id_def->df_type->tp_fund == FUNCTION) {
- error("illegal initialization of function");
- idf->id_def->df_type->tp_fund = ERRONEOUS;
- }
- if (level == L_FORMAL2)
- warning("illegal initialization of formal parameter (ignored)");
- }
- '=' /* used to be optional because of V6 */
- {
- #ifdef LINT
- lint_statement();
- #endif /* LINT */
- if (globalflag) {
- struct expr ex;
- code_declaration(idf, &ex, level, sc);
- }
- }
- 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 */
- #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);
- }
- #ifdef DBSYMTAB
- if (options['g'] && globalflag) {
- stb_string(idf->id_def, sc, idf->id_text);
- }
- #endif /* DBSYMTAB */
- init_idf(idf);
- }
- ;
- /*
- 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;)
- {
- arith count;
- struct formal *fm = 0;
- }
- :
- primary_declarator(dc)
- [
- '('
- formal_list(&fm) ? /* semantic check later... */
- ')'
- {
- add_decl_unary(dc, FUNCTION, (arith)0, fm);
- fm = 0;
- }
- |
- 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;) :
- identifier(&dc->dc_idf)
- |
- '(' declarator(dc) ')'
- ;
- arrayer(arith *sizep;)
- { struct expr *expr; }
- :
- '['
- [
- constant_expression(&expr)
- {
- check_array_subscript(expr);
- *sizep = expr->VL_VALUE;
- free_expression(expr);
- }
- |
- empty
- { *sizep = (arith)-1; }
- ]
- ']'
- ;
- formal_list (struct formal **fmp;)
- :
- formal(fmp) [ %persistent ',' formal(fmp) ]*
- ;
- formal(struct formal **fmp;)
- {struct idf *idf; }
- :
- identifier(&idf)
- {
- register struct formal *new = new_formal();
- new->fm_idf = idf;
- new->next = *fmp;
- *fmp = new;
- }
- ;
- /* Change 2 */
- enum_specifier(register struct type **tpp;)
- {
- 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)
- {
- #ifdef DBSYMTAB
- if (options['g']) {
- stb_tag(idf->id_enum, idf->id_text);
- }
- #endif /*DBSYMTAB */
- }
- |
- {apply_struct(ENUM, idf, tpp);}
- empty
- ]
- ]
- ;
- enumerator_pack(register struct type *tp; arith *lp;) :
- '{'
- 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;)
- {
- int fund;
- struct idf *idfX;
- register struct idf *idf;
- }
- :
- [ STRUCT | UNION ]
- {fund = DOT;}
- [
- {
- declare_struct(fund, (struct idf *)0, tpp);
- }
- struct_declaration_pack(*tpp)
- |
- identifier(&idfX) { idf = idfX; }
- [
- {
- declare_struct(fund, idf, tpp);
- (idf->id_struct->tg_busy)++;
- }
- struct_declaration_pack(*tpp)
- {
- (idf->id_struct->tg_busy)--;
- #ifdef DBSYMTAB
- if (options['g']) {
- stb_tag(idf->id_struct, idf->id_text);
- }
- #endif /*DBSYMTAB */
- }
- |
- {apply_struct(fund, idf, tpp);}
- empty
- ]
- ]
- ;
- struct_declaration_pack(register struct type *stp;)
- {
- 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");}
- ]
- ;
- struct_declarator_list(struct type *tp; struct type *stp;
- 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;)
- {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 */
|