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