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