1 /*
2 * Copyright (c) 1985 Sun Microsystems, Inc.
3 * Copyright (c) 1980 The Regents of the University of California.
4 * Copyright (c) 1976 Board of Trustees of the University of Illinois.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by the University of California, Berkeley, the University of Illinois,
13 * Urbana, and Sun Microsystems, Inc. The name of either University
14 * or Sun Microsystems may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 */
20
21 #ifndef lint
22 static char sccsid[] = "@(#)parse.c 5.8 (Berkeley) 9/15/88";
23 #endif /* not lint */
24
25 #include "indent_globs.h"
26
27 struct parser_state *parser_state_tos;
28
29 /* like ++parser_state_tos->tos but checks for stack overflow and extends
30 stack if necessary. */
31 static int
inc_pstack()32 inc_pstack ()
33 {
34 if (++parser_state_tos->tos >= parser_state_tos->p_stack_size)
35 {
36 parser_state_tos->p_stack_size *= 2;
37 parser_state_tos->p_stack = (enum codes *)
38 xrealloc (parser_state_tos->p_stack,
39 parser_state_tos->p_stack_size * sizeof (enum codes));
40 parser_state_tos->il = (int *)
41 xrealloc (parser_state_tos->il,
42 parser_state_tos->p_stack_size * sizeof (int));
43 parser_state_tos->cstk = (int *)
44 xrealloc (parser_state_tos->cstk,
45 parser_state_tos->p_stack_size * sizeof (int));
46 }
47 return parser_state_tos->tos;
48 }
49
50 void
parse(tk)51 parse(tk)
52 enum codes tk; /* the code for the construct scanned */
53 {
54 int i;
55
56 #ifdef debug
57 printf("%2d - %s\n", tk, token);
58 #endif
59
60 while (parser_state_tos->p_stack[parser_state_tos->tos] == ifhead && tk != elselit) {
61 /* true if we have an if without an else */
62 parser_state_tos->p_stack[parser_state_tos->tos] = stmt; /* apply the if(..) stmt ::= stmt
63 * reduction */
64 reduce(); /* see if this allows any reduction */
65 }
66
67
68 switch (tk) { /* go on and figure out what to do with the
69 * input */
70
71 case decl: /* scanned a declaration word */
72 parser_state_tos->search_brace = btype_2;
73 /* indicate that following brace should be on same line */
74 if (parser_state_tos->p_stack[parser_state_tos->tos] != decl) { /* only put one declaration
75 * onto stack */
76 break_comma = true; /* while in declaration, newline should be
77 * forced after comma */
78 parser_state_tos->p_stack[inc_pstack()] = decl;
79 parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
80
81 if (ljust_decl) {/* only do if we want left justified
82 * declarations */
83 parser_state_tos->ind_level = 0;
84 for (i = parser_state_tos->tos - 1; i > 0; --i)
85 if (parser_state_tos->p_stack[i] == decl)
86 /* indentation is number of declaration levels deep
87 we are times spaces per level */
88 parser_state_tos->ind_level += ind_size;
89 parser_state_tos->i_l_follow = parser_state_tos->ind_level;
90 }
91 }
92 break;
93
94 case ifstmt: /* scanned if (...) */
95 if (parser_state_tos->p_stack[parser_state_tos->tos] == elsehead
96 && else_if) /* "else if ..." */
97 parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos];
98 case dolit: /* 'do' */
99 case forstmt: /* for (...) */
100 inc_pstack();
101 parser_state_tos->p_stack[parser_state_tos->tos] = tk;
102 parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level = parser_state_tos->i_l_follow;
103 parser_state_tos->i_l_follow += ind_size; /* subsequent statements should be indented 1 */
104 parser_state_tos->search_brace = btype_2;
105 break;
106
107 case lbrace: /* scanned { */
108 break_comma = false; /* don't break comma in an initial list */
109 if (parser_state_tos->p_stack[parser_state_tos->tos] == stmt || parser_state_tos->p_stack[parser_state_tos->tos] == decl
110 || parser_state_tos->p_stack[parser_state_tos->tos] == stmtl)
111 /* it is a random, isolated stmt group or a declaration */
112 parser_state_tos->i_l_follow += ind_size;
113 else {
114 if (s_code == e_code) {
115 /*
116 * only do this if there is nothing on the line
117 */
118
119 parser_state_tos->ind_level -= ind_size;
120 /*
121 * it is a group as part of a while, for, etc.
122 */
123
124 /* For -bl formatting, indent by brace_indent
125 additional spaces
126 e.g.
127 if (foo == bar)
128 {
129 <--> brace_indent spaces (in this example, 4)
130 */
131 if (!btype_2)
132 {
133 parser_state_tos->ind_level += brace_indent;
134 parser_state_tos->i_l_follow += brace_indent;
135 if (parser_state_tos->p_stack[parser_state_tos->tos] == swstmt)
136 case_ind += brace_indent;
137 }
138
139 if (parser_state_tos->p_stack[parser_state_tos->tos] == swstmt
140 && case_indent
141 >= ind_size)
142 parser_state_tos->ind_level -= ind_size;
143 /*
144 * for a switch, brace should be two levels out from the code
145 */
146 }
147 }
148
149 inc_pstack();
150 parser_state_tos->p_stack[parser_state_tos->tos] = lbrace;
151 parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level;
152 inc_pstack();
153 parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
154 /* allow null stmt between braces */
155 parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
156 break;
157
158 case whilestmt: /* scanned while (...) */
159 if (parser_state_tos->p_stack[parser_state_tos->tos] == dohead) {
160 /* it is matched with do stmt */
161 parser_state_tos->ind_level = parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos];
162 inc_pstack();
163 parser_state_tos->p_stack[parser_state_tos->tos] = whilestmt;
164 parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level = parser_state_tos->i_l_follow;
165 }
166 else { /* it is a while loop */
167 inc_pstack();
168 parser_state_tos->p_stack[parser_state_tos->tos] = whilestmt;
169 parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
170 parser_state_tos->i_l_follow += ind_size;
171 parser_state_tos->search_brace = btype_2;
172 }
173
174 break;
175
176 case elselit: /* scanned an else */
177
178 if (parser_state_tos->p_stack[parser_state_tos->tos] != ifhead)
179 diag(1, "Unmatched 'else'");
180 else {
181 parser_state_tos->ind_level = parser_state_tos->il[parser_state_tos->tos]; /* indentation for else should
182 * be same as for if */
183 /* everything following should be in 1 level */
184 parser_state_tos->i_l_follow = parser_state_tos->ind_level + ind_size;
185
186 parser_state_tos->p_stack[parser_state_tos->tos] = elsehead;
187 /* remember if with else */
188 parser_state_tos->search_brace = btype_2 | else_if;
189 }
190 break;
191
192 case rbrace: /* scanned a } */
193 /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
194 if (parser_state_tos->p_stack[parser_state_tos->tos - 1] == lbrace) {
195 parser_state_tos->ind_level = parser_state_tos->i_l_follow = parser_state_tos->il[--parser_state_tos->tos];
196 parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
197 }
198 else
199 diag(1, "Stmt nesting error.");
200 break;
201
202 case swstmt: /* had switch (...) */
203 inc_pstack();
204 parser_state_tos->p_stack[parser_state_tos->tos] = swstmt;
205 parser_state_tos->cstk[parser_state_tos->tos] = case_ind;
206 /* save current case indent level */
207 parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->i_l_follow;
208 case_ind = parser_state_tos->i_l_follow + case_indent; /* cases should be one
209 * level down from
210 * switch */
211 /* statements should be two levels in */
212 parser_state_tos->i_l_follow += case_indent + ind_size;
213
214 parser_state_tos->search_brace = btype_2;
215 break;
216
217 case semicolon: /* this indicates a simple stmt */
218 break_comma = false; /* turn off flag to break after commas in a
219 * declaration */
220 inc_pstack();
221 parser_state_tos->p_stack[parser_state_tos->tos] = stmt;
222 parser_state_tos->il[parser_state_tos->tos] = parser_state_tos->ind_level;
223 break;
224
225 default: /* this is an error */
226 diag(1, "Unknown code to parser");
227 return;
228
229
230 } /* end of switch */
231
232 reduce(); /* see if any reduction can be done */
233
234 #ifdef debug
235 for (i = 1; i <= parser_state_tos->tos; ++i)
236 printf("(%d %d)", parser_state_tos->p_stack[i], parser_state_tos->il[i]);
237 printf("\n");
238 #endif
239
240 return;
241 }
242
243 /*
244 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
245 *
246 * All rights reserved
247 *
248 *
249 * NAME: reduce
250 *
251 * FUNCTION: Implements the reduce part of the parsing algorithm
252 *
253 * ALGORITHM: The following reductions are done. Reductions are repeated until
254 * no more are possible.
255 *
256 * Old TOS New TOS <stmt> <stmt> <stmtl> <stmtl> <stmt> <stmtl> do
257 * <stmt> "dostmt" if <stmt> "ifstmt" switch <stmt> <stmt> decl
258 * <stmt> <stmt> "ifelse" <stmt> <stmt> for <stmt> <stmt> while
259 * <stmt> <stmt> "dostmt" while <stmt>
260 *
261 * On each reduction, parser_state_tos->i_l_follow (the indentation for the following line) is
262 * set to the indentation level associated with the old TOS.
263 *
264 * PARAMETERS: None
265 *
266 * RETURNS: Nothing
267 *
268 * GLOBALS: parser_state_tos->cstk parser_state_tos->i_l_follow = parser_state_tos->il parser_state_tos->p_stack = parser_state_tos->tos =
269 *
270 * CALLS: None
271 *
272 * CALLED BY: parse
273 *
274 * HISTORY: initial coding November 1976 D A Willcox of CAC
275 *
276 */
277 /*----------------------------------------------*\
278 | REDUCTION PHASE |
279 \*----------------------------------------------*/
reduce()280 reduce()
281 {
282
283 register int i;
284
285 for (;;) { /* keep looping until there is nothing left to
286 * reduce */
287
288 switch (parser_state_tos->p_stack[parser_state_tos->tos]) {
289
290 case stmt:
291 switch (parser_state_tos->p_stack[parser_state_tos->tos - 1]) {
292
293 case stmt:
294 case stmtl:
295 /* stmtl stmt or stmt stmt */
296 parser_state_tos->p_stack[--parser_state_tos->tos] = stmtl;
297 break;
298
299 case dolit: /* <do> <stmt> */
300 parser_state_tos->p_stack[--parser_state_tos->tos] = dohead;
301 parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos];
302 break;
303
304 case ifstmt:
305 /* <if> <stmt> */
306 parser_state_tos->p_stack[--parser_state_tos->tos] = ifhead;
307 for (i = parser_state_tos->tos - 1;
308 (
309 parser_state_tos->p_stack[i] != stmt
310 &&
311 parser_state_tos->p_stack[i] != stmtl
312 &&
313 parser_state_tos->p_stack[i] != lbrace
314 );
315 --i);
316 parser_state_tos->i_l_follow = parser_state_tos->il[i];
317 /*
318 * for the time being, we will assume that there is no else on
319 * this if, and set the indentation level accordingly. If an
320 * else is scanned, it will be fixed up later
321 */
322 break;
323
324 case swstmt:
325 /* <switch> <stmt> */
326 case_ind = parser_state_tos->cstk[parser_state_tos->tos - 1];
327
328 case decl: /* finish of a declaration */
329 case elsehead:
330 /* <<if> <stmt> else> <stmt> */
331 case forstmt:
332 /* <for> <stmt> */
333 case whilestmt:
334 /* <while> <stmt> */
335 parser_state_tos->p_stack[--parser_state_tos->tos] = stmt;
336 parser_state_tos->i_l_follow = parser_state_tos->il[parser_state_tos->tos];
337 break;
338
339 default: /* <anything else> <stmt> */
340 return;
341
342 } /* end of section for <stmt> on top of stack */
343 break;
344
345 case whilestmt: /* while (...) on top */
346 if (parser_state_tos->p_stack[parser_state_tos->tos - 1] == dohead) {
347 /* it is termination of a do while */
348 parser_state_tos->p_stack[--parser_state_tos->tos] = stmt;
349 break;
350 }
351 else
352 return;
353
354 default: /* anything else on top */
355 return;
356
357 }
358 }
359 }
360