1 |
|
|
/* $OpenBSD: parse.c,v 1.9 2009/10/27 23:59:39 deraadt Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 1980, 1993 |
5 |
|
|
* The Regents of the University of California. |
6 |
|
|
* Copyright (c) 1976 Board of Trustees of the University of Illinois. |
7 |
|
|
* Copyright (c) 1985 Sun Microsystems, Inc. |
8 |
|
|
* All rights reserved. |
9 |
|
|
* |
10 |
|
|
* Redistribution and use in source and binary forms, with or without |
11 |
|
|
* modification, are permitted provided that the following conditions |
12 |
|
|
* are met: |
13 |
|
|
* 1. Redistributions of source code must retain the above copyright |
14 |
|
|
* notice, this list of conditions and the following disclaimer. |
15 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
16 |
|
|
* notice, this list of conditions and the following disclaimer in the |
17 |
|
|
* documentation and/or other materials provided with the distribution. |
18 |
|
|
* 3. Neither the name of the University nor the names of its contributors |
19 |
|
|
* may be used to endorse or promote products derived from this software |
20 |
|
|
* without specific prior written permission. |
21 |
|
|
* |
22 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
23 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
24 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
26 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 |
|
|
* SUCH DAMAGE. |
33 |
|
|
*/ |
34 |
|
|
|
35 |
|
|
#include <stdio.h> |
36 |
|
|
#include "indent_globs.h" |
37 |
|
|
#include "indent_codes.h" |
38 |
|
|
|
39 |
|
|
void reduce(void); |
40 |
|
|
|
41 |
|
|
void |
42 |
|
|
parse(int tk) /* the code for the construct scanned */ |
43 |
|
|
{ |
44 |
|
|
int i; |
45 |
|
|
|
46 |
|
|
#ifdef debug |
47 |
|
|
printf("%2d - %s\n", tk, token); |
48 |
|
|
#endif |
49 |
|
|
|
50 |
|
|
while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { |
51 |
|
|
/* true if we have an if without an else */ |
52 |
|
|
ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt |
53 |
|
|
* reduction */ |
54 |
|
|
reduce(); /* see if this allows any reduction */ |
55 |
|
|
} |
56 |
|
|
|
57 |
|
|
|
58 |
|
|
switch (tk) { /* go on and figure out what to do with the |
59 |
|
|
* input */ |
60 |
|
|
|
61 |
|
|
case decl: /* scanned a declaration word */ |
62 |
|
|
ps.search_brace = btype_2; |
63 |
|
|
/* indicate that following brace should be on same line */ |
64 |
|
|
if (ps.p_stack[ps.tos] != decl) { /* only put one declaration |
65 |
|
|
* onto stack */ |
66 |
|
|
break_comma = true; /* while in declaration, newline should be |
67 |
|
|
* forced after comma */ |
68 |
|
|
ps.p_stack[++ps.tos] = decl; |
69 |
|
|
ps.il[ps.tos] = ps.i_l_follow; |
70 |
|
|
|
71 |
|
|
if (ps.ljust_decl) {/* only do if we want left justified |
72 |
|
|
* declarations */ |
73 |
|
|
ps.ind_level = 0; |
74 |
|
|
for (i = ps.tos - 1; i > 0; --i) |
75 |
|
|
if (ps.p_stack[i] == decl) |
76 |
|
|
++ps.ind_level; /* indentation is number of |
77 |
|
|
* declaration levels deep we are */ |
78 |
|
|
ps.i_l_follow = ps.ind_level; |
79 |
|
|
} |
80 |
|
|
} |
81 |
|
|
break; |
82 |
|
|
|
83 |
|
|
case ifstmt: /* scanned if (...) */ |
84 |
|
|
if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ |
85 |
|
|
ps.i_l_follow = ps.il[ps.tos]; |
86 |
|
|
case dolit: /* 'do' */ |
87 |
|
|
case forstmt: /* for (...) */ |
88 |
|
|
ps.p_stack[++ps.tos] = tk; |
89 |
|
|
ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; |
90 |
|
|
++ps.i_l_follow; /* subsequent statements should be indented 1 */ |
91 |
|
|
ps.search_brace = btype_2; |
92 |
|
|
break; |
93 |
|
|
|
94 |
|
|
case lbrace: /* scanned { */ |
95 |
|
|
break_comma = false; /* don't break comma in an initial list */ |
96 |
|
|
if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl |
97 |
|
|
|| ps.p_stack[ps.tos] == stmtl) |
98 |
|
|
++ps.i_l_follow; /* it is a random, isolated stmt group or a |
99 |
|
|
* declaration */ |
100 |
|
|
else { |
101 |
|
|
if (s_code == e_code) { |
102 |
|
|
/* |
103 |
|
|
* only do this if there is nothing on the line |
104 |
|
|
*/ |
105 |
|
|
--ps.ind_level; |
106 |
|
|
/* |
107 |
|
|
* it is a group as part of a while, for, etc. |
108 |
|
|
*/ |
109 |
|
|
if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) |
110 |
|
|
--ps.ind_level; |
111 |
|
|
/* |
112 |
|
|
* for a switch, brace should be two levels out from the code |
113 |
|
|
*/ |
114 |
|
|
} |
115 |
|
|
} |
116 |
|
|
|
117 |
|
|
ps.p_stack[++ps.tos] = lbrace; |
118 |
|
|
ps.il[ps.tos] = ps.ind_level; |
119 |
|
|
ps.p_stack[++ps.tos] = stmt; |
120 |
|
|
/* allow null stmt between braces */ |
121 |
|
|
ps.il[ps.tos] = ps.i_l_follow; |
122 |
|
|
break; |
123 |
|
|
|
124 |
|
|
case whilestmt: /* scanned while (...) */ |
125 |
|
|
if (ps.p_stack[ps.tos] == dohead) { |
126 |
|
|
/* it is matched with do stmt */ |
127 |
|
|
ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; |
128 |
|
|
ps.p_stack[++ps.tos] = whilestmt; |
129 |
|
|
ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; |
130 |
|
|
} |
131 |
|
|
else { /* it is a while loop */ |
132 |
|
|
ps.p_stack[++ps.tos] = whilestmt; |
133 |
|
|
ps.il[ps.tos] = ps.i_l_follow; |
134 |
|
|
++ps.i_l_follow; |
135 |
|
|
ps.search_brace = btype_2; |
136 |
|
|
} |
137 |
|
|
|
138 |
|
|
break; |
139 |
|
|
|
140 |
|
|
case elselit: /* scanned an else */ |
141 |
|
|
|
142 |
|
|
if (ps.p_stack[ps.tos] != ifhead) |
143 |
|
|
diag(1, "Unmatched 'else'"); |
144 |
|
|
else { |
145 |
|
|
ps.ind_level = ps.il[ps.tos]; /* indentation for else should |
146 |
|
|
* be same as for if */ |
147 |
|
|
ps.i_l_follow = ps.ind_level + 1; /* everything following should |
148 |
|
|
* be in 1 level */ |
149 |
|
|
ps.p_stack[ps.tos] = elsehead; |
150 |
|
|
/* remember if with else */ |
151 |
|
|
ps.search_brace = btype_2 | ps.else_if; |
152 |
|
|
} |
153 |
|
|
break; |
154 |
|
|
|
155 |
|
|
case rbrace: /* scanned a } */ |
156 |
|
|
/* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ |
157 |
|
|
if (ps.p_stack[ps.tos - 1] == lbrace) { |
158 |
|
|
ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; |
159 |
|
|
ps.p_stack[ps.tos] = stmt; |
160 |
|
|
} |
161 |
|
|
else |
162 |
|
|
diag(1, "Stmt nesting error."); |
163 |
|
|
break; |
164 |
|
|
|
165 |
|
|
case swstmt: /* had switch (...) */ |
166 |
|
|
ps.p_stack[++ps.tos] = swstmt; |
167 |
|
|
ps.cstk[ps.tos] = case_ind; |
168 |
|
|
/* save current case indent level */ |
169 |
|
|
ps.il[ps.tos] = ps.i_l_follow; |
170 |
|
|
case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one |
171 |
|
|
* level down from |
172 |
|
|
* switch */ |
173 |
|
|
ps.i_l_follow += ps.case_indent + 1; /* statements should be two |
174 |
|
|
* levels in */ |
175 |
|
|
ps.search_brace = btype_2; |
176 |
|
|
break; |
177 |
|
|
|
178 |
|
|
case semicolon: /* this indicates a simple stmt */ |
179 |
|
|
break_comma = false; /* turn off flag to break after commas in a |
180 |
|
|
* declaration */ |
181 |
|
|
ps.p_stack[++ps.tos] = stmt; |
182 |
|
|
ps.il[ps.tos] = ps.ind_level; |
183 |
|
|
break; |
184 |
|
|
|
185 |
|
|
default: /* this is an error */ |
186 |
|
|
diag(1, "Unknown code to parser"); |
187 |
|
|
return; |
188 |
|
|
|
189 |
|
|
|
190 |
|
|
} /* end of switch */ |
191 |
|
|
|
192 |
|
|
reduce(); /* see if any reduction can be done */ |
193 |
|
|
|
194 |
|
|
#ifdef debug |
195 |
|
|
for (i = 1; i <= ps.tos; ++i) |
196 |
|
|
printf("(%d %d)", ps.p_stack[i], ps.il[i]); |
197 |
|
|
printf("\n"); |
198 |
|
|
#endif |
199 |
|
|
|
200 |
|
|
return; |
201 |
|
|
} |
202 |
|
|
|
203 |
|
|
/* |
204 |
|
|
* NAME: reduce |
205 |
|
|
* |
206 |
|
|
* FUNCTION: Implements the reduce part of the parsing algorithm |
207 |
|
|
* |
208 |
|
|
* ALGORITHM: The following reductions are done. Reductions are repeated |
209 |
|
|
* until no more are possible. |
210 |
|
|
* |
211 |
|
|
* Old TOS New TOS |
212 |
|
|
* <stmt> <stmt> <stmtl> |
213 |
|
|
* <stmtl> <stmt> <stmtl> |
214 |
|
|
* do <stmt> "dostmt" |
215 |
|
|
* if <stmt> "ifstmt" |
216 |
|
|
* switch <stmt> <stmt> |
217 |
|
|
* decl <stmt> <stmt> |
218 |
|
|
* "ifelse" <stmt> <stmt> |
219 |
|
|
* for <stmt> <stmt> |
220 |
|
|
* while <stmt> <stmt> |
221 |
|
|
* "dostmt" while <stmt> |
222 |
|
|
* |
223 |
|
|
* On each reduction, ps.i_l_follow (the indentation for the following line) |
224 |
|
|
* is set to the indentation level associated with the old TOS. |
225 |
|
|
* |
226 |
|
|
* PARAMETERS: None |
227 |
|
|
* |
228 |
|
|
* RETURNS: Nothing |
229 |
|
|
* |
230 |
|
|
* GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = |
231 |
|
|
* |
232 |
|
|
* CALLS: None |
233 |
|
|
* |
234 |
|
|
* CALLED BY: parse |
235 |
|
|
* |
236 |
|
|
* HISTORY: initial coding November 1976 D A Willcox of CAC |
237 |
|
|
* |
238 |
|
|
*/ |
239 |
|
|
/*----------------------------------------------*\ |
240 |
|
|
| REDUCTION PHASE | |
241 |
|
|
\*----------------------------------------------*/ |
242 |
|
|
void |
243 |
|
|
reduce(void) |
244 |
|
|
{ |
245 |
|
|
|
246 |
|
|
int i; |
247 |
|
|
|
248 |
|
|
for (;;) { /* keep looping until there is nothing left to |
249 |
|
|
* reduce */ |
250 |
|
|
|
251 |
|
|
switch (ps.p_stack[ps.tos]) { |
252 |
|
|
|
253 |
|
|
case stmt: |
254 |
|
|
switch (ps.p_stack[ps.tos - 1]) { |
255 |
|
|
|
256 |
|
|
case stmt: |
257 |
|
|
case stmtl: |
258 |
|
|
/* stmtl stmt or stmt stmt */ |
259 |
|
|
ps.p_stack[--ps.tos] = stmtl; |
260 |
|
|
break; |
261 |
|
|
|
262 |
|
|
case dolit: /* <do> <stmt> */ |
263 |
|
|
ps.p_stack[--ps.tos] = dohead; |
264 |
|
|
ps.i_l_follow = ps.il[ps.tos]; |
265 |
|
|
break; |
266 |
|
|
|
267 |
|
|
case ifstmt: |
268 |
|
|
/* <if> <stmt> */ |
269 |
|
|
ps.p_stack[--ps.tos] = ifhead; |
270 |
|
|
for (i = ps.tos - 1; |
271 |
|
|
( |
272 |
|
|
ps.p_stack[i] != stmt |
273 |
|
|
&& |
274 |
|
|
ps.p_stack[i] != stmtl |
275 |
|
|
&& |
276 |
|
|
ps.p_stack[i] != lbrace |
277 |
|
|
); |
278 |
|
|
--i); |
279 |
|
|
ps.i_l_follow = ps.il[i]; |
280 |
|
|
/* |
281 |
|
|
* for the time being, we will assume that there is no else on |
282 |
|
|
* this if, and set the indentation level accordingly. If an |
283 |
|
|
* else is scanned, it will be fixed up later |
284 |
|
|
*/ |
285 |
|
|
break; |
286 |
|
|
|
287 |
|
|
case swstmt: |
288 |
|
|
/* <switch> <stmt> */ |
289 |
|
|
case_ind = ps.cstk[ps.tos - 1]; |
290 |
|
|
|
291 |
|
|
case decl: /* finish of a declaration */ |
292 |
|
|
case elsehead: |
293 |
|
|
/* <<if> <stmt> else> <stmt> */ |
294 |
|
|
case forstmt: |
295 |
|
|
/* <for> <stmt> */ |
296 |
|
|
case whilestmt: |
297 |
|
|
/* <while> <stmt> */ |
298 |
|
|
ps.p_stack[--ps.tos] = stmt; |
299 |
|
|
ps.i_l_follow = ps.il[ps.tos]; |
300 |
|
|
break; |
301 |
|
|
|
302 |
|
|
default: /* <anything else> <stmt> */ |
303 |
|
|
return; |
304 |
|
|
|
305 |
|
|
} /* end of section for <stmt> on top of stack */ |
306 |
|
|
break; |
307 |
|
|
|
308 |
|
|
case whilestmt: /* while (...) on top */ |
309 |
|
|
if (ps.p_stack[ps.tos - 1] == dohead) { |
310 |
|
|
/* it is termination of a do while */ |
311 |
|
|
ps.p_stack[--ps.tos] = stmt; |
312 |
|
|
break; |
313 |
|
|
} |
314 |
|
|
else |
315 |
|
|
return; |
316 |
|
|
|
317 |
|
|
default: /* anything else on top */ |
318 |
|
|
return; |
319 |
|
|
|
320 |
|
|
} |
321 |
|
|
} |
322 |
|
|
} |