Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / program.g
1 /*
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".
4  */
5 /* $Id: program.g,v 1.14 1994/06/27 08:01:53 ceriel Exp $ */
6 /* PROGRAM PARSER */
7
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
22         invalidated.
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
30         correct programs.
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.
34
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.
41 */
42
43 %lexical        LLlex;
44 %start          C_program, program;
45 %start          If_expr, control_if_expression;
46
47 {
48 #include        "lint.h"
49 #include        "nopp.h"
50 #include        "debug.h"
51 #include        <flt_arith.h>
52 #include        "arith.h"
53 #include        "LLlex.h"
54 #include        "idf.h"
55 #include        "label.h"
56 #include        "type.h"
57 #include        "declar.h"
58 #include        "decspecs.h"
59 #include        "code.h"
60 #include        "expr.h"
61 #include        "def.h"
62 #ifdef  LINT
63 #include        "l_lint.h"
64 #endif  /* LINT */
65
66 #ifndef NOPP
67 extern arith ifval;
68 #endif /* NOPP */
69
70 extern error();
71 }
72
73 control_if_expression
74         {
75                 struct expr *exprX;
76         }
77 :
78         constant_expression(&exprX)
79                 {
80 #ifndef NOPP
81                         register struct expr *expr = exprX;
82                         if (expr->ex_flags & EX_SIZEOF)
83                                 expr_error(expr,
84                                         "sizeof not allowed in preprocessor");
85                         ifval = expr->VL_VALUE;
86                         free_expression(expr);
87 #endif /* NOPP */
88                 }
89 ;
90
91 /* 3.7 */
92 program:
93         [%persistent external_definition]*
94         { unstack_world(); }
95 ;
96
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.
103         
104         A definition starts with a decl_specifiers, which contains things
105         like
106                 typedef int
107         which is implicitly repeated for every definition in the list, and
108         then for each identifier a declarator is given, of the form
109                 *a()
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
113         struct decspecs.
114
115         With the introduction of prototypes, extra problems for the scope
116         administration were introduced as well.  We can have, for example,
117         int x(double x);
118         and
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
131             begin_proc().
132 */
133
134 external_definition
135         {       struct decspecs Ds;
136                 struct  declarator Dc;
137         }
138 :
139         {       Ds = null_decspecs;
140                 Dc = null_declarator;
141         }
142         [ %if (DOT != IDENTIFIER || AHEAD == IDENTIFIER)
143                 decl_specifiers(&Ds)
144         |
145                 {do_decspecs(&Ds);}
146         ]
147         [
148                 declarator(&Dc)
149                 {
150                         declare_idf(&Ds, &Dc, level);
151 #ifdef  LINT
152                         lint_ext_def(Dc.dc_idf, Ds.ds_sc);
153 #endif  /* LINT */
154                 }
155                 [
156                         function(&Ds, &Dc)
157                 |
158                         {       if (! Ds.ds_sc_given && ! Ds.ds_typequal &&
159                                     Ds.ds_notypegiven) {
160                                         strict("declaration specifiers missing");
161                                 }
162                         }
163                         non_function(&Ds, &Dc)
164                 ]
165         |
166                 {       if (! Ds.ds_sc_given && ! Ds.ds_typequal &&
167                             Ds.ds_notypegiven) {
168                                 strict("declaration missing");
169                         }
170                 }
171                 ';'
172         ]
173         {remove_declarator(&Dc); flush_strings(); }
174 ;
175
176 non_function(register struct decspecs *ds; register struct declarator *dc;)
177 :
178         {       reject_params(dc);
179         }
180         [
181                 initializer(dc->dc_idf, ds->ds_sc)
182         |
183                 { code_declaration(dc->dc_idf, (struct expr *) 0, level, ds->ds_sc); }
184         ]
185         {
186 #ifdef  LINT
187                 lint_non_function_decl(ds, dc);
188 #endif  /* LINT */
189         }
190         [
191                 ','
192                 init_declarator(ds)
193         ]*
194         ';'
195 ;
196
197 /* 3.7.1 */
198 function(struct decspecs *ds; struct declarator *dc;)
199         {
200                 arith fbytes;
201                 register struct idf *idf = dc->dc_idf;
202         }
203 :
204         {
205 #ifdef  LINT
206                 lint_start_function();
207 #endif  /* LINT */
208                 idf_initialized(idf);
209                 stack_level();          /* L_FORMAL1 declarations */
210                 declare_params(dc);
211                 begin_proc(ds, idf);    /* sets global function info */
212                 stack_level();          /* L_FORMAL2 declarations */
213                 declare_protos(dc);
214         }
215         declaration*
216         {
217                 check_formals(idf, dc);         /* check style-mixtures */
218                 declare_formals(idf, &fbytes);
219 #ifdef  LINT
220                 lint_formals();
221 #endif  /* LINT */
222         }
223         compound_statement
224         {
225                 end_proc(fbytes);
226 #ifdef  LINT
227                 lint_implicit_return();
228 #endif  /* LINT */
229                 unstack_level();        /* L_FORMAL2 declarations */
230 #ifdef  LINT
231                 lint_end_formals();
232 #endif  /* LINT */
233                 unstack_level();        /* L_FORMAL1 declarations */
234 #ifdef  LINT
235                 lint_end_function();
236 #endif  /* LINT */
237         }
238 ;