Logo Search packages:      
Sourcecode: postgresql-8.4 version File versions  Download package

parser.c
/*-------------------------------------------------------------------------
 *
 * 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-2009, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * IDENTIFICATION
 *      $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.78 2009/06/11 14:49:00 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include "parser/gramparse.h" /* required before parser/gram.h! */
#include "parser/gram.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;
}


/*
 * pg_parse_string_token - get the value represented by a string literal
 *
 * Given the textual form of a SQL string literal, produce the represented
 * value as a palloc'd string.  It is caller's responsibility that the
 * passed string does represent one single string literal.
 *
 * We export this function to avoid having plpgsql depend on internal details
 * of the core grammar (such as the token code assigned to SCONST).  Note
 * that since the scanner isn't presently re-entrant, this cannot be used
 * during use of the main parser/scanner.
 */
char *
pg_parse_string_token(const char *token)
{
      int               ctoken;

      scanner_init(token);

      ctoken = base_yylex();

      if (ctoken != SCONST)         /* caller error */
            elog(ERROR, "expected string constant, got token code %d", ctoken);

      scanner_finish();

      return base_yylval.str;
}


/*
 * 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 TIME must be reduced to one token
                   */
                  cur_yylval = base_yylval;
                  cur_yylloc = base_yylloc;
                  next_token = base_yylex();
                  switch (next_token)
                  {
                        case TIME:
                              cur_token = WITH_TIME;
                              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;
}

Generated by  Doxygen 1.6.0   Back to index