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
10 * analyze.c and related files.
13 * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
14 * Portions Copyright (c) 1994, Regents of the University of California
17 * src/backend/parser/parser.c
19 *-------------------------------------------------------------------------
24 #include "parser/gramparse.h"
25 #include "parser/parser.h"
30 * Given a query in string form, do lexical and grammatical analysis.
32 * Returns a list of raw (un-analyzed) parse trees.
35 raw_parser(const char *str)
37 core_yyscan_t yyscanner;
38 base_yy_extra_type yyextra;
41 /* initialize the flex scanner */
42 yyscanner = scanner_init(str, &yyextra.core_yy_extra,
43 ScanKeywords, NumScanKeywords);
45 /* base_yylex() only needs this much initialization */
46 yyextra.have_lookahead = false;
48 /* initialize the bison parser */
49 parser_init(&yyextra);
52 yyresult = base_yyparse(yyscanner);
54 /* Clean up (release memory) */
55 scanner_finish(yyscanner);
57 if (yyresult) /* error */
60 return yyextra.parsetree;
65 * Intermediate filter between parser and core lexer (core_yylex in scan.l).
67 * The filter is needed because in some cases the standard SQL grammar
68 * requires more than one token lookahead. We reduce these cases to one-token
69 * lookahead by combining tokens here, in order to keep the grammar LALR(1).
71 * Using a filter is simpler than trying to recognize multiword tokens
72 * directly in scan.l, because we'd have to allow for comments between the
73 * words. Furthermore it's not clear how to do it without re-introducing
74 * scanner backtrack, which would cost more performance than this filter
77 * The filter also provides a convenient place to translate between
78 * the core_YYSTYPE and YYSTYPE representations (which are really the
79 * same thing anyway, but notationally they're different).
82 base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
84 base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner);
87 core_YYSTYPE cur_yylval;
90 /* Get next token --- we might already have it */
91 if (yyextra->have_lookahead)
93 cur_token = yyextra->lookahead_token;
94 lvalp->core_yystype = yyextra->lookahead_yylval;
95 *llocp = yyextra->lookahead_yylloc;
96 yyextra->have_lookahead = false;
99 cur_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
101 /* Do we need to look ahead for a possible multiword token? */
107 * NULLS FIRST and NULLS LAST must be reduced to one token
109 cur_yylval = lvalp->core_yystype;
111 next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
115 cur_token = NULLS_FIRST;
118 cur_token = NULLS_LAST;
121 /* save the lookahead token for next time */
122 yyextra->lookahead_token = next_token;
123 yyextra->lookahead_yylval = lvalp->core_yystype;
124 yyextra->lookahead_yylloc = *llocp;
125 yyextra->have_lookahead = true;
126 /* and back up the output info to cur_token */
127 lvalp->core_yystype = cur_yylval;
136 * WITH TIME and WITH ORDINALITY must each be reduced to one token
138 cur_yylval = lvalp->core_yystype;
140 next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
144 cur_token = WITH_TIME;
147 cur_token = WITH_ORDINALITY;
150 /* save the lookahead token for next time */
151 yyextra->lookahead_token = next_token;
152 yyextra->lookahead_yylval = lvalp->core_yystype;
153 yyextra->lookahead_yylloc = *llocp;
154 yyextra->have_lookahead = true;
155 /* and back up the output info to cur_token */
156 lvalp->core_yystype = cur_yylval;