예제 #1
0
파일: parser.c 프로젝트: sunyangkobe/cscd43
/*
 * Intermediate filter between parser and base lexer (base_yylex in scan.l).
 *
 * The filter is needed because in some cases SQL92 requires more than one
 * token lookahead.  We reduce these cases to one-token lookahead by combining
 * tokens here, in order to keep the grammar LR(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 ...
 */
int
yylex(void)
{
	int			cur_token;

	/* Get next token --- we might already have it */
	if (have_lookahead)
	{
		cur_token = lookahead_token;
		have_lookahead = false;
	}
	else
		cur_token = base_yylex();

	/* Do we need to look ahead for a possible multiword token? */
	switch (cur_token)
	{
		case UNION:
			/* UNION JOIN must be reduced to a single UNIONJOIN token */
			lookahead_token = base_yylex();
			if (lookahead_token == JOIN)
				cur_token = UNIONJOIN;
			else
				have_lookahead = true;
			break;

		default:
			break;
	}

	return cur_token;
}
예제 #2
0
/*
 * 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;
}
예제 #3
0
/*
 * 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, 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 TIME:
					cur_token = WITH_TIME;
					break;
				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;
}