Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 10bcfa1

Browse files
committed
Re-refactor the core scanner's API, in order to get out from under the problem
of different parsers having different YYSTYPE unions that they want to use with it. I defined a new union core_YYSTYPE that is just the (very short) list of semantic values returned by the core scanner. I had originally worried that this would require an extra interface layer, but actually we can have parser.c's base_yylex (formerly filtered_base_yylex) take care of that at no extra cost. Names associated with the core scanner are now "core_yy_foo", with "base_yy_foo" being used in the core Bison parser and the parser.c interface layer. This solves the last serious stumbling block to eliminating plpgsql's separate lexer. One restriction that will still be present is that plpgsql and the core will have to agree on the token numbers assigned to tokens that can be returned by the core lexer. Since Bison doesn't seem willing to accept external assignments of those numbers, we'll have to live with decreeing that core and plpgsql grammars declare these tokens first and in the same order.
1 parent 2ace38d commit 10bcfa1

File tree

5 files changed

+236
-172
lines changed

5 files changed

+236
-172
lines changed

src/backend/parser/gram.y

+24-31
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.689 2009/11/09 02:36:56 tgl Exp $
14+
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.690 2009/11/09 18:38:48 tgl Exp $
1515
*
1616
* HISTORY
1717
* AUTHOR DATE MAJOR EVENT
@@ -75,12 +75,6 @@
7575
(Current) = (Rhs)[0]; \
7676
} while (0)
7777

78-
/*
79-
* The %name-prefix option below will make bison call base_yylex, but we
80-
* really want it to call filtered_base_yylex (see parser.c).
81-
*/
82-
#define base_yylex filtered_base_yylex
83-
8478
/*
8579
* Bison doesn't allocate anything that needs to live across parser calls,
8680
* so we can easily have it use palloc instead of malloc. This prevents
@@ -104,10 +98,10 @@ typedef struct PrivTarget
10498
#define parser_yyerror(msg) scanner_yyerror(msg, yyscanner)
10599
#define parser_errposition(pos) scanner_errposition(pos, yyscanner)
106100

107-
static void base_yyerror(YYLTYPE *yylloc, base_yyscan_t yyscanner,
101+
static void base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner,
108102
const char *msg);
109103
static Node *makeColumnRef(char *colname, List *indirection,
110-
int location, base_yyscan_t yyscanner);
104+
int location, core_yyscan_t yyscanner);
111105
static Node *makeTypeCast(Node *arg, TypeName *typename, int location);
112106
static Node *makeStringConst(char *str, int location);
113107
static Node *makeStringConstCast(char *str, int location, TypeName *typename);
@@ -118,17 +112,17 @@ static Node *makeNullAConst(int location);
118112
static Node *makeAConst(Value *v, int location);
119113
static Node *makeBoolAConst(bool state, int location);
120114
static FuncCall *makeOverlaps(List *largs, List *rargs,
121-
int location, base_yyscan_t yyscanner);
122-
static void check_qualified_name(List *names, base_yyscan_t yyscanner);
123-
static List *check_func_name(List *names, base_yyscan_t yyscanner);
124-
static List *check_indirection(List *indirection, base_yyscan_t yyscanner);
115+
int location, core_yyscan_t yyscanner);
116+
static void check_qualified_name(List *names, core_yyscan_t yyscanner);
117+
static List *check_func_name(List *names, core_yyscan_t yyscanner);
118+
static List *check_indirection(List *indirection, core_yyscan_t yyscanner);
125119
static List *extractArgTypes(List *parameters);
126120
static SelectStmt *findLeftmostSelect(SelectStmt *node);
127121
static void insertSelectOptions(SelectStmt *stmt,
128122
List *sortClause, List *lockingClause,
129123
Node *limitOffset, Node *limitCount,
130124
WithClause *withClause,
131-
base_yyscan_t yyscanner);
125+
core_yyscan_t yyscanner);
132126
static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
133127
static Node *doNegate(Node *n, int location);
134128
static void doNegateFloat(Value *v);
@@ -145,15 +139,18 @@ static TypeName *TableFuncTypeName(List *columns);
145139
%name-prefix="base_yy"
146140
%locations
147141

148-
%parse-param {base_yyscan_t yyscanner}
149-
%lex-param {base_yyscan_t yyscanner}
142+
%parse-param {core_yyscan_t yyscanner}
143+
%lex-param {core_yyscan_t yyscanner}
150144

151145
%union
152146
{
147+
core_YYSTYPE core_yystype;
148+
/* these fields must match core_YYSTYPE: */
153149
int ival;
154-
char chr;
155150
char *str;
156151
const char *keyword;
152+
153+
char chr;
157154
bool boolean;
158155
JoinType jtype;
159156
DropBehavior dbehavior;
@@ -162,7 +159,6 @@ static TypeName *TableFuncTypeName(List *columns);
162159
Node *node;
163160
Value *value;
164161
ObjectType objtype;
165-
166162
TypeName *typnam;
167163
FunctionParameter *fun_param;
168164
FunctionParameterMode fun_param_mode;
@@ -180,7 +176,6 @@ static TypeName *TableFuncTypeName(List *columns);
180176
ResTarget *target;
181177
struct PrivTarget *privtarget;
182178
AccessPriv *accesspriv;
183-
184179
InsertStmt *istmt;
185180
VariableSetStmt *vsetstmt;
186181
}
@@ -602,6 +597,7 @@ static TypeName *TableFuncTypeName(List *columns);
602597
%left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
603598
/* kluge to keep xml_whitespace_option from causing shift/reduce conflicts */
604599
%right PRESERVE STRIP_P
600+
605601
%%
606602

