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