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