Commit f9e2c7fa authored by Tom Lane's avatar Tom Lane

Allow bare column names to be subscripted as arrays. This

creates a reduce/reduce conflict, which I resolved by changing the
'AexprConst -> Typename Sconst' rule to 'AexprConst -> SimpleTypename Sconst'.
In other words, a subscripted type declaration can't be used in that
syntax any longer.  This seems a small price to pay for not having to
qualify subscripted columns anymore.
Other cleanups: rename res_target_list to update_target_list, and remove
productions for variants that are not legal in an UPDATE target list;
rename res_target_list2 to plain target_list; delete position_expr
in favor of using b_expr in that production; merge opt_indirection
into attr nonterminal, since there are no places where an unsubscripted
attr is wanted; fix typos in Param support; change case_arg so that
an arbitrary a_expr is allowed, not only a column name.
parent bc9236bc
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.91 1999/07/16 04:59:29 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.92 1999/07/16 22:29:42 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -169,8 +169,8 @@ Oid param_type(int t); /* used in parse_expr.c */ ...@@ -169,8 +169,8 @@ Oid param_type(int t); /* used in parse_expr.c */
oper_argtypes, RuleActionList, RuleActionBlock, RuleActionMulti, oper_argtypes, RuleActionList, RuleActionBlock, RuleActionMulti,
opt_column_list, columnList, opt_va_list, va_list, opt_column_list, columnList, opt_va_list, va_list,
sort_clause, sortby_list, index_params, index_list, name_list, sort_clause, sortby_list, index_params, index_list, name_list,
from_clause, from_expr, table_list, opt_array_bounds, nest_array_bounds, from_clause, from_expr, table_list, opt_array_bounds,
expr_list, attrs, res_target_list, res_target_list2, expr_list, attrs, target_list, update_target_list,
def_list, opt_indirection, group_clause, TriggerFuncArgs, def_list, opt_indirection, group_clause, TriggerFuncArgs,
opt_select_limit opt_select_limit
...@@ -189,7 +189,6 @@ Oid param_type(int t); /* used in parse_expr.c */ ...@@ -189,7 +189,6 @@ Oid param_type(int t); /* used in parse_expr.c */
%type <str> join_outer %type <str> join_outer
%type <ival> join_type %type <ival> join_type
%type <node> position_expr
%type <list> extract_list, position_list %type <list> extract_list, position_list
%type <list> substr_list, substr_from, substr_for, trim_list %type <list> substr_list, substr_from, substr_for, trim_list
%type <list> opt_interval %type <list> opt_interval
...@@ -232,10 +231,11 @@ Oid param_type(int t); /* used in parse_expr.c */ ...@@ -232,10 +231,11 @@ Oid param_type(int t); /* used in parse_expr.c */
%type <ielem> index_elem, func_index %type <ielem> index_elem, func_index
%type <range> table_expr %type <range> table_expr
%type <relexp> relation_expr %type <relexp> relation_expr
%type <target> res_target_el, res_target_el2 %type <target> target_el, update_target_el
%type <paramno> ParamNo %type <paramno> ParamNo
%type <typnam> Typename, opt_type, Array, Generic, Character, Datetime, Numeric %type <typnam> Typename, opt_type, SimpleTypename,
Generic, Numeric, Character, Datetime
%type <str> generic, numeric, character, datetime %type <str> generic, numeric, character, datetime
%type <str> extract_arg %type <str> extract_arg
%type <str> opt_charset, opt_collate %type <str> opt_charset, opt_collate
...@@ -687,6 +687,10 @@ ClosePortalStmt: CLOSE opt_id ...@@ -687,6 +687,10 @@ ClosePortalStmt: CLOSE opt_id
} }
; ;
opt_id: ColId { $$ = $1; }
| /*EMPTY*/ { $$ = NULL; }
;
/***************************************************************************** /*****************************************************************************
* *
...@@ -2476,7 +2480,7 @@ InsertStmt: INSERT INTO relation_name insert_rest ...@@ -2476,7 +2480,7 @@ InsertStmt: INSERT INTO relation_name insert_rest
} }
; ;
insert_rest: VALUES '(' res_target_list2 ')' insert_rest: VALUES '(' target_list ')'
{ {
$$ = makeNode(InsertStmt); $$ = makeNode(InsertStmt);
$$->cols = NULL; $$->cols = NULL;
...@@ -2519,7 +2523,7 @@ insert_rest: VALUES '(' res_target_list2 ')' ...@@ -2519,7 +2523,7 @@ insert_rest: VALUES '(' res_target_list2 ')'
$$->intersectClause = n->intersectClause; $$->intersectClause = n->intersectClause;
$$->forUpdate = n->forUpdate; $$->forUpdate = n->forUpdate;
} }
| '(' columnList ')' VALUES '(' res_target_list2 ')' | '(' columnList ')' VALUES '(' target_list ')'
{ {
$$ = makeNode(InsertStmt); $$ = makeNode(InsertStmt);
$$->cols = $2; $$->cols = $2;
...@@ -2621,7 +2625,7 @@ opt_lmode: SHARE { $$ = TRUE; } ...@@ -2621,7 +2625,7 @@ opt_lmode: SHARE { $$ = TRUE; }
*****************************************************************************/ *****************************************************************************/
UpdateStmt: UPDATE relation_name UpdateStmt: UPDATE relation_name
SET res_target_list SET update_target_list
from_clause from_clause
where_clause where_clause
{ {
...@@ -2804,7 +2808,7 @@ select_clause: '(' select_clause ')' ...@@ -2804,7 +2808,7 @@ select_clause: '(' select_clause ')'
} }
; ;
SubSelect: SELECT opt_unique res_target_list2 SubSelect: SELECT opt_unique target_list
result from_clause where_clause result from_clause where_clause
group_clause having_clause group_clause having_clause
{ {
...@@ -3183,17 +3187,9 @@ relation_expr: relation_name ...@@ -3183,17 +3187,9 @@ relation_expr: relation_name
$$->inh = TRUE; $$->inh = TRUE;
} }
opt_array_bounds: '[' ']' nest_array_bounds opt_array_bounds: '[' ']' opt_array_bounds
{ $$ = lcons(makeInteger(-1), $3); } { $$ = lcons(makeInteger(-1), $3); }
| '[' Iconst ']' nest_array_bounds | '[' Iconst ']' opt_array_bounds
{ $$ = lcons(makeInteger($2), $4); }
| /*EMPTY*/
{ $$ = NIL; }
;
nest_array_bounds: '[' ']' nest_array_bounds
{ $$ = lcons(makeInteger(-1), $3); }
| '[' Iconst ']' nest_array_bounds
{ $$ = lcons(makeInteger($2), $4); } { $$ = lcons(makeInteger($2), $4); }
| /*EMPTY*/ | /*EMPTY*/
{ $$ = NIL; } { $$ = NIL; }
...@@ -3210,7 +3206,7 @@ nest_array_bounds: '[' ']' nest_array_bounds ...@@ -3210,7 +3206,7 @@ nest_array_bounds: '[' ']' nest_array_bounds
* *
*****************************************************************************/ *****************************************************************************/
Typename: Array opt_array_bounds Typename: SimpleTypename opt_array_bounds
{ {
$$ = $1; $$ = $1;
$$->arrayBounds = $2; $$->arrayBounds = $2;
...@@ -3232,17 +3228,17 @@ Typename: Array opt_array_bounds ...@@ -3232,17 +3228,17 @@ Typename: Array opt_array_bounds
else else
$$->setof = FALSE; $$->setof = FALSE;
} }
| SETOF Array | SETOF SimpleTypename
{ {
$$ = $2; $$ = $2;
$$->setof = TRUE; $$->setof = TRUE;
} }
; ;
Array: Generic SimpleTypename: Generic
| Datetime
| Numeric | Numeric
| Character | Character
| Datetime
; ;
Generic: generic Generic: generic
...@@ -3254,7 +3250,7 @@ Generic: generic ...@@ -3254,7 +3250,7 @@ Generic: generic
; ;
generic: IDENT { $$ = $1; } generic: IDENT { $$ = $1; }
| TYPE_P { $$ = xlateSqlType("type"); } | TYPE_P { $$ = "type"; }
; ;
/* SQL92 numeric data types /* SQL92 numeric data types
...@@ -3615,21 +3611,18 @@ sub_type: ANY { $$ = ANY_SUBLINK; } ...@@ -3615,21 +3611,18 @@ sub_type: ANY { $$ = ANY_SUBLINK; }
* All operations/expressions are allowed in a BETWEEN clause * All operations/expressions are allowed in a BETWEEN clause
* if surrounded by parens. * if surrounded by parens.
*/ */
a_expr: attr opt_indirection a_expr: attr
{ { $$ = (Node *) $1; }
$1->indirection = $2;
$$ = (Node *)$1;
}
| row_expr | row_expr
{ $$ = $1; } { $$ = $1; }
| AexprConst | AexprConst
{ $$ = $1; } { $$ = $1; }
| ColId | ColId opt_indirection
{ {
/* could be a column name or a relation_name */ /* could be a column name or a relation_name */
Ident *n = makeNode(Ident); Ident *n = makeNode(Ident);
n->name = $1; n->name = $1;
n->indirection = NULL; n->indirection = $2;
$$ = (Node *)n; $$ = (Node *)n;
} }
| '-' a_expr %prec UMINUS | '-' a_expr %prec UMINUS
...@@ -3679,7 +3672,7 @@ a_expr: attr opt_indirection ...@@ -3679,7 +3672,7 @@ a_expr: attr opt_indirection
/* AexprConst can be either A_Const or ParamNo */ /* AexprConst can be either A_Const or ParamNo */
if (nodeTag($1) == T_A_Const) { if (nodeTag($1) == T_A_Const) {
((A_Const *)$1)->typename = $3; ((A_Const *)$1)->typename = $3;
} else if (nodeTag($1) == T_Param) { } else if (nodeTag($1) == T_ParamNo) {
((ParamNo *)$1)->typename = $3; ((ParamNo *)$1)->typename = $3;
/* otherwise, try to transform to a function call */ /* otherwise, try to transform to a function call */
} else { } else {
...@@ -3695,7 +3688,7 @@ a_expr: attr opt_indirection ...@@ -3695,7 +3688,7 @@ a_expr: attr opt_indirection
/* AexprConst can be either A_Const or ParamNo */ /* AexprConst can be either A_Const or ParamNo */
if (nodeTag($3) == T_A_Const) { if (nodeTag($3) == T_A_Const) {
((A_Const *)$3)->typename = $5; ((A_Const *)$3)->typename = $5;
} else if (nodeTag($5) == T_Param) { } else if (nodeTag($3) == T_ParamNo) {
((ParamNo *)$3)->typename = $5; ((ParamNo *)$3)->typename = $5;
/* otherwise, try to transform to a function call */ /* otherwise, try to transform to a function call */
} else { } else {
...@@ -4282,21 +4275,19 @@ a_expr: attr opt_indirection ...@@ -4282,21 +4275,19 @@ a_expr: attr opt_indirection
/* Restricted expressions /* Restricted expressions
* b_expr is a subset of the complete expression syntax * b_expr is a subset of the complete expression syntax
* defined by a_expr. b_expr is used in BETWEEN clauses * defined by a_expr. b_expr is used in BETWEEN clauses
* to eliminate parser ambiguities stemming from the AND keyword. * to eliminate parser ambiguities stemming from the AND keyword,
* and also in POSITION clauses where the IN keyword gives trouble.
*/ */
b_expr: attr opt_indirection b_expr: attr
{ { $$ = (Node *) $1; }
$1->indirection = $2;
$$ = (Node *)$1;
}
| AexprConst | AexprConst
{ $$ = $1; } { $$ = $1; }
| ColId | ColId opt_indirection
{ {
/* could be a column name or a relation_name */ /* could be a column name or a relation_name */
Ident *n = makeNode(Ident); Ident *n = makeNode(Ident);
n->name = $1; n->name = $1;
n->indirection = NULL; n->indirection = $2;
$$ = (Node *)n; $$ = (Node *)n;
} }
| '-' b_expr %prec UMINUS | '-' b_expr %prec UMINUS
...@@ -4317,10 +4308,10 @@ b_expr: attr opt_indirection ...@@ -4317,10 +4308,10 @@ b_expr: attr opt_indirection
{ $$ = makeA_Expr(OP, "/", $1, $3); } { $$ = makeA_Expr(OP, "/", $1, $3); }
| b_expr '%' b_expr | b_expr '%' b_expr
{ $$ = makeA_Expr(OP, "%", $1, $3); } { $$ = makeA_Expr(OP, "%", $1, $3); }
| b_expr '^' b_expr
{ $$ = makeA_Expr(OP, "^", $1, $3); }
| b_expr '*' b_expr | b_expr '*' b_expr
{ $$ = makeA_Expr(OP, "*", $1, $3); } { $$ = makeA_Expr(OP, "*", $1, $3); }
| b_expr '^' b_expr
{ $$ = makeA_Expr(OP, "^", $1, $3); }
| ':' b_expr | ':' b_expr
{ $$ = makeA_Expr(OP, ":", NULL, $2); } { $$ = makeA_Expr(OP, ":", NULL, $2); }
| ';' b_expr | ';' b_expr
...@@ -4333,7 +4324,7 @@ b_expr: attr opt_indirection ...@@ -4333,7 +4324,7 @@ b_expr: attr opt_indirection
/* AexprConst can be either A_Const or ParamNo */ /* AexprConst can be either A_Const or ParamNo */
if (nodeTag($1) == T_A_Const) { if (nodeTag($1) == T_A_Const) {
((A_Const *)$1)->typename = $3; ((A_Const *)$1)->typename = $3;
} else if (nodeTag($1) == T_Param) { } else if (nodeTag($1) == T_ParamNo) {
((ParamNo *)$1)->typename = $3; ((ParamNo *)$1)->typename = $3;
/* otherwise, try to transform to a function call */ /* otherwise, try to transform to a function call */
} else { } else {
...@@ -4349,7 +4340,7 @@ b_expr: attr opt_indirection ...@@ -4349,7 +4340,7 @@ b_expr: attr opt_indirection
/* AexprConst can be either A_Const or ParamNo */ /* AexprConst can be either A_Const or ParamNo */
if (nodeTag($3) == T_A_Const) { if (nodeTag($3) == T_A_Const) {
((A_Const *)$3)->typename = $5; ((A_Const *)$3)->typename = $5;
} else if (nodeTag($3) == T_Param) { } else if (nodeTag($3) == T_ParamNo) {
((ParamNo *)$3)->typename = $5; ((ParamNo *)$3)->typename = $5;
/* otherwise, try to transform to a function call */ /* otherwise, try to transform to a function call */
} else { } else {
...@@ -4571,140 +4562,14 @@ extract_arg: datetime { $$ = $1; } ...@@ -4571,140 +4562,14 @@ extract_arg: datetime { $$ = $1; }
| TIMEZONE_MINUTE { $$ = "tz_minute"; } | TIMEZONE_MINUTE { $$ = "tz_minute"; }
; ;
position_list: position_expr IN position_expr /* position_list uses b_expr not a_expr to avoid conflict with general IN */
position_list: b_expr IN b_expr
{ $$ = makeList($3, $1, -1); } { $$ = makeList($3, $1, -1); }
| /*EMPTY*/ | /*EMPTY*/
{ $$ = NIL; } { $$ = NIL; }
; ;
position_expr: attr opt_indirection
{
$1->indirection = $2;
$$ = (Node *)$1;
}
| AexprConst
{ $$ = $1; }
| '-' position_expr %prec UMINUS
{ $$ = makeA_Expr(OP, "-", NULL, $2); }
| position_expr '+' position_expr
{ $$ = makeA_Expr(OP, "+", $1, $3); }
| position_expr '-' position_expr
{ $$ = makeA_Expr(OP, "-", $1, $3); }
| position_expr '/' position_expr
{ $$ = makeA_Expr(OP, "/", $1, $3); }
| position_expr '%' position_expr
{ $$ = makeA_Expr(OP, "%", $1, $3); }
| position_expr '*' position_expr
{ $$ = makeA_Expr(OP, "*", $1, $3); }
| '|' position_expr
{ $$ = makeA_Expr(OP, "|", NULL, $2); }
| position_expr TYPECAST Typename
{
$$ = (Node *)$1;
/* AexprConst can be either A_Const or ParamNo */
if (nodeTag($1) == T_A_Const) {
((A_Const *)$1)->typename = $3;
} else if (nodeTag($1) == T_Param) {
((ParamNo *)$1)->typename = $3;
/* otherwise, try to transform to a function call */
} else {
FuncCall *n = makeNode(FuncCall);
n->funcname = $3->name;
n->args = lcons($1,NIL);
$$ = (Node *)n;
}
}
| CAST '(' position_expr AS Typename ')'
{
$$ = (Node *)$3;
/* AexprConst can be either A_Const or ParamNo */
if (nodeTag($3) == T_A_Const) {
((A_Const *)$3)->typename = $5;
} else if (nodeTag($3) == T_Param) {
((ParamNo *)$3)->typename = $5;
/* otherwise, try to transform to a function call */
} else {
FuncCall *n = makeNode(FuncCall);
n->funcname = $5->name;
n->args = lcons($3,NIL);
$$ = (Node *)n;
}
}
| '(' position_expr ')'
{ $$ = $2; }
| position_expr Op position_expr
{ $$ = makeA_Expr(OP, $2, $1, $3); }
| Op position_expr
{ $$ = makeA_Expr(OP, $1, NULL, $2); }
| position_expr Op
{ $$ = makeA_Expr(OP, $2, $1, NULL); }
| ColId
{
/* could be a column name or a relation_name */
Ident *n = makeNode(Ident);
n->name = $1;
n->indirection = NULL;
$$ = (Node *)n;
}
| func_name '(' ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = NIL;
$$ = (Node *)n;
}
| func_name '(' expr_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = $3;
$$ = (Node *)n;
}
| POSITION '(' position_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "strpos";
n->args = $3;
$$ = (Node *)n;
}
| SUBSTRING '(' substr_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "substr";
n->args = $3;
$$ = (Node *)n;
}
/* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
| TRIM '(' BOTH trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "btrim";
n->args = $4;
$$ = (Node *)n;
}
| TRIM '(' LEADING trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "ltrim";
n->args = $4;
$$ = (Node *)n;
}
| TRIM '(' TRAILING trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "rtrim";
n->args = $4;
$$ = (Node *)n;
}
| TRIM '(' trim_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "btrim";
n->args = $3;
$$ = (Node *)n;
}
;
substr_list: expr_list substr_from substr_for substr_list: expr_list substr_from substr_for
{ {
$$ = nconc(nconc($1,$2),$3); $$ = nconc(nconc($1,$2),$3);
...@@ -4846,38 +4711,27 @@ case_default: ELSE a_expr_or_null { $$ = $2; } ...@@ -4846,38 +4711,27 @@ case_default: ELSE a_expr_or_null { $$ = $2; }
| /*EMPTY*/ { $$ = NULL; } | /*EMPTY*/ { $$ = NULL; }
; ;
case_arg: attr opt_indirection case_arg: a_expr
{ { $$ = $1; }
$1->indirection = $2;
$$ = (Node *)$1;
}
| ColId
{
/* could be a column name or a relation_name */
Ident *n = makeNode(Ident);
n->name = $1;
n->indirection = NULL;
$$ = (Node *)n;
}
| /*EMPTY*/ | /*EMPTY*/
{ $$ = NULL; } { $$ = NULL; }
; ;
attr: relation_name '.' attrs attr: relation_name '.' attrs opt_indirection
{ {
$$ = makeNode(Attr); $$ = makeNode(Attr);
$$->relname = $1; $$->relname = $1;
$$->paramNo = NULL; $$->paramNo = NULL;
$$->attrs = $3; $$->attrs = $3;
$$->indirection = NULL; $$->indirection = $4;
} }
| ParamNo '.' attrs | ParamNo '.' attrs opt_indirection
{ {
$$ = makeNode(Attr); $$ = makeNode(Attr);
$$->relname = NULL; $$->relname = NULL;
$$->paramNo = $1; $$->paramNo = $1;
$$->attrs = $3; $$->attrs = $3;
$$->indirection = NULL; $$->indirection = $4;
} }
; ;
...@@ -4896,66 +4750,16 @@ attrs: attr_name ...@@ -4896,66 +4750,16 @@ attrs: attr_name
* *
*****************************************************************************/ *****************************************************************************/
res_target_list: res_target_list ',' res_target_el /* Target lists as found in SELECT ... and INSERT VALUES ( ... ) */
{ $$ = lappend($1,$3); }
| res_target_el
{ $$ = lcons($1, NIL); }
| '*'
{
ResTarget *rt = makeNode(ResTarget);
Attr *att = makeNode(Attr);
att->relname = "*";
att->paramNo = NULL;
att->attrs = NULL;
att->indirection = NIL;
rt->name = NULL;
rt->indirection = NULL;
rt->val = (Node *)att;
$$ = lcons(rt, NIL);
}
;
res_target_el: ColId opt_indirection '=' a_expr_or_null
{
$$ = makeNode(ResTarget);
$$->name = $1;
$$->indirection = $2;
$$->val = (Node *)$4;
}
| attr opt_indirection
{
$$ = makeNode(ResTarget);
$$->name = NULL;
$$->indirection = $2;
$$->val = (Node *)$1;
}
| relation_name '.' '*'
{
Attr *att = makeNode(Attr);
att->relname = $1;
att->paramNo = NULL;
att->attrs = lcons(makeString("*"), NIL);
att->indirection = NIL;
$$ = makeNode(ResTarget);
$$->name = NULL;
$$->indirection = NULL;
$$->val = (Node *)att;
}
;
/* target_list: target_list ',' target_el
** target list for select.
** should get rid of the other but is still needed by the defunct select into
** and update (uses a subset)
*/
res_target_list2: res_target_list2 ',' res_target_el2
{ $$ = lappend($1, $3); } { $$ = lappend($1, $3); }
| res_target_el2 | target_el
{ $$ = lcons($1, NIL); } { $$ = lcons($1, NIL); }
; ;
/* AS is not optional because shift/red conflict with unary ops */ /* AS is not optional because shift/red conflict with unary ops */
res_target_el2: a_expr_or_null AS ColLabel target_el: a_expr_or_null AS ColLabel
{ {
$$ = makeNode(ResTarget); $$ = makeNode(ResTarget);
$$->name = $3; $$->name = $3;
...@@ -4995,10 +4799,29 @@ res_target_el2: a_expr_or_null AS ColLabel ...@@ -4995,10 +4799,29 @@ res_target_el2: a_expr_or_null AS ColLabel
} }
; ;
opt_id: ColId { $$ = $1; } /* Target list as found in UPDATE table SET ... */
| /*EMPTY*/ { $$ = NULL; }
update_target_list: update_target_list ',' update_target_el
{ $$ = lappend($1,$3); }
| update_target_el
{ $$ = lcons($1, NIL); }
;
update_target_el: ColId opt_indirection '=' a_expr_or_null
{
$$ = makeNode(ResTarget);
$$->name = $1;
$$->indirection = $2;
$$->val = (Node *)$4;
}
; ;
/*****************************************************************************
*
* Names and constants
*
*****************************************************************************/
relation_name: SpecialRuleRelation relation_name: SpecialRuleRelation
{ {
$$ = $1; $$ = $1;
...@@ -5056,7 +4879,10 @@ AexprConst: Iconst ...@@ -5056,7 +4879,10 @@ AexprConst: Iconst
n->val.val.str = $1; n->val.val.str = $1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| Typename Sconst /* this rule formerly used Typename, but that causes reduce conflicts
* with subscripted column names ...
*/
| SimpleTypename Sconst
{ {
A_Const *n = makeNode(A_Const); A_Const *n = makeNode(A_Const);
n->typename = $1; n->typename = $1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment