xref: /csrg-svn/usr.bin/indent/parse.c (revision 33767)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
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.
13  */
14 
15 #ifndef lint
16 static char sccsid[] = "@(#)parse.c	5.5 (Berkeley) 03/22/88";
17 #endif /* not lint */
18 
19 /*
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  */
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  */
53 
54 #include "./indent_globs.h"
55 #include "./indent_codes.h"
56 
57 
58 
59 
60 parse(tk)
61     int         tk;		/* the code for the construct scanned */
62 {
63     int         i;
64 
65 #ifdef debug
66     printf("%2d - %s\n", tk, token);
67 #endif
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 */
73     }
74 
75 
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;
98 		}
99 	    }
100 	    break;
101 
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;
112 	    break;
113 
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 */
120 	    else {
121 		if (s_code == e_code) {
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 		     */
131 		}
132 	    }
133 
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;
139 	    break;
140 
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;
147 	    }
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;
153 	    }
154 
155 	    break;
156 
157 	case elselit: 		/* scanned an else */
158 
159 	    if (ps.p_stack[ps.tos] != ifhead)
160 		diag(1,"Unmatched 'else'");
161 	    else {
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;
167 	    }
168 
169 	    break;
170 
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;
176 	    }
177 	    else
178 		diag(1,"Stmt nesting error.");
179 	    break;
180 
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 */
189 	    ps.i_l_follow += ps.case_indent + 1;	/* statements should be
190 						 * two levels in */
191 	    ps.search_brace = btype_2;
192 	    break;
193 
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;
199 	    break;
200 
201 	default: 		/* this is an error */
202 	    diag(1,"Unknown code to parser");
203 	    return;
204 
205 
206     }				/* end of switch */
207 
208     reduce();			/* see if any reduction can be done */
209 #ifdef debug
210     for (i = 1; i <= ps.tos; ++i)
211 	printf("(%d %d)", ps.p_stack[i], ps.il[i]);
212     printf("\n");
213 #endif
214     return;
215 }
216 /*
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 
246  *
247  * HISTORY: initial coding 	November 1976	D A Willcox of CAC
248  *
249  */
250 /*----------------------------------------------*\
251  * |   REDUCTION PHASE
252 \*----------------------------------------------*/
253 reduce() {
254 
255     register int i;
256 
257     for (;;) {			/* keep looping until there is nothing
258 				 * left to reduce */
259 
260 	switch (ps.p_stack[ps.tos]) {
261 
262 	    case stmt:
263 		switch (ps.p_stack[ps.tos - 1]) {
264 
265 		    case stmt:
266 		    case stmtl:
267 			/* stmtl stmt or stmt stmt */
268 			ps.p_stack[--ps.tos] = stmtl;
269 			break;
270 
271 		    case dolit: /* <do> <stmt> */
272 			ps.p_stack[--ps.tos] = dohead;
273 			ps.i_l_follow = ps.il[ps.tos];
274 			break;
275 
276 		    case ifstmt:
277 			/* <if> <stmt> */
278 			ps.p_stack[--ps.tos] = ifhead;
279 			for (i = ps.tos - 1;
280 				(
281 				    ps.p_stack[i] != stmt
282 				    &&
283 				    ps.p_stack[i] != stmtl
284 				    &&
285 				    ps.p_stack[i] != lbrace
286 				);
287 				--i);
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 			 */
295 			break;
296 
297 		    case swstmt:
298 			/* <switch> <stmt> */
299 			case_ind = ps.cstk[ps.tos - 1];
300 
301 		    case decl: 	/* finish of a declaration */
302 		    case elsehead:
303 			/* <<if> <stmt> else> <stmt> */
304 		    case forstmt:
305 			/* <for> <stmt> */
306 		    case whilestmt:
307 			/* <while> <stmt> */
308 			ps.p_stack[--ps.tos] = stmt;
309 			ps.i_l_follow = ps.il[ps.tos];
310 			break;
311 
312 		    default: 	/* <anything else> <stmt> */
313 			return;
314 
315 		}		/* end of section for <stmt> on top of
316 				 * stack */
317 		break;
318 
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;
323 		    break;
324 		}
325 		else
326 		    return;
327 
328 	    default: 		/* anything else on top */
329 		return;
330 
331 	}
332     }
333 }
334