1 /*-------------------------------------------------------------------------
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
13 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
14 * Portions Copyright (c) 1994, Regents of the University of California
17 * $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.63 2004/12/31 22:00:27 pgsql Exp $
19 *-------------------------------------------------------------------------
23 #include "pool_parser.h"
24 #include "pool_memory.h"
25 #include "gramparse.h"
30 List *parsetree; /* result of parsing is left here */
33 static int lookahead_token; /* one-token lookahead */
34 static bool have_lookahead; /* lookahead_token set? */
35 static YYSTYPE lookahead_yylval; /* yylval for lookahead token */
36 static YYLTYPE lookahead_yylloc; /* yylloc for lookahead token */
41 * Given a query in string form, do lexical and grammatical analysis.
43 * Returns a list of raw (un-analyzed) parse trees.
46 raw_parser(const char *str)
50 if (pool_memory == NULL)
51 pool_memory = pool_memory_create(PARSER_BLOCK_SIZE);
53 parsetree = NIL; /* in case grammar forgets to set it */
54 have_lookahead = false;
59 if (setjmp(jmpbuffer) != 0)
62 return NIL; /* error */
66 yyresult = base_yyparse();
70 if (yyresult) /* error */
76 void free_parser(void)
78 pool_memory_delete(pool_memory, 1);
82 * Intermediate filter between parser and base lexer (base_yylex in scan.l).
84 * The filter is needed because in some cases the standard SQL grammar
85 * requires more than one token lookahead. We reduce these cases to one-token
86 * lookahead by combining tokens here, in order to keep the grammar LALR(1).
88 * Using a filter is simpler than trying to recognize multiword tokens
89 * directly in scan.l, because we'd have to allow for comments between the
90 * words. Furthermore it's not clear how to do it without re-introducing
91 * scanner backtrack, which would cost more performance than this filter
95 filtered_base_yylex(void)
102 /* Get next token --- we might already have it */
105 cur_token = lookahead_token;
106 base_yylval = lookahead_yylval;
107 base_yylloc = lookahead_yylloc;
108 have_lookahead = false;
111 cur_token = base_yylex();
113 /* Do we need to look ahead for a possible multiword token? */
118 * NULLS FIRST and NULLS LAST must be reduced to one token
120 cur_yylval = base_yylval;
121 cur_yylloc = base_yylloc;
122 next_token = base_yylex();
126 cur_token = NULLS_FIRST;
129 cur_token = NULLS_LAST;
132 /* save the lookahead token for next time */
133 lookahead_token = next_token;
134 lookahead_yylval = base_yylval;
135 lookahead_yylloc = base_yylloc;
136 have_lookahead = true;
137 /* and back up the output info to cur_token */
138 base_yylval = cur_yylval;
139 base_yylloc = cur_yylloc;
146 * WITH CASCADED, LOCAL, or CHECK must be reduced to one token
148 * XXX an alternative way is to recognize just WITH_TIME and put
149 * the ugliness into the datetime datatype productions instead of
150 * WITH CHECK OPTION. However that requires promoting WITH to a
151 * fully reserved word. If we ever have to do that anyway
152 * (perhaps for SQL99 recursive queries), come back and simplify
155 cur_yylval = base_yylval;
156 cur_yylloc = base_yylloc;
157 next_token = base_yylex();
161 cur_token = WITH_CASCADED;
164 cur_token = WITH_LOCAL;
167 cur_token = WITH_CHECK;
170 /* save the lookahead token for next time */
171 lookahead_token = next_token;
172 lookahead_yylval = base_yylval;
173 lookahead_yylloc = base_yylloc;
174 have_lookahead = true;
175 /* and back up the output info to cur_token */
176 base_yylval = cur_yylval;
177 base_yylloc = cur_yylloc;