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.
This commit is contained in:
parent
bc9236bc01
commit
f9e2c7fae8
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*
|
||||
* 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
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
|
@ -169,8 +169,8 @@ Oid param_type(int t); /* used in parse_expr.c */
|
|||
oper_argtypes, RuleActionList, RuleActionBlock, RuleActionMulti,
|
||||
opt_column_list, columnList, opt_va_list, va_list,
|
||||
sort_clause, sortby_list, index_params, index_list, name_list,
|
||||
from_clause, from_expr, table_list, opt_array_bounds, nest_array_bounds,
|
||||
expr_list, attrs, res_target_list, res_target_list2,
|
||||
from_clause, from_expr, table_list, opt_array_bounds,
|
||||
expr_list, attrs, target_list, update_target_list,
|
||||
def_list, opt_indirection, group_clause, TriggerFuncArgs,
|
||||
opt_select_limit
|
||||
|
||||
|
@ -189,7 +189,6 @@ Oid param_type(int t); /* used in parse_expr.c */
|
|||
%type <str> join_outer
|
||||
%type <ival> join_type
|
||||
|
||||
%type <node> position_expr
|
||||
%type <list> extract_list, position_list
|
||||
%type <list> substr_list, substr_from, substr_for, trim_list
|
||||
%type <list> opt_interval
|
||||
|
@ -232,10 +231,11 @@ Oid param_type(int t); /* used in parse_expr.c */
|
|||
%type <ielem> index_elem, func_index
|
||||
%type <range> table_expr
|
||||
%type <relexp> relation_expr
|
||||
%type <target> res_target_el, res_target_el2
|
||||
%type <target> target_el, update_target_el
|
||||
%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> extract_arg
|
||||
%type <str> opt_charset, opt_collate
|
||||
|
@ -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
|
|||
}
|
||||
;
|
||||
|
||||
insert_rest: VALUES '(' res_target_list2 ')'
|
||||
insert_rest: VALUES '(' target_list ')'
|
||||
{
|
||||
$$ = makeNode(InsertStmt);
|
||||
$$->cols = NULL;
|
||||
|
@ -2519,7 +2523,7 @@ insert_rest: VALUES '(' res_target_list2 ')'
|
|||
$$->intersectClause = n->intersectClause;
|
||||
$$->forUpdate = n->forUpdate;
|
||||
}
|
||||
| '(' columnList ')' VALUES '(' res_target_list2 ')'
|
||||
| '(' columnList ')' VALUES '(' target_list ')'
|
||||
{
|
||||
$$ = makeNode(InsertStmt);
|
||||
$$->cols = $2;
|
||||
|
@ -2621,7 +2625,7 @@ opt_lmode: SHARE { $$ = TRUE; }
|
|||
*****************************************************************************/
|
||||
|
||||
UpdateStmt: UPDATE relation_name
|
||||
SET res_target_list
|
||||
SET update_target_list
|
||||
from_clause
|
||||
where_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
|
||||
group_clause having_clause
|
||||
{
|
||||
|
@ -3183,17 +3187,9 @@ relation_expr: relation_name
|
|||
$$->inh = TRUE;
|
||||
}
|
||||
|
||||
opt_array_bounds: '[' ']' nest_array_bounds
|
||||
opt_array_bounds: '[' ']' opt_array_bounds
|
||||
{ $$ = lcons(makeInteger(-1), $3); }
|
||||
| '[' Iconst ']' nest_array_bounds
|
||||
{ $$ = lcons(makeInteger($2), $4); }
|
||||
| /*EMPTY*/
|
||||
{ $$ = NIL; }
|
||||
;
|
||||
|
||||
nest_array_bounds: '[' ']' nest_array_bounds
|
||||
{ $$ = lcons(makeInteger(-1), $3); }
|
||||
| '[' Iconst ']' nest_array_bounds
|
||||
| '[' Iconst ']' opt_array_bounds
|
||||
{ $$ = lcons(makeInteger($2), $4); }
|
||||
| /*EMPTY*/
|
||||
{ $$ = NIL; }
|
||||
|
@ -3210,7 +3206,7 @@ nest_array_bounds: '[' ']' nest_array_bounds
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
Typename: Array opt_array_bounds
|
||||
Typename: SimpleTypename opt_array_bounds
|
||||
{
|
||||
$$ = $1;
|
||||
$$->arrayBounds = $2;
|
||||
|
@ -3232,17 +3228,17 @@ Typename: Array opt_array_bounds
|
|||
else
|
||||
$$->setof = FALSE;
|
||||
}
|
||||
| SETOF Array
|
||||
| SETOF SimpleTypename
|
||||
{
|
||||
$$ = $2;
|
||||
$$->setof = TRUE;
|
||||
}
|
||||
;
|
||||
|
||||
Array: Generic
|
||||
| Datetime
|
||||
SimpleTypename: Generic
|
||||
| Numeric
|
||||
| Character
|
||||
| Datetime
|
||||
;
|
||||
|
||||
Generic: generic
|
||||
|
@ -3254,7 +3250,7 @@ Generic: generic
|
|||
;
|
||||
|
||||
generic: IDENT { $$ = $1; }
|
||||
| TYPE_P { $$ = xlateSqlType("type"); }
|
||||
| TYPE_P { $$ = "type"; }
|
||||
;
|
||||
|
||||
/* SQL92 numeric data types
|
||||
|
@ -3615,21 +3611,18 @@ sub_type: ANY { $$ = ANY_SUBLINK; }
|
|||
* All operations/expressions are allowed in a BETWEEN clause
|
||||
* if surrounded by parens.
|
||||
*/
|
||||
a_expr: attr opt_indirection
|
||||
{
|
||||
$1->indirection = $2;
|
||||
$$ = (Node *)$1;
|
||||
}
|
||||
a_expr: attr
|
||||
{ $$ = (Node *) $1; }
|
||||
| row_expr
|
||||
{ $$ = $1; }
|
||||
| AexprConst
|
||||
{ $$ = $1; }
|
||||
| ColId
|
||||
| ColId opt_indirection
|
||||
{
|
||||
/* could be a column name or a relation_name */
|
||||
Ident *n = makeNode(Ident);
|
||||
n->name = $1;
|
||||
n->indirection = NULL;
|
||||
n->indirection = $2;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| '-' a_expr %prec UMINUS
|
||||
|
@ -3679,7 +3672,7 @@ a_expr: attr opt_indirection
|
|||
/* 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) {
|
||||
} else if (nodeTag($1) == T_ParamNo) {
|
||||
((ParamNo *)$1)->typename = $3;
|
||||
/* otherwise, try to transform to a function call */
|
||||
} else {
|
||||
|
@ -3695,7 +3688,7 @@ a_expr: attr opt_indirection
|
|||
/* AexprConst can be either A_Const or ParamNo */
|
||||
if (nodeTag($3) == T_A_Const) {
|
||||
((A_Const *)$3)->typename = $5;
|
||||
} else if (nodeTag($5) == T_Param) {
|
||||
} else if (nodeTag($3) == T_ParamNo) {
|
||||
((ParamNo *)$3)->typename = $5;
|
||||
/* otherwise, try to transform to a function call */
|
||||
} else {
|
||||
|
@ -4282,21 +4275,19 @@ a_expr: attr opt_indirection
|
|||
/* Restricted expressions
|
||||
* b_expr is a subset of the complete expression syntax
|
||||
* 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
|
||||
{
|
||||
$1->indirection = $2;
|
||||
$$ = (Node *)$1;
|
||||
}
|
||||
b_expr: attr
|
||||
{ $$ = (Node *) $1; }
|
||||
| AexprConst
|
||||
{ $$ = $1; }
|
||||
| ColId
|
||||
| ColId opt_indirection
|
||||
{
|
||||
/* could be a column name or a relation_name */
|
||||
Ident *n = makeNode(Ident);
|
||||
n->name = $1;
|
||||
n->indirection = NULL;
|
||||
n->indirection = $2;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| '-' b_expr %prec UMINUS
|
||||
|
@ -4317,10 +4308,10 @@ b_expr: attr opt_indirection
|
|||
{ $$ = makeA_Expr(OP, "/", $1, $3); }
|
||||
| b_expr '%' b_expr
|
||||
{ $$ = makeA_Expr(OP, "%", $1, $3); }
|
||||
| b_expr '^' b_expr
|
||||
{ $$ = makeA_Expr(OP, "^", $1, $3); }
|
||||
| b_expr '*' b_expr
|
||||
{ $$ = makeA_Expr(OP, "*", $1, $3); }
|
||||
| b_expr '^' b_expr
|
||||
{ $$ = makeA_Expr(OP, "^", $1, $3); }
|
||||
| ':' b_expr
|
||||
{ $$ = makeA_Expr(OP, ":", NULL, $2); }
|
||||
| ';' b_expr
|
||||
|
@ -4333,7 +4324,7 @@ b_expr: attr opt_indirection
|
|||
/* 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) {
|
||||
} else if (nodeTag($1) == T_ParamNo) {
|
||||
((ParamNo *)$1)->typename = $3;
|
||||
/* otherwise, try to transform to a function call */
|
||||
} else {
|
||||
|
@ -4349,7 +4340,7 @@ b_expr: attr opt_indirection
|
|||
/* 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) {
|
||||
} else if (nodeTag($3) == T_ParamNo) {
|
||||
((ParamNo *)$3)->typename = $5;
|
||||
/* otherwise, try to transform to a function call */
|
||||
} else {
|
||||
|
@ -4571,140 +4562,14 @@ extract_arg: datetime { $$ = $1; }
|
|||
| 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); }
|
||||
| /*EMPTY*/
|
||||
{ $$ = 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
|
||||
{
|
||||
$$ = nconc(nconc($1,$2),$3);
|
||||
|
@ -4846,38 +4711,27 @@ case_default: ELSE a_expr_or_null { $$ = $2; }
|
|||
| /*EMPTY*/ { $$ = NULL; }
|
||||
;
|
||||
|
||||
case_arg: attr opt_indirection
|
||||
{
|
||||
$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;
|
||||
}
|
||||
case_arg: a_expr
|
||||
{ $$ = $1; }
|
||||
| /*EMPTY*/
|
||||
{ $$ = NULL; }
|
||||
;
|
||||
|
||||
attr: relation_name '.' attrs
|
||||
attr: relation_name '.' attrs opt_indirection
|
||||
{
|
||||
$$ = makeNode(Attr);
|
||||
$$->relname = $1;
|
||||
$$->paramNo = NULL;
|
||||
$$->attrs = $3;
|
||||
$$->indirection = NULL;
|
||||
$$->indirection = $4;
|
||||
}
|
||||
| ParamNo '.' attrs
|
||||
| ParamNo '.' attrs opt_indirection
|
||||
{
|
||||
$$ = makeNode(Attr);
|
||||
$$->relname = NULL;
|
||||
$$->paramNo = $1;
|
||||
$$->attrs = $3;
|
||||
$$->indirection = NULL;
|
||||
$$->indirection = $4;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -4896,66 +4750,16 @@ attrs: attr_name
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
res_target_list: res_target_list ',' res_target_el
|
||||
{ $$ = 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);
|
||||
}
|
||||
;
|
||||
/* Target lists as found in SELECT ... and INSERT VALUES ( ... ) */
|
||||
|
||||
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 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
|
||||
target_list: target_list ',' target_el
|
||||
{ $$ = lappend($1, $3); }
|
||||
| res_target_el2
|
||||
| target_el
|
||||
{ $$ = lcons($1, NIL); }
|
||||
;
|
||||
|
||||
/* 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);
|
||||
$$->name = $3;
|
||||
|
@ -4995,10 +4799,29 @@ res_target_el2: a_expr_or_null AS ColLabel
|
|||
}
|
||||
;
|
||||
|
||||
opt_id: ColId { $$ = $1; }
|
||||
| /*EMPTY*/ { $$ = NULL; }
|
||||
/* Target list as found in UPDATE table SET ... */
|
||||
|
||||
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
|
||||
{
|
||||
$$ = $1;
|
||||
|
@ -5056,7 +4879,10 @@ AexprConst: Iconst
|
|||
n->val.val.str = $1;
|
||||
$$ = (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);
|
||||
n->typename = $1;
|
||||
|
|
Loading…
Reference in New Issue