]> granicus.if.org Git - postgresql/blob - src/backend/parser/parser.c
541d3643a1018a2779806278620ff24455af6c73
[postgresql] / src / backend / parser / parser.c
1 /*-------------------------------------------------------------------------
2  *
3  * parser.c
4  *              Main entry point/driver for PostgreSQL grammar
5  *
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.
11  *
12  *
13  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
14  * Portions Copyright (c) 1994, Regents of the University of California
15  *
16  * IDENTIFICATION
17  *        src/backend/parser/parser.c
18  *
19  *-------------------------------------------------------------------------
20  */
21
22 #include "postgres.h"
23
24 #include "parser/gramparse.h"
25 #include "parser/parser.h"
26
27
28 /*
29  * raw_parser
30  *              Given a query in string form, do lexical and grammatical analysis.
31  *
32  * Returns a list of raw (un-analyzed) parse trees.
33  */
34 List *
35 raw_parser(const char *str)
36 {
37         core_yyscan_t yyscanner;
38         base_yy_extra_type yyextra;
39         int                     yyresult;
40
41         /* initialize the flex scanner */
42         yyscanner = scanner_init(str, &yyextra.core_yy_extra,
43                                                          ScanKeywords, NumScanKeywords);
44
45         /* base_yylex() only needs this much initialization */
46         yyextra.have_lookahead = false;
47
48         /* initialize the bison parser */
49         parser_init(&yyextra);
50
51         /* Parse! */
52         yyresult = base_yyparse(yyscanner);
53
54         /* Clean up (release memory) */
55         scanner_finish(yyscanner);
56
57         if (yyresult)                           /* error */
58                 return NIL;
59
60         return yyextra.parsetree;
61 }
62
63
64 /*
65  * Intermediate filter between parser and core lexer (core_yylex in scan.l).
66  *
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).
70  *
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
75  * layer does.
76  *
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).
80  */
81 int
82 base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
83 {
84         base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner);
85         int                     cur_token;
86         int                     next_token;
87         core_YYSTYPE cur_yylval;
88         YYLTYPE         cur_yylloc;
89
90         /* Get next token --- we might already have it */
91         if (yyextra->have_lookahead)
92         {
93                 cur_token = yyextra->lookahead_token;
94                 lvalp->core_yystype = yyextra->lookahead_yylval;
95                 *llocp = yyextra->lookahead_yylloc;
96                 yyextra->have_lookahead = false;
97         }
98         else
99                 cur_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
100
101         /* Do we need to look ahead for a possible multiword token? */
102         switch (cur_token)
103         {
104                 case NULLS_P:
105
106                         /*
107                          * NULLS FIRST and NULLS LAST must be reduced to one token
108                          */
109                         cur_yylval = lvalp->core_yystype;
110                         cur_yylloc = *llocp;
111                         next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
112                         switch (next_token)
113                         {
114                                 case FIRST_P:
115                                         cur_token = NULLS_FIRST;
116                                         break;
117                                 case LAST_P:
118                                         cur_token = NULLS_LAST;
119                                         break;
120                                 default:
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;
128                                         *llocp = cur_yylloc;
129                                         break;
130                         }
131                         break;
132
133                 case WITH:
134
135                         /*
136                          * WITH TIME and WITH ORDINALITY must each be reduced to one token
137                          */
138                         cur_yylval = lvalp->core_yystype;
139                         cur_yylloc = *llocp;
140                         next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
141                         switch (next_token)
142                         {
143                                 case TIME:
144                                         cur_token = WITH_TIME;
145                                         break;
146                                 case ORDINALITY:
147                                         cur_token = WITH_ORDINALITY;
148                                         break;
149                                 default:
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;
157                                         *llocp = cur_yylloc;
158                                         break;
159                         }
160                         break;
161
162                 default:
163                         break;
164         }
165
166         return cur_token;
167 }