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