Header And Logo

PostgreSQL
| The world's most advanced open source database.

parser.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * parser.c
00004  *      Main entry point/driver for PostgreSQL grammar
00005  *
00006  * Note that the grammar is not allowed to perform any table access
00007  * (since we need to be able to do basic parsing even while inside an
00008  * aborted transaction).  Therefore, the data structures returned by
00009  * the grammar are "raw" parsetrees that still need to be analyzed by
00010  * analyze.c and related files.
00011  *
00012  *
00013  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00014  * Portions Copyright (c) 1994, Regents of the University of California
00015  *
00016  * IDENTIFICATION
00017  *    src/backend/parser/parser.c
00018  *
00019  *-------------------------------------------------------------------------
00020  */
00021 
00022 #include "postgres.h"
00023 
00024 #include "parser/gramparse.h"
00025 #include "parser/parser.h"
00026 
00027 
00028 /*
00029  * raw_parser
00030  *      Given a query in string form, do lexical and grammatical analysis.
00031  *
00032  * Returns a list of raw (un-analyzed) parse trees.
00033  */
00034 List *
00035 raw_parser(const char *str)
00036 {
00037     core_yyscan_t yyscanner;
00038     base_yy_extra_type yyextra;
00039     int         yyresult;
00040 
00041     /* initialize the flex scanner */
00042     yyscanner = scanner_init(str, &yyextra.core_yy_extra,
00043                              ScanKeywords, NumScanKeywords);
00044 
00045     /* base_yylex() only needs this much initialization */
00046     yyextra.have_lookahead = false;
00047 
00048     /* initialize the bison parser */
00049     parser_init(&yyextra);
00050 
00051     /* Parse! */
00052     yyresult = base_yyparse(yyscanner);
00053 
00054     /* Clean up (release memory) */
00055     scanner_finish(yyscanner);
00056 
00057     if (yyresult)               /* error */
00058         return NIL;
00059 
00060     return yyextra.parsetree;
00061 }
00062 
00063 
00064 /*
00065  * Intermediate filter between parser and core lexer (core_yylex in scan.l).
00066  *
00067  * The filter is needed because in some cases the standard SQL grammar
00068  * requires more than one token lookahead.  We reduce these cases to one-token
00069  * lookahead by combining tokens here, in order to keep the grammar LALR(1).
00070  *
00071  * Using a filter is simpler than trying to recognize multiword tokens
00072  * directly in scan.l, because we'd have to allow for comments between the
00073  * words.  Furthermore it's not clear how to do it without re-introducing
00074  * scanner backtrack, which would cost more performance than this filter
00075  * layer does.
00076  *
00077  * The filter also provides a convenient place to translate between
00078  * the core_YYSTYPE and YYSTYPE representations (which are really the
00079  * same thing anyway, but notationally they're different).
00080  */
00081 int
00082 base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
00083 {
00084     base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner);
00085     int         cur_token;
00086     int         next_token;
00087     core_YYSTYPE cur_yylval;
00088     YYLTYPE     cur_yylloc;
00089 
00090     /* Get next token --- we might already have it */
00091     if (yyextra->have_lookahead)
00092     {
00093         cur_token = yyextra->lookahead_token;
00094         lvalp->core_yystype = yyextra->lookahead_yylval;
00095         *llocp = yyextra->lookahead_yylloc;
00096         yyextra->have_lookahead = false;
00097     }
00098     else
00099         cur_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
00100 
00101     /* Do we need to look ahead for a possible multiword token? */
00102     switch (cur_token)
00103     {
00104         case NULLS_P:
00105 
00106             /*
00107              * NULLS FIRST and NULLS LAST must be reduced to one token
00108              */
00109             cur_yylval = lvalp->core_yystype;
00110             cur_yylloc = *llocp;
00111             next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
00112             switch (next_token)
00113             {
00114                 case FIRST_P:
00115                     cur_token = NULLS_FIRST;
00116                     break;
00117                 case LAST_P:
00118                     cur_token = NULLS_LAST;
00119                     break;
00120                 default:
00121                     /* save the lookahead token for next time */
00122                     yyextra->lookahead_token = next_token;
00123                     yyextra->lookahead_yylval = lvalp->core_yystype;
00124                     yyextra->lookahead_yylloc = *llocp;
00125                     yyextra->have_lookahead = true;
00126                     /* and back up the output info to cur_token */
00127                     lvalp->core_yystype = cur_yylval;
00128                     *llocp = cur_yylloc;
00129                     break;
00130             }
00131             break;
00132 
00133         case WITH:
00134 
00135             /*
00136              * WITH TIME must be reduced to one token
00137              */
00138             cur_yylval = lvalp->core_yystype;
00139             cur_yylloc = *llocp;
00140             next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
00141             switch (next_token)
00142             {
00143                 case TIME:
00144                     cur_token = WITH_TIME;
00145                     break;
00146                 default:
00147                     /* save the lookahead token for next time */
00148                     yyextra->lookahead_token = next_token;
00149                     yyextra->lookahead_yylval = lvalp->core_yystype;
00150                     yyextra->lookahead_yylloc = *llocp;
00151                     yyextra->have_lookahead = true;
00152                     /* and back up the output info to cur_token */
00153                     lvalp->core_yystype = cur_yylval;
00154                     *llocp = cur_yylloc;
00155                     break;
00156             }
00157             break;
00158 
00159         default:
00160             break;
00161     }
00162 
00163     return cur_token;
00164 }