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.46 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-2008, PostgreSQL Global Development Group
     * Portions Copyright (c) 1994, Regents of the University of California
     *
     * IDENTIFICATION
     *	  $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.73 2008/01/01 19:45:51 momjian Exp $
     *
     *-------------------------------------------------------------------------
     */
    
    #include "postgres.h"
    
    #include "parser/gramparse.h"	/* required before parser/parse.h! */
    #include "parser/parse.h"
    #include "parser/parser.h"
    
    
    List	   *parsetree;			/* result of parsing is left here */
    
    static bool have_lookahead;		/* is lookahead info valid? */
    static int	lookahead_token;	/* one-token lookahead */
    static YYSTYPE lookahead_yylval;	/* yylval for lookahead token */
    static YYLTYPE lookahead_yylloc;	/* yylloc for lookahead token */
    
    
    /*
     * 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)
    {
    	int			yyresult;
    
    	parsetree = NIL;			/* in case grammar forgets to set it */
    	have_lookahead = false;
    
    	scanner_init(str);
    	parser_init();
    
    	yyresult = base_yyparse();
    
    	scanner_finish();
    
    	if (yyresult)				/* error */
    		return NIL;
    
    	return parsetree;
    }
    
    
    /*
     * Intermediate filter between parser and base lexer (base_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.
     */
    int
    filtered_base_yylex(void)
    {
    	int			cur_token;
    	int			next_token;
    	YYSTYPE		cur_yylval;
    	YYLTYPE		cur_yylloc;
    
    	/* Get next token --- we might already have it */
    	if (have_lookahead)
    	{
    		cur_token = lookahead_token;
    		base_yylval = lookahead_yylval;
    		base_yylloc = lookahead_yylloc;
    		have_lookahead = false;
    	}
    	else
    		cur_token = base_yylex();
    
    	/* 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 = base_yylval;
    			cur_yylloc = base_yylloc;
    			next_token = base_yylex();
    			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 */
    					lookahead_token = next_token;
    					lookahead_yylval = base_yylval;
    					lookahead_yylloc = base_yylloc;
    					have_lookahead = true;
    					/* and back up the output info to cur_token */
    					base_yylval = cur_yylval;
    					base_yylloc = cur_yylloc;
    					break;
    			}
    			break;
    
    		case WITH:
    
    			/*
    			 * WITH CASCADED, LOCAL, or CHECK must be reduced to one token
    			 *
    			 * XXX an alternative way is to recognize just WITH_TIME and put
    			 * the ugliness into the datetime datatype productions instead of
    			 * WITH CHECK OPTION.  However that requires promoting WITH to a
    			 * fully reserved word.  If we ever have to do that anyway
    			 * (perhaps for SQL99 recursive queries), come back and simplify
    			 * this code.
    			 */
    			cur_yylval = base_yylval;
    			cur_yylloc = base_yylloc;
    			next_token = base_yylex();
    			switch (next_token)
    			{
    				case CASCADED:
    					cur_token = WITH_CASCADED;
    					break;
    				case LOCAL:
    					cur_token = WITH_LOCAL;
    					break;
    				case CHECK:
    					cur_token = WITH_CHECK;
    					break;
    				default:
    					/* save the lookahead token for next time */
    					lookahead_token = next_token;
    					lookahead_yylval = base_yylval;
    					lookahead_yylloc = base_yylloc;
    					have_lookahead = true;
    					/* and back up the output info to cur_token */
    					base_yylval = cur_yylval;
    					base_yylloc = cur_yylloc;
    					break;
    			}
    			break;
    
    		default:
    			break;
    	}
    
    	return cur_token;
    }