Fix xslt_process() to ensure that it inserts a NULL terminator after the
[PostgreSQL.git] / src / interfaces / ecpg / preproc / parser.c
blobda894bed59b49765fabbbf674c58d31ad9dda0d5
1 /*-------------------------------------------------------------------------
3 * parser.c
4 * Main entry point/driver for PostgreSQL grammar
6 * Note that the grammar is not allowed to perform any table access
7 * (since we need to be able to do basic parsing even while inside an
8 * aborted transaction). Therefore, the data structures returned by
9 * the grammar are "raw" parsetrees that still need to be analyzed by
10 * analyze.c and related files.
13 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
14 * Portions Copyright (c) 1994, Regents of the University of California
16 * IDENTIFICATION
17 * $PostgreSQL$
19 *-------------------------------------------------------------------------
22 #include "postgres_fe.h"
24 #include "extern.h"
25 #include "preproc.h"
28 static bool have_lookahead; /* is lookahead info valid? */
29 static int lookahead_token; /* one-token lookahead */
30 static YYSTYPE lookahead_yylval; /* yylval for lookahead token */
31 static YYLTYPE lookahead_yylloc; /* yylloc for lookahead token */
35 * Intermediate filter between parser and base lexer (base_yylex in scan.l).
37 * The filter is needed because in some cases the standard SQL grammar
38 * requires more than one token lookahead. We reduce these cases to one-token
39 * lookahead by combining tokens here, in order to keep the grammar LALR(1).
41 * Using a filter is simpler than trying to recognize multiword tokens
42 * directly in scan.l, because we'd have to allow for comments between the
43 * words. Furthermore it's not clear how to do it without re-introducing
44 * scanner backtrack, which would cost more performance than this filter
45 * layer does.
47 int
48 filtered_base_yylex(void)
50 int cur_token;
51 int next_token;
52 YYSTYPE cur_yylval;
53 YYLTYPE cur_yylloc;
55 /* Get next token --- we might already have it */
56 if (have_lookahead)
58 cur_token = lookahead_token;
59 base_yylval = lookahead_yylval;
60 base_yylloc = lookahead_yylloc;
61 have_lookahead = false;
63 else
64 cur_token = base_yylex();
66 /* Do we need to look ahead for a possible multiword token? */
67 switch (cur_token)
69 case NULLS_P:
72 * NULLS FIRST and NULLS LAST must be reduced to one token
74 cur_yylval = base_yylval;
75 cur_yylloc = base_yylloc;
76 next_token = base_yylex();
77 switch (next_token)
79 case FIRST_P:
80 cur_token = NULLS_FIRST;
81 break;
82 case LAST_P:
83 cur_token = NULLS_LAST;
84 break;
85 default:
86 /* save the lookahead token for next time */
87 lookahead_token = next_token;
88 lookahead_yylval = base_yylval;
89 lookahead_yylloc = base_yylloc;
90 have_lookahead = true;
91 /* and back up the output info to cur_token */
92 base_yylval = cur_yylval;
93 base_yylloc = cur_yylloc;
94 break;
96 break;
98 case WITH:
101 * WITH TIME must be reduced to one token
103 cur_yylval = base_yylval;
104 cur_yylloc = base_yylloc;
105 next_token = base_yylex();
106 switch (next_token)
108 case TIME:
109 cur_token = WITH_TIME;
110 break;
111 default:
112 /* save the lookahead token for next time */
113 lookahead_token = next_token;
114 lookahead_yylval = base_yylval;
115 lookahead_yylloc = base_yylloc;
116 have_lookahead = true;
117 /* and back up the output info to cur_token */
118 base_yylval = cur_yylval;
119 base_yylloc = cur_yylloc;
120 break;
122 break;
124 default:
125 break;
128 return cur_token;