Skip to content
Snippets Groups Projects
Select Git revision
  • benchmark-tools
  • postgres-lambda
  • master default
  • REL9_4_25
  • REL9_5_20
  • REL9_6_16
  • REL_10_11
  • REL_11_6
  • REL_12_1
  • REL_12_0
  • REL_12_RC1
  • REL_12_BETA4
  • REL9_4_24
  • REL9_5_19
  • REL9_6_15
  • REL_10_10
  • REL_11_5
  • REL_12_BETA3
  • REL9_4_23
  • REL9_5_18
  • REL9_6_14
  • REL_10_9
  • REL_11_4
23 results

parser.c

Blame
  • parser.c 4.37 KiB
    /*-------------------------------------------------------------------------
     *
     * parser.c
     *		Main entry point/driver for PostgreSQL grammar
     *
     * Note that the grammar is not allowed to perform any table access
     * (since we need to be able to do basic parsing even while inside an
     * aborted transaction).  Therefore, the data structures returned by
     * the grammar are "raw" parsetrees that still need to be analyzed by
     * analyze.c and related files.
     *
     *
     * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
     * Portions Copyright (c) 1994, Regents of the University of California
     *
     * IDENTIFICATION
     *	  src/backend/parser/parser.c
     *
     *-------------------------------------------------------------------------
     */
    
    #include "postgres.h"
    
    #include "parser/gramparse.h"
    #include "parser/parser.h"
    
    
    /*
     * raw_parser
     *		Given a query in string form, do lexical and grammatical analysis.
     *
     * Returns a list of raw (un-analyzed) parse trees.
     */
    List *
    raw_parser(const char *str)
    {
    	core_yyscan_t yyscanner;
    	base_yy_extra_type yyextra;
    	int			yyresult;
    
    	/* initialize the flex scanner */
    	yyscanner = scanner_init(str, &yyextra.core_yy_extra,
    							 ScanKeywords, NumScanKeywords);
    
    	/* base_yylex() only needs this much initialization */
    	yyextra.have_lookahead = false;
    
    	/* initialize the bison parser */
    	parser_init(&yyextra);
    
    	/* Parse! */
    	yyresult = base_yyparse(yyscanner);
    
    	/* Clean up (release memory) */
    	scanner_finish(yyscanner);
    
    	if (yyresult)				/* error */
    		return NIL;
    
    	return yyextra.parsetree;
    }
    
    
    /*
     * Intermediate filter between parser and core lexer (core_yylex in scan.l).
     *
     * The filter is needed because in some cases the standard SQL grammar
     * requires more than one token lookahead.	We reduce these cases to one-token
     * lookahead by combining tokens here, in order to keep the grammar LALR(1).
     *
     * Using a filter is simpler than trying to recognize multiword tokens
     * directly in scan.l, because we'd have to allow for comments between the
     * words.  Furthermore it's not clear how to do it without re-introducing
     * scanner backtrack, which would cost more performance than this filter
     * layer does.
     *
     * The filter also provides a convenient place to translate between
     * the core_YYSTYPE and YYSTYPE representations (which are really the
     * same thing anyway, but notationally they're different).
     */
    int
    base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
    {
    	base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner);
    	int			cur_token;
    	int			next_token;
    	core_YYSTYPE cur_yylval;
    	YYLTYPE		cur_yylloc;
    
    	/* Get next token --- we might already have it */
    	if (yyextra->have_lookahead)
    	{
    		cur_token = yyextra->lookahead_token;
    		lvalp->core_yystype = yyextra->lookahead_yylval;
    		*llocp = yyextra->lookahead_yylloc;
    		yyextra->have_lookahead = false;
    	}
    	else
    		cur_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
    
    	/* Do we need to look ahead for a possible multiword token? */
    	switch (cur_token)
    	{
    		case NULLS_P:
    
    			/*
    			 * NULLS FIRST and NULLS LAST must be reduced to one token
    			 */
    			cur_yylval = lvalp->core_yystype;
    			cur_yylloc = *llocp;
    			next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
    			switch (next_token)
    			{
    				case FIRST_P:
    					cur_token = NULLS_FIRST;
    					break;
    				case LAST_P:
    					cur_token = NULLS_LAST;
    					break;
    				default:
    					/* save the lookahead token for next time */
    					yyextra->lookahead_token = next_token;
    					yyextra->lookahead_yylval = lvalp->core_yystype;
    					yyextra->lookahead_yylloc = *llocp;
    					yyextra->have_lookahead = true;
    					/* and back up the output info to cur_token */
    					lvalp->core_yystype = cur_yylval;
    					*llocp = cur_yylloc;
    					break;
    			}
    			break;
    
    		case WITH:
    
    			/*
    			 * WITH TIME must be reduced to one token
    			 */
    			cur_yylval = lvalp->core_yystype;
    			cur_yylloc = *llocp;
    			next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
    			switch (next_token)
    			{
    				case TIME:
    					cur_token = WITH_TIME;
    					break;
    				default:
    					/* save the lookahead token for next time */
    					yyextra->lookahead_token = next_token;
    					yyextra->lookahead_yylval = lvalp->core_yystype;
    					yyextra->lookahead_yylloc = *llocp;
    					yyextra->have_lookahead = true;
    					/* and back up the output info to cur_token */
    					lvalp->core_yystype = cur_yylval;
    					*llocp = cur_yylloc;
    					break;
    			}
    			break;
    
    		default:
    			break;
    	}
    
    	return cur_token;
    }