PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
parse.c File Reference
#include "c.h"
#include <err.h>
#include <stdio.h>
#include "indent_globs.h"
#include "indent_codes.h"
#include "indent.h"
Include dependency graph for parse.c:

Go to the source code of this file.

Functions

static void reduce (void)
 
void parse (int tk)
 

Function Documentation

◆ parse()

void parse ( int  tk)

Definition at line 49 of file parse.c.

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 }
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
#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

References break_comma, btype_2, case_ind, parser_state::case_indent, parser_state::cstk, decl, diag2(), dohead, dolit, e_code, parser_state::else_if, elsehead, elselit, errx(), forstmt, i, parser_state::i_l_follow, ifhead, ifstmt, parser_state::il, parser_state::ind_level, lbrace, parser_state::ljust_decl, nitems, parser_state::p_stack, printf, ps, rbrace, reduce(), s_code, parser_state::search_brace, semicolon, stmt, stmtl, swstmt, token, parser_state::tos, and whilestmt.

◆ reduce()

static void reduce ( void  )
static

Definition at line 260 of file parse.c.

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 }

References case_ind, parser_state::cstk, decl, dohead, dolit, elsehead, forstmt, i, parser_state::i_l_follow, ifhead, ifstmt, parser_state::il, lbrace, parser_state::p_stack, ps, stmt, stmtl, swstmt, parser_state::tos, and whilestmt.

Referenced by parse(), and startScan().