PostgreSQL Source Code git master
parse.c
Go to the documentation of this file.
1/*-
2 * Copyright (c) 1985 Sun Microsystems, Inc.
3 * Copyright (c) 1980, 1993
4 * The Regents of the University of California. All rights reserved.
5 * 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#if 0
33#ifndef lint
34static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93";
35#endif /* not lint */
36#endif
37
38#include "c.h"
39
40#include <err.h>
41#include <stdio.h>
42#include "indent_globs.h"
43#include "indent_codes.h"
44#include "indent.h"
45
46static void reduce(void);
47
48void
49parse(int tk) /* tk: the code for the construct scanned */
50{
51 int i;
52
53#ifdef debug
54 printf("%2d - %s\n", tk, token);
55#endif
56
57 while (ps.p_stack[ps.tos] == ifhead && tk != elselit) {
58 /* true if we have an if without an else */
59 ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt
60 * reduction */
61 reduce(); /* see if this allows any reduction */
62 }
63
64
65 switch (tk) { /* go on and figure out what to do with the
66 * input */
67
68 case decl: /* scanned a declaration word */
70 /* indicate that following brace should be on same line */
71 if (ps.p_stack[ps.tos] != decl) { /* only put one declaration
72 * onto stack */
73 break_comma = true; /* while in declaration, newline should be
74 * forced after comma */
75 ps.p_stack[++ps.tos] = decl;
77
78 if (ps.ljust_decl) {/* only do if we want left justified
79 * declarations */
80 ps.ind_level = 0;
81 for (i = ps.tos - 1; i > 0; --i)
82 if (ps.p_stack[i] == decl)
83 ++ps.ind_level; /* indentation is number of
84 * declaration levels deep we are */
86 }
87 }
88 break;
89
90 case ifstmt: /* scanned if (...) */
91 if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */
92 /*
93 * Note that the stack pointer here is decremented, effectively
94 * reducing "else if" to "if". This saves a lot of stack space
95 * in case of a long "if-else-if ... else-if" sequence.
96 */
97 ps.i_l_follow = ps.il[ps.tos--];
98 /* the rest is the same as for dolit and forstmt */
99 /* FALLTHROUGH */
100 case dolit: /* 'do' */
101 case forstmt: /* for (...) */
102 ps.p_stack[++ps.tos] = tk;
104 ++ps.i_l_follow; /* subsequent statements should be indented 1 */
106 break;
107
108 case lbrace: /* scanned { */
109 break_comma = false; /* don't break comma in an initial list */
110 if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
111 || ps.p_stack[ps.tos] == stmtl)
112 ++ps.i_l_follow; /* it is a random, isolated stmt group or a
113 * declaration */
114 else {
115 if (s_code == e_code) {
116 /*
117 * only do this if there is nothing on the line
118 */
119 --ps.ind_level;
120 /*
121 * it is a group as part of a while, for, etc.
122 */
123 if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1)
124 --ps.ind_level;
125 /*
126 * for a switch, brace should be two levels out from the code
127 */
128 }
129 }
130
131 ps.p_stack[++ps.tos] = lbrace;
132 ps.il[ps.tos] = ps.ind_level;
133 ps.p_stack[++ps.tos] = stmt;
134 /* allow null stmt between braces */
135 ps.il[ps.tos] = ps.i_l_follow;
136 break;
137
138 case whilestmt: /* scanned while (...) */
139 if (ps.p_stack[ps.tos] == dohead) {
140 /* it is matched with do stmt */
144 }
145 else { /* it is a while loop */
147 ps.il[ps.tos] = ps.i_l_follow;
148 ++ps.i_l_follow;
150 }
151
152 break;
153
154 case elselit: /* scanned an else */
155
156 if (ps.p_stack[ps.tos] != ifhead)
157 diag2(1, "Unmatched 'else'");
158 else {
159 ps.ind_level = ps.il[ps.tos]; /* indentation for else should
160 * be same as for if */
161 ps.i_l_follow = ps.ind_level + 1; /* everything following should
162 * be in 1 level */
164 /* remember if with else */
166 }
167 break;
168
169 case rbrace: /* scanned a } */
170 /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
171 if (ps.tos > 0 && ps.p_stack[ps.tos - 1] == lbrace) {
173 ps.p_stack[ps.tos] = stmt;
174 }
175 else
176 diag2(1, "Statement nesting error");
177 break;
178
179 case swstmt: /* had switch (...) */
180 ps.p_stack[++ps.tos] = swstmt;
181 ps.cstk[ps.tos] = case_ind;
182 /* save current case indent level */
183 ps.il[ps.tos] = ps.i_l_follow;
184 case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one
185 * level down from
186 * switch */
187 ps.i_l_follow += ps.case_indent + 1; /* statements should be two
188 * levels in */
190 break;
191
192 case semicolon: /* this indicates a simple stmt */
193 break_comma = false; /* turn off flag to break after commas in a
194 * declaration */
195 ps.p_stack[++ps.tos] = stmt;
196 ps.il[ps.tos] = ps.ind_level;
197 break;
198
199 default: /* this is an error */
200 diag2(1, "Unknown code to parser");
201 return;
202
203
204 } /* end of switch */
205
206 if (ps.tos >= nitems(ps.p_stack) - 1)
207 errx(1, "Parser stack overflow");
208
209 reduce(); /* see if any reduction can be done */
210
211#ifdef debug
212 for (i = 1; i <= ps.tos; ++i)
213 printf("(%d %d)", ps.p_stack[i], ps.il[i]);
214 printf("\n");
215#endif
216
217 return;
218}
219
220/*
221 * NAME: reduce
222 *
223 * FUNCTION: Implements the reduce part of the parsing algorithm
224 *
225 * ALGORITHM: The following reductions are done. Reductions are repeated
226 * until no more are possible.
227 *
228 * Old TOS New TOS
229 * <stmt> <stmt> <stmtl>
230 * <stmtl> <stmt> <stmtl>
231 * do <stmt> "dostmt"
232 * if <stmt> "ifstmt"
233 * switch <stmt> <stmt>
234 * decl <stmt> <stmt>
235 * "ifelse" <stmt> <stmt>
236 * for <stmt> <stmt>
237 * while <stmt> <stmt>
238 * "dostmt" while <stmt>
239 *
240 * On each reduction, ps.i_l_follow (the indentation for the following line)
241 * is set to the indentation level associated with the old TOS.
242 *
243 * PARAMETERS: None
244 *
245 * RETURNS: Nothing
246 *
247 * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
248 *
249 * CALLS: None
250 *
251 * CALLED BY: parse
252 *
253 * HISTORY: initial coding November 1976 D A Willcox of CAC
254 *
255 */
256/*----------------------------------------------*\
257| REDUCTION PHASE |
258\*----------------------------------------------*/
259static void
261{
262 int i;
263
264 for (;;) { /* keep looping until there is nothing left to
265 * reduce */
266
267 switch (ps.p_stack[ps.tos]) {
268
269 case stmt:
270 switch (ps.p_stack[ps.tos - 1]) {
271
272 case stmt:
273 case stmtl:
274 /* stmtl stmt or stmt stmt */
275 ps.p_stack[--ps.tos] = stmtl;
276 break;
277
278 case dolit: /* <do> <stmt> */
279 ps.p_stack[--ps.tos] = dohead;
280 ps.i_l_follow = ps.il[ps.tos];
281 break;
282
283 case ifstmt:
284 /* <if> <stmt> */
285 ps.p_stack[--ps.tos] = ifhead;
286 for (i = ps.tos - 1;
287 (
288 ps.p_stack[i] != stmt
289 &&
290 ps.p_stack[i] != stmtl
291 &&
292 ps.p_stack[i] != lbrace
293 );
294 --i);
295 ps.i_l_follow = ps.il[i];
296 /*
297 * for the time being, we will assume that there is no else on
298 * this if, and set the indentation level accordingly. If an
299 * else is scanned, it will be fixed up later
300 */
301 break;
302
303 case swstmt:
304 /* <switch> <stmt> */
305 case_ind = ps.cstk[ps.tos - 1];
306 /* FALLTHROUGH */
307 case decl: /* finish of a declaration */
308 case elsehead:
309 /* <<if> <stmt> else> <stmt> */
310 case forstmt:
311 /* <for> <stmt> */
312 case whilestmt:
313 /* <while> <stmt> */
314 ps.p_stack[--ps.tos] = stmt;
315 ps.i_l_follow = ps.il[ps.tos];
316 break;
317
318 default: /* <anything else> <stmt> */
319 return;
320
321 } /* end of section for <stmt> on top of 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.tos -= 2;
328 break;
329 }
330 else
331 return;
332
333 default: /* anything else on top */
334 return;
335
336 }
337 }
338}
void errx(int eval, const char *fmt,...)
Definition: err.c:58
void diag2(int, const char *)
Definition: io.c:590
#define nitems(x)
Definition: indent.h:31
#define stmt
Definition: indent_codes.h:59
#define whilestmt
Definition: indent_codes.h:57
#define swstmt
Definition: indent_codes.h:50
#define ifhead
Definition: indent_codes.h:64
#define rbrace
Definition: indent_codes.h:46
#define ifstmt
Definition: indent_codes.h:56
#define lbrace
Definition: indent_codes.h:45
#define semicolon
Definition: indent_codes.h:44
#define forstmt
Definition: indent_codes.h:58
#define dolit
Definition: indent_codes.h:62
#define dohead
Definition: indent_codes.h:63
#define elsehead
Definition: indent_codes.h:65
#define elselit
Definition: indent_codes.h:61
#define stmtl
Definition: indent_codes.h:60
#define decl
Definition: indent_codes.h:53
#define token
Definition: indent_globs.h:126
int btype_2
char * e_code
struct parser_state ps
int break_comma
float case_ind
char * s_code
int i
Definition: isn.c:72
static void reduce(void)
Definition: parse.c:260
void parse(int tk)
Definition: parse.c:49
#define printf(...)
Definition: port.h:244
float cstk[32]
Definition: indent_globs.h:237
float case_indent
Definition: indent_globs.h:322
int p_stack[256]
Definition: indent_globs.h:235