2 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 * See the copyright notice in the ACK home directory, in the file "Copyright".
5 /* $Id: program.g,v 1.14 1994/06/27 08:01:53 ceriel Exp $ */
8 /* The presence of typedef declarations renders it impossible to
9 make a context-free grammar of C. Consequently we need
10 context-sensitive parsing techniques, the simplest one being
11 a subtle cooperation between the parser and the lexical scanner.
12 The lexical scanner has to know whether to return IDENTIFIER
13 or TYPE_IDENTIFIER for a given tag, and it obtains this information
14 from the definition list, as constructed by the parser.
15 The present grammar is essentially LL(2), and is processed by
16 a parser generator which accepts LL(1) with tie breaking rules
17 in C, of the form %if(cond) and %while(cond). To solve the LL(1)
18 ambiguities, the lexical scanner does a one symbol look-ahead.
19 This symbol, however, cannot always be correctly assessed, since
20 the present symbol may cause a change in the definition list
21 which causes the identification of the look-ahead symbol to be
23 The lexical scanner relies on the parser (or its routines) to
24 detect this situation and then update the look-ahead symbol.
25 An alternative approach would be to reassess the look-ahead symbol
26 in the lexical scanner when it is promoted to dot symbol. This
27 would be more beautiful but less correct, since then for a short
28 while there would be a discrepancy between the look-ahead symbol
29 and the definition list; I think it would nevertheless work in
31 A third solution would be to enter the identifier as soon as it
32 is found; its storage class is then known, although its full type
33 isn't. We would have to fill that in afterwards.
35 At block exit the situation is even worse. Upon reading the
36 closing brace, the names declared inside the function are cleared
37 from the name list. This action may expose a type identifier that
38 is the same as the identifier in the look-ahead symbol. This
39 situation certainly invalidates the third solution, and casts
40 doubts upon the second.
44 %start C_program, program;
45 %start If_expr, control_if_expression;
51 #include <flt_arith.h>
78 constant_expression(&exprX)
81 register struct expr *expr = exprX;
82 if (expr->ex_flags & EX_SIZEOF)
84 "sizeof not allowed in preprocessor");
85 ifval = expr->VL_VALUE;
86 free_expression(expr);
93 [%persistent external_definition]*
97 /* A C identifier definition is remarkable in that it formulates
98 the declaration in a way different from most other languages:
99 e.g., rather than defining x as a pointer-to-integer, it defines
100 *x as an integer and lets the compiler deduce that x is actually
101 pointer-to-integer. This has profound consequences, both for the
102 structure of an identifier definition and for the compiler.
104 A definition starts with a decl_specifiers, which contains things
107 which is implicitly repeated for every definition in the list, and
108 then for each identifier a declarator is given, of the form
110 or so. The decl_specifiers is kept in a struct decspecs, to be
111 used again and again, while the declarator is stored in a struct
112 declarator, only to be passed to declare_idf together with the
115 With the introduction of prototypes, extra problems for the scope
116 administration were introduced as well. We can have, for example,
119 int x(double x) { ... use(x) ... }
120 In the first case, the parameter name can be forgotten, whereas in
121 the second case, the parameter should have a block scope. The
122 problem lies in the fact that the parameter's type is known before
123 the type of the function, which causes the def structure to be on
124 the end of the list. Our solution is as follows:
125 1- In case of a declaration, throw the parameter identifier away
126 before the declaration of the outer x.
127 2- In case of a definition, the function begin_proc() changes the
128 def list for the identifier. This means that declare_idf()
129 contains an extra test in case we already saw a declaration of
130 such a function, because this function is called before
135 { struct decspecs Ds;
136 struct declarator Dc;
139 { Ds = null_decspecs;
140 Dc = null_declarator;
142 [ %if (DOT != IDENTIFIER || AHEAD == IDENTIFIER)
150 declare_idf(&Ds, &Dc, level);
152 lint_ext_def(Dc.dc_idf, Ds.ds_sc);
158 { if (! Ds.ds_sc_given && ! Ds.ds_typequal &&
160 strict("declaration specifiers missing");
163 non_function(&Ds, &Dc)
166 { if (! Ds.ds_sc_given && ! Ds.ds_typequal &&
168 strict("declaration missing");
173 {remove_declarator(&Dc); flush_strings(); }
176 non_function(register struct decspecs *ds; register struct declarator *dc;)
181 initializer(dc->dc_idf, ds->ds_sc)
183 { code_declaration(dc->dc_idf, (struct expr *) 0, level, ds->ds_sc); }
187 lint_non_function_decl(ds, dc);
198 function(struct decspecs *ds; struct declarator *dc;)
201 register struct idf *idf = dc->dc_idf;
206 lint_start_function();
208 idf_initialized(idf);
209 stack_level(); /* L_FORMAL1 declarations */
211 begin_proc(ds, idf); /* sets global function info */
212 stack_level(); /* L_FORMAL2 declarations */
217 check_formals(idf, dc); /* check style-mixtures */
218 declare_formals(idf, &fbytes);
227 lint_implicit_return();
229 unstack_level(); /* L_FORMAL2 declarations */
233 unstack_level(); /* L_FORMAL1 declarations */