Node *n;
Type *t;
+ walkexpr(nt, Etype, &nt->ninit);
t = nt->type;
if(nt->op != OTYPE) {
yyerror("%S is not a type", nt->sym);
if(nn->op == OKEY)
nn = nn->left;
- if(nn->op == OTYPE && nn->sym == S) {
+ if(nn->sym == S) {
+ walkexpr(nn, Etype, &nn->ninit);
yyerror("cannot mix anonymous %T with named arguments", nn->type);
return xanondcl(nn);
}
t = types[TINT32];
if(nt == N)
yyerror("missing type for argument %S", nn->sym);
- else if(nt->op != OTYPE)
- yyerror("%S is not a type", nt->sym);
- else
- t = nt->type;
+ else {
+ walkexpr(nt, Etype, &nt->ninit);
+ if(nt->op != OTYPE)
+ yyerror("%S is not a type", nt->sym);
+ else
+ t = nt->type;
+ }
n = nod(ODCLFIELD, newname(nn->sym), N);
n->type = t;
return n;
* new_name_list (type | [type] = expr_list)
*/
NodeList*
-variter(NodeList *vl, Type *t, NodeList *el)
+variter(NodeList *vl, Node *nt, NodeList *el)
{
int doexpr;
Node *v, *e, *a;
Type *tv;
NodeList *r;
+ Type *t;
+
+ t = T;
+ if(nt) {
+ walkexpr(nt, Etype, &nt->ninit);
+ t = nt->type;
+ }
r = nil;
doexpr = el != nil;
/*
* Go language grammar.
*
- * The grammar has 6 reduce/reduce conflicts, caused by
- * input that can be parsed as either a type or an expression
- * depending on context, like the t in t(1). The expressions
- * have the more general syntax, so the grammar arranges
- * that such input gets parsed as expressions and then is
- * fixed up as a type later. In return for this extra work,
- * the lexer need not distinguish type names from variable names.
- *
* The Go semicolon rules are:
*
* 1. all statements and declarations are terminated by semicolons
%type <node> fndcl fnliteral
%type <node> for_body for_header for_stmt if_header if_stmt
%type <node> keyval labelname name
-%type <node> name_or_type
+%type <node> name_or_type non_expr_type
%type <node> new_name dcl_name oexpr
%type <node> onew_name
%type <node> osimple_stmt pexpr
%type <list> interfacedcl_list interfacedcl vardcl vardcl_list structdcl structdcl_list
%type <list> common_dcl constdcl constdcl1 constdcl_list typedcl_list
-%type <type> type
%type <node> convtype dotdotdot
-%type <node> indcl interfacetype structtype
+%type <node> indcl interfacetype structtype ptrtype
%type <type> new_type typedclname
%type <node> chantype non_chan_type othertype non_fn_type fntype fnlitdcl
%left ')'
%left PreferToRightParen
-%left NotDot
%left '.'
-%left NotBrace
%left '{'
%%
}
vardcl:
- dcl_name_list type varoptsemi
+ dcl_name_list ntype varoptsemi
{
$$ = variter($1, $2, nil);
}
-| dcl_name_list type varoptsemi '=' expr_list
+| dcl_name_list ntype varoptsemi '=' expr_list
{
$$ = variter($1, $2, $5);
}
| dcl_name_list '=' expr_list
{
- $$ = variter($1, T, $3);
+ $$ = variter($1, nil, $3);
}
constdcl:
}
typedcl:
- typedclname type
+ typedclname ntype
{
- updatetype($1, $2);
+ walkexpr($2, Etype, &$2->ninit);
+ updatetype($1, $2->type);
resumecheckwidth();
}
| typedclname LSTRUCT
}
case:
- LCASE expr_list ':'
+ LCASE expr_or_type_list ':'
{
int e;
Node *n;
}
break;
}
-| LCASE type ':'
- {
- Node *n;
-
- $$ = nod(OXCASE, N, N);
- poptodcl();
- if(typeswvar == N || typeswvar->right == N) {
- yyerror("type case not in a type switch");
- n = N;
- } else
- n = old2new(typeswvar->right, $2, &$$->ninit);
- $$->list = list1(nod(OTYPESW, n, N));
- }
| LCASE name '=' expr ':'
{
// will be converted to OCASE
{
$$ = nodlit($1);
}
-| name %prec NotBrace
+| name
| pexpr '.' sym
{
if($1->op == OPACK) {
expr_or_type:
expr
-| ntype %prec PreferToRightParen
+| non_expr_type %prec PreferToRightParen
name_or_type:
- dotname
-| type
- {
- $$ = typenod($1);
- }
+ ntype
lbrace:
LBODY
LNAME
name:
- sym %prec NotDot
+ sym
{
$$ = oldname($1);
}
$$ = typenod(typ(TDDD));
}
-type:
- ntype
+ntype:
+ chantype
+| fntype
+| othertype
+| ptrtype
+| dotname
+| '(' ntype ')'
{
- NodeList *init;
-
- init = nil;
- walkexpr($1, Etype, &init);
- // init can only be set if this was not a type; ignore
-
- $$ = $1->type;
+ $$ = $2;
}
-ntype:
+non_expr_type:
chantype
| fntype
| othertype
-| '(' ntype ')'
+| '*' non_expr_type
+ {
+ $$ = nod(OIND, $2, N);
+ }
+| '(' non_expr_type ')'
{
$$ = $2;
}
non_chan_type:
fntype
| othertype
+| ptrtype
+| dotname
| '(' ntype ')'
{
$$ = $2;
non_fn_type:
chantype
| othertype
+| ptrtype
+| dotname
dotname:
- name %prec NotDot
+ name
| name '.' sym
{
if($1->op == OPACK) {
}
othertype:
- '[' oexpr ']' type
+ '[' oexpr ']' ntype
{
- $$ = typenod(aindex($2, $4));
+ $$ = nod(OTARRAY, $2, $4);
}
| LCOMM LCHAN ntype
{
{
$$ = nod(OTMAP, $3, $5);
}
-| '*' ntype
+| structtype
+| interfacetype
+
+ptrtype:
+ '*' ntype
{
$$ = nod(OIND, $2, N);
}
-| structtype
-| interfacetype
-| dotname
chantype:
LCHAN ntype
fndcl:
dcl_name '(' oarg_type_list ')' fnres
{
+ Node *n;
+
b0stack = dclstack; // mark base for fn literals
$$ = nod(ODCLFUNC, N, N);
$$->nname = $1;
if($3 == nil && $5 == nil)
$$->nname = renameinit($1);
- $$->type = functype(N, $3, $5);
+ n = nod(OTFUNC, N, N);
+ n->list = $3;
+ n->rlist = $5;
+ walkexpr(n, Etype, &n->ninit);
+ $$->type = n->type;
funchdr($$);
}
| '(' oarg_type_list ')' new_name '(' oarg_type_list ')' fnres
}
| packname
{
- $$ = list1(nod(ODCLFIELD, N, typenod(oldtype($1))));
+ $$ = list1(nod(ODCLFIELD, N, oldname($1)));
}
indcl:
'(' oarg_type_list ')' fnres
{
// without func keyword
- $$ = typenod(functype(fakethis(), $2, $4));
+ $$ = nod(OTFUNC, fakethis(), N);
+ $$->list = $2;
+ $$->rlist = $4;
}
/*