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