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
34 static 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 
46 static void reduce(void);
47 
48 void
49 parse(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;
76  ps.il[ps.tos] = ps.i_l_follow;
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 */
142  ps.p_stack[++ps.tos] = whilestmt;
144  }
145  else { /* it is a while loop */
146  ps.p_stack[++ps.tos] = whilestmt;
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 */
163  ps.p_stack[ps.tos] = elsehead;
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) {
172  ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
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 \*----------------------------------------------*/
259 static void
260 reduce(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:73
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