607603
/*
@@ -10932,14 +10928,14 @@ reserved_keyword:
1093210928
* available from the scanner.
1093310929
*/
1093410930
static void
10935-
base_yyerror(YYLTYPE *yylloc, base_yyscan_t yyscanner, const char *msg)
10931+
base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner, const char *msg)
1093610932
{
1093710933
parser_yyerror(msg);
1093810934
}
1093910935

1094010936
static Node *
1094110937
makeColumnRef(char *colname, List *indirection,
10942-
int location, base_yyscan_t yyscanner)
10938+
int location, core_yyscan_t yyscanner)
1094310939
{
1094410940
/*
1094510941
* Generate a ColumnRef node, with an A_Indirection node added if there
@@ -11109,7 +11105,7 @@ makeBoolAConst(bool state, int location)
1110911105
* Create and populate a FuncCall node to support the OVERLAPS operator.
1111011106
*/
1111111107
static FuncCall *
11112-
makeOverlaps(List *largs, List *rargs, int location, base_yyscan_t yyscanner)
11108+
makeOverlaps(List *largs, List *rargs, int location, core_yyscan_t yyscanner)
1111311109
{
1111411110
FuncCall *n = makeNode(FuncCall);
1111511111

@@ -11143,7 +11139,7 @@ makeOverlaps(List *largs, List *rargs, int location, base_yyscan_t yyscanner)
1114311139
* subscripts and '*', which we then must reject here.
1114411140
*/
1114511141
static void
11146-
check_qualified_name(List *names, base_yyscan_t yyscanner)
11142+
check_qualified_name(List *names, core_yyscan_t yyscanner)
1114711143
{
1114811144
ListCell *i;
1114911145

@@ -11160,7 +11156,7 @@ check_qualified_name(List *names, base_yyscan_t yyscanner)
1116011156
* and '*', which we then must reject here.
1116111157
*/
1116211158
static List *
11163-
check_func_name(List *names, base_yyscan_t yyscanner)
11159+
check_func_name(List *names, core_yyscan_t yyscanner)
1116411160
{
1116511161
ListCell *i;
1116611162

@@ -11178,7 +11174,7 @@ check_func_name(List *names, base_yyscan_t yyscanner)
1117811174
* in the grammar, so do it here.
1117911175
*/
1118011176
static List *
11181-
check_indirection(List *indirection, base_yyscan_t yyscanner)
11177+
check_indirection(List *indirection, core_yyscan_t yyscanner)
1118211178
{
1118311179
ListCell *l;
1118411180

@@ -11237,7 +11233,7 @@ insertSelectOptions(SelectStmt *stmt,
1123711233
List *sortClause, List *lockingClause,
1123811234
Node *limitOffset, Node *limitCount,
1123911235
WithClause *withClause,
11240-
base_yyscan_t yyscanner)
11236+
core_yyscan_t yyscanner)
1124111237
{
1124211238
Assert(IsA(stmt, SelectStmt));
1124311239

@@ -11463,12 +11459,9 @@ TableFuncTypeName(List *columns)
1146311459
}
1146411460

1146511461
/*
11466-
* Must undefine base_yylex before including scan.c, since we want it
11467-
* to create the function base_yylex not filtered_base_yylex.
11462+
* Must undefine this stuff before including scan.c, since it has different
11463+
* definitions for these macros.
1146811464
*/
11469-
#undef base_yylex
11470-
11471-
/* Undefine some other stuff that would conflict in scan.c, too */
1147211465
#undef yyerror
1147311466
#undef yylval
1147411467
#undef yylloc

src/backend/parser/parser.c

+27-21
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* Portions Copyright (c) 1994, Regents of the University of California
1515
*
1616
* IDENTIFICATION
17-
* $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.81 2009/07/14 20:24:10 tgl Exp $
17+
* $PostgreSQL: pgsql/src/backend/parser/parser.c,v 1.82 2009/11/09 18:38:48 tgl Exp $
1818
*
1919
*-------------------------------------------------------------------------
2020
*/
@@ -34,14 +34,15 @@
3434
List *
3535
raw_parser(const char *str)
3636
{
37-
base_yyscan_t yyscanner;
37+
core_yyscan_t yyscanner;
3838
base_yy_extra_type yyextra;
3939
int yyresult;
4040

4141
/* initialize the flex scanner */
42-
yyscanner = scanner_init(str, &yyextra, ScanKeywords, NumScanKeywords);
42+
yyscanner = scanner_init(str, &yyextra.core_yy_extra,
43+
ScanKeywords, NumScanKeywords);
4344

44-
/* filtered_base_yylex() only needs this much initialization */
45+
/* base_yylex() only needs this much initialization */
4546
yyextra.have_lookahead = false;
4647

4748
/* initialize the bison parser */
@@ -73,15 +74,16 @@ raw_parser(const char *str)
7374
char *
7475
pg_parse_string_token(const char *token)
7576
{
76-
base_yyscan_t yyscanner;
77+
core_yyscan_t yyscanner;
7778
base_yy_extra_type yyextra;
7879
int ctoken;
79-
YYSTYPE yylval;
80+
core_YYSTYPE yylval;
8081
YYLTYPE yylloc;
8182

82-
yyscanner = scanner_init(token, &yyextra, ScanKeywords, NumScanKeywords);
83+
yyscanner = scanner_init(token, &yyextra.core_yy_extra,
84+
ScanKeywords, NumScanKeywords);
8385

84-
ctoken = base_yylex(&yylval, &yylloc, yyscanner);
86+
ctoken = core_yylex(&yylval, &yylloc, yyscanner);
8587

8688
if (ctoken != SCONST) /* caller error */
8789
elog(ERROR, "expected string constant, got token code %d", ctoken);
@@ -93,7 +95,7 @@ pg_parse_string_token(const char *token)
9395

9496

9597
/*
96-
* Intermediate filter between parser and base lexer (base_yylex in scan.l).
98+
* Intermediate filter between parser and core lexer (core_yylex in scan.l).
9799
*
98100
* The filter is needed because in some cases the standard SQL grammar
99101
* requires more than one token lookahead. We reduce these cases to one-token
@@ -104,26 +106,30 @@ pg_parse_string_token(const char *token)
104106
* words. Furthermore it's not clear how to do it without re-introducing
105107
* scanner backtrack, which would cost more performance than this filter
106108
* layer does.
109+
*
110+
* The filter also provides a convenient place to translate between
111+
* the core_YYSTYPE and YYSTYPE representations (which are really the
112+
* same thing anyway, but notationally they're different).
107113
*/
108114
int
109-
filtered_base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, base_yyscan_t yyscanner)
115+
base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
110116
{
111117
base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner);
112118
int cur_token;
113119
int next_token;
114-
YYSTYPE cur_yylval;
120+
core_YYSTYPE cur_yylval;
115121
YYLTYPE cur_yylloc;
116122

117123
/* Get next token --- we might already have it */
118124
if (yyextra->have_lookahead)
119125
{
120126
cur_token = yyextra->lookahead_token;
121-
*lvalp = yyextra->lookahead_yylval;
127+
lvalp->core_yystype = yyextra->lookahead_yylval;
122128
*llocp = yyextra->lookahead_yylloc;
123129
yyextra->have_lookahead = false;
124130
}
125131
else
126-
cur_token = base_yylex(lvalp, llocp, yyscanner);
132+
cur_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
127133

128134
/* Do we need to look ahead for a possible multiword token? */
129135
switch (cur_token)
@@ -133,9 +139,9 @@ filtered_base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, base_yyscan_t yyscanner)
133139
/*
134140
* NULLS FIRST and NULLS LAST must be reduced to one token
135141
*/
136-
cur_yylval = *lvalp;
142+
cur_yylval = lvalp->core_yystype;
137143
cur_yylloc = *llocp;
138-
next_token = base_yylex(lvalp, llocp, yyscanner);
144+
next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
139145
switch (next_token)
140146
{
141147
case FIRST_P:
@@ -147,11 +153,11 @@ filtered_base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, base_yyscan_t yyscanner)
147153
default:
148154
/* save the lookahead token for next time */
149155
yyextra->lookahead_token = next_token;
150-
yyextra->lookahead_yylval = *lvalp;
156+
yyextra->lookahead_yylval = lvalp->core_yystype;
151157
yyextra->lookahead_yylloc = *llocp;
152158
yyextra->have_lookahead = true;
153159
/* and back up the output info to cur_token */
154-
*lvalp = cur_yylval;
160+
lvalp->core_yystype = cur_yylval;
155161
*llocp = cur_yylloc;
156162
break;
157163
}
@@ -162,9 +168,9 @@ filtered_base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, base_yyscan_t yyscanner)
162168
/*
163169
* WITH TIME must be reduced to one token
164170
*/
165-
cur_yylval = *lvalp;
171+
cur_yylval = lvalp->core_yystype;
166172
cur_yylloc = *llocp;
167-
next_token = base_yylex(lvalp, llocp, yyscanner);
173+
next_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner);
168174
switch (next_token)
169175
{
170176
case TIME:
@@ -173,11 +179,11 @@ filtered_base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, base_yyscan_t yyscanner)
173179
default:
174180
/* save the lookahead token for next time */
175181
yyextra->lookahead_token = next_token;
176-
yyextra->lookahead_yylval = *lvalp;
182+
yyextra->lookahead_yylval = lvalp->core_yystype;
177183
yyextra->lookahead_yylloc = *llocp;
178184
yyextra->have_lookahead = true;
179185
/* and back up the output info to cur_token */
180-
*lvalp = cur_yylval;
186+
lvalp->core_yystype = cur_yylval;
181187
*llocp = cur_yylloc;
182188
break;
183189
}

0 commit comments

Comments
 (0)