aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parser.c')
-rw-r--r--src/backend/parser/parser.c74
1 files changed, 73 insertions, 1 deletions
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index 6c331ad338d..de40e64fa8a 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -14,7 +14,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.65 2006/03/07 01:00:17 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.66 2006/05/27 17:38:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,11 +22,15 @@
#include "postgres.h"
#include "parser/gramparse.h"
+#include "parser/parse.h"
#include "parser/parser.h"
List *parsetree; /* result of parsing is left here */
+static int lookahead_token; /* one-token lookahead */
+static bool have_lookahead; /* lookahead_token set? */
+
/*
* raw_parser
@@ -40,6 +44,7 @@ raw_parser(const char *str)
int yyresult;
parsetree = NIL; /* in case grammar forgets to set it */
+ have_lookahead = false;
scanner_init(str);
parser_init();
@@ -53,3 +58,70 @@ raw_parser(const char *str)
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;
+
+ /* 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 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.
+ */
+ lookahead_token = base_yylex();
+ switch (lookahead_token)
+ {
+ case CASCADED:
+ cur_token = WITH_CASCADED;
+ break;
+ case LOCAL:
+ cur_token = WITH_LOCAL;
+ break;
+ case CHECK:
+ cur_token = WITH_CHECK;
+ break;
+ default:
+ have_lookahead = true;
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return cur_token;
+}