1 /*
2 * Copyright (c) 1985 Sun Microsystems, Inc.
3 * Copyright (c) 1980, 1993
4 * The Regents of the University of California. All rights reserved.
5 * All rights reserved.
6 *
7 * %sccs.include.redist.c%
8 */
9
10 #ifndef lint
11 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 06/06/93";
12 #endif /* not lint */
13
14 #include <stdio.h>
15 #include "indent_globs.h"
16 #include "indent_codes.h"
17
parse(tk)18 parse(tk)
19 int tk; /* the code for the construct scanned */
20 {
21 int i;
22
23 #ifdef debug
24 printf("%2d - %s\n", tk, token);
25 #endif
26
27 while (ps.p_stack[ps.tos] == ifhead && tk != elselit) {
28 /* true if we have an if without an else */
29 ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt
30 * reduction */
31 reduce(); /* see if this allows any reduction */
32 }
33
34
35 switch (tk) { /* go on and figure out what to do with the
36 * input */
37
38 case decl: /* scanned a declaration word */
39 ps.search_brace = btype_2;
40 /* indicate that following brace should be on same line */
41 if (ps.p_stack[ps.tos] != decl) { /* only put one declaration
42 * onto stack */
43 break_comma = true; /* while in declaration, newline should be
44 * forced after comma */
45 ps.p_stack[++ps.tos] = decl;
46 ps.il[ps.tos] = ps.i_l_follow;
47
48 if (ps.ljust_decl) {/* only do if we want left justified
49 * declarations */
50 ps.ind_level = 0;
51 for (i = ps.tos - 1; i > 0; --i)
52 if (ps.p_stack[i] == decl)
53 ++ps.ind_level; /* indentation is number of
54 * declaration levels deep we are */
55 ps.i_l_follow = ps.ind_level;
56 }
57 }
58 break;
59
60 case ifstmt: /* scanned if (...) */
61 if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */
62 ps.i_l_follow = ps.il[ps.tos];
63 case dolit: /* 'do' */
64 case forstmt: /* for (...) */
65 ps.p_stack[++ps.tos] = tk;
66 ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
67 ++ps.i_l_follow; /* subsequent statements should be indented 1 */
68 ps.search_brace = btype_2;
69 break;
70
71 case lbrace: /* scanned { */
72 break_comma = false; /* don't break comma in an initial list */
73 if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
74 || ps.p_stack[ps.tos] == stmtl)
75 ++ps.i_l_follow; /* it is a random, isolated stmt group or a
76 * declaration */
77 else {
78 if (s_code == e_code) {
79 /*
80 * only do this if there is nothing on the line
81 */
82 --ps.ind_level;
83 /*
84 * it is a group as part of a while, for, etc.
85 */
86 if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1)
87 --ps.ind_level;
88 /*
89 * for a switch, brace should be two levels out from the code
90 */
91 }
92 }
93
94 ps.p_stack[++ps.tos] = lbrace;
95 ps.il[ps.tos] = ps.ind_level;
96 ps.p_stack[++ps.tos] = stmt;
97 /* allow null stmt between braces */
98 ps.il[ps.tos] = ps.i_l_follow;
99 break;
100
101 case whilestmt: /* scanned while (...) */
102 if (ps.p_stack[ps.tos] == dohead) {
103 /* it is matched with do stmt */
104 ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
105 ps.p_stack[++ps.tos] = whilestmt;
106 ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
107 }
108 else { /* it is a while loop */
109 ps.p_stack[++ps.tos] = whilestmt;
110 ps.il[ps.tos] = ps.i_l_follow;
111 ++ps.i_l_follow;
112 ps.search_brace = btype_2;
113 }
114
115 break;
116
117 case elselit: /* scanned an else */
118
119 if (ps.p_stack[ps.tos] != ifhead)
120 diag(1, "Unmatched 'else'");
121 else {
122 ps.ind_level = ps.il[ps.tos]; /* indentation for else should
123 * be same as for if */
124 ps.i_l_follow = ps.ind_level + 1; /* everything following should
125 * be in 1 level */
126 ps.p_stack[ps.tos] = elsehead;
127 /* remember if with else */
128 ps.search_brace = btype_2 | ps.else_if;
129 }
130 break;
131
132 case rbrace: /* scanned a } */
133 /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
134 if (ps.p_stack[ps.tos - 1] == lbrace) {
135 ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
136 ps.p_stack[ps.tos] = stmt;
137 }
138 else
139 diag(1, "Stmt nesting error.");
140 break;
141
142 case swstmt: /* had switch (...) */
143 ps.p_stack[++ps.tos] = swstmt;
144 ps.cstk[ps.tos] = case_ind;
145 /* save current case indent level */
146 ps.il[ps.tos] = ps.i_l_follow;
147 case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one
148 * level down from
149 * switch */
150 ps.i_l_follow += ps.case_indent + 1; /* statements should be two
151 * levels in */
152 ps.search_brace = btype_2;
153 break;
154
155 case semicolon: /* this indicates a simple stmt */
156 break_comma = false; /* turn off flag to break after commas in a
157 * declaration */
158 ps.p_stack[++ps.tos] = stmt;
159 ps.il[ps.tos] = ps.ind_level;
160 break;
161
162 default: /* this is an error */
163 diag(1, "Unknown code to parser");
164 return;
165
166
167 } /* end of switch */
168
169 reduce(); /* see if any reduction can be done */
170
171 #ifdef debug
172 for (i = 1; i <= ps.tos; ++i)
173 printf("(%d %d)", ps.p_stack[i], ps.il[i]);
174 printf("\n");
175 #endif
176
177 return;
178 }
179
180 /*
181 * NAME: reduce
182 *
183 * FUNCTION: Implements the reduce part of the parsing algorithm
184 *
185 * ALGORITHM: The following reductions are done. Reductions are repeated
186 * until no more are possible.
187 *
188 * Old TOS New TOS
189 * <stmt> <stmt> <stmtl>
190 * <stmtl> <stmt> <stmtl>
191 * do <stmt> "dostmt"
192 * if <stmt> "ifstmt"
193 * switch <stmt> <stmt>
194 * decl <stmt> <stmt>
195 * "ifelse" <stmt> <stmt>
196 * for <stmt> <stmt>
197 * while <stmt> <stmt>
198 * "dostmt" while <stmt>
199 *
200 * On each reduction, ps.i_l_follow (the indentation for the following line)
201 * is set to the indentation level associated with the old TOS.
202 *
203 * PARAMETERS: None
204 *
205 * RETURNS: Nothing
206 *
207 * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
208 *
209 * CALLS: None
210 *
211 * CALLED BY: parse
212 *
213 * HISTORY: initial coding November 1976 D A Willcox of CAC
214 *
215 */
216 /*----------------------------------------------*\
217 | REDUCTION PHASE |
218 \*----------------------------------------------*/
reduce()219 reduce()
220 {
221
222 register int i;
223
224 for (;;) { /* keep looping until there is nothing left to
225 * reduce */
226
227 switch (ps.p_stack[ps.tos]) {
228
229 case stmt:
230 switch (ps.p_stack[ps.tos - 1]) {
231
232 case stmt:
233 case stmtl:
234 /* stmtl stmt or stmt stmt */
235 ps.p_stack[--ps.tos] = stmtl;
236 break;
237
238 case dolit: /* <do> <stmt> */
239 ps.p_stack[--ps.tos] = dohead;
240 ps.i_l_follow = ps.il[ps.tos];
241 break;
242
243 case ifstmt:
244 /* <if> <stmt> */
245 ps.p_stack[--ps.tos] = ifhead;
246 for (i = ps.tos - 1;
247 (
248 ps.p_stack[i] != stmt
249 &&
250 ps.p_stack[i] != stmtl
251 &&
252 ps.p_stack[i] != lbrace
253 );
254 --i);
255 ps.i_l_follow = ps.il[i];
256 /*
257 * for the time being, we will assume that there is no else on
258 * this if, and set the indentation level accordingly. If an
259 * else is scanned, it will be fixed up later
260 */
261 break;
262
263 case swstmt:
264 /* <switch> <stmt> */
265 case_ind = ps.cstk[ps.tos - 1];
266
267 case decl: /* finish of a declaration */
268 case elsehead:
269 /* <<if> <stmt> else> <stmt> */
270 case forstmt:
271 /* <for> <stmt> */
272 case whilestmt:
273 /* <while> <stmt> */
274 ps.p_stack[--ps.tos] = stmt;
275 ps.i_l_follow = ps.il[ps.tos];
276 break;
277
278 default: /* <anything else> <stmt> */
279 return;
280
281 } /* end of section for <stmt> on top of stack */
282 break;
283
284 case whilestmt: /* while (...) on top */
285 if (ps.p_stack[ps.tos - 1] == dohead) {
286 /* it is termination of a do while */
287 ps.p_stack[--ps.tos] = stmt;
288 break;
289 }
290 else
291 return;
292
293 default: /* anything else on top */
294 return;
295
296 }
297 }
298 }
299