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/interfaces/ecpg/preproc/parser.c
00018  *
00019  *-------------------------------------------------------------------------
00020  */
00021 
00022 #include "postgres_fe.h"
00023 
00024 #include "extern.h"
00025 #include "preproc.h"
00026 
00027 
00028 static bool have_lookahead;     /* is lookahead info valid? */
00029 static int  lookahead_token;    /* one-token lookahead */
00030 static YYSTYPE lookahead_yylval;    /* yylval for lookahead token */
00031 static YYLTYPE lookahead_yylloc;    /* yylloc for lookahead token */
00032 
00033 
00034 /*
00035  * Intermediate filter between parser and base lexer (base_yylex in scan.l).
00036  *
00037  * The filter is needed because in some cases the standard SQL grammar
00038  * requires more than one token lookahead.  We reduce these cases to one-token
00039  * lookahead by combining tokens here, in order to keep the grammar LALR(1).
00040  *
00041  * Using a filter is simpler than trying to recognize multiword tokens
00042  * directly in scan.l, because we'd have to allow for comments between the
00043  * words.  Furthermore it's not clear how to do it without re-introducing
00044  * scanner backtrack, which would cost more performance than this filter
00045  * layer does.
00046  */
00047 int
00048 filtered_base_yylex(void)
00049 {
00050     int         cur_token;
00051     int         next_token;
00052     YYSTYPE     cur_yylval;
00053     YYLTYPE     cur_yylloc;
00054 
00055     /* Get next token --- we might already have it */
00056     if (have_lookahead)
00057     {
00058         cur_token = lookahead_token;
00059         base_yylval = lookahead_yylval;
00060         base_yylloc = lookahead_yylloc;
00061         have_lookahead = false;
00062     }
00063     else
00064         cur_token = base_yylex();
00065 
00066     /* Do we need to look ahead for a possible multiword token? */
00067     switch (cur_token)
00068     {
00069         case NULLS_P:
00070 
00071             /*
00072              * NULLS FIRST and NULLS LAST must be reduced to one token
00073              */
00074             cur_yylval = base_yylval;
00075             cur_yylloc = base_yylloc;
00076             next_token = base_yylex();
00077             switch (next_token)
00078             {
00079                 case FIRST_P:
00080                     cur_token = NULLS_FIRST;
00081                     break;
00082                 case LAST_P:
00083                     cur_token = NULLS_LAST;
00084                     break;
00085                 default:
00086                     /* save the lookahead token for next time */
00087                     lookahead_token = next_token;
00088                     lookahead_yylval = base_yylval;
00089                     lookahead_yylloc = base_yylloc;
00090                     have_lookahead = true;
00091                     /* and back up the output info to cur_token */
00092                     base_yylval = cur_yylval;
00093                     base_yylloc = cur_yylloc;
00094                     break;
00095             }
00096             break;
00097 
00098         case WITH:
00099 
00100             /*
00101              * WITH TIME must be reduced to one token
00102              */
00103             cur_yylval = base_yylval;
00104             cur_yylloc = base_yylloc;
00105             next_token = base_yylex();
00106             switch (next_token)
00107             {
00108                 case TIME:
00109                     cur_token = WITH_TIME;
00110                     break;
00111                 default:
00112                     /* save the lookahead token for next time */
00113                     lookahead_token = next_token;
00114                     lookahead_yylval = base_yylval;
00115                     lookahead_yylloc = base_yylloc;
00116                     have_lookahead = true;
00117                     /* and back up the output info to cur_token */
00118                     base_yylval = cur_yylval;
00119                     base_yylloc = cur_yylloc;
00120                     break;
00121             }
00122             break;
00123 
00124         default:
00125             break;
00126     }
00127 
00128     return cur_token;
00129 }