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