%token LLSH LRSH LINC LDEC LCOMM
%token LIGNORE
+/*
+ * the go semicolon rules are:
+ *
+ * 1. all statements and declarations are terminated by semicolons
+ * 2. semicolons can be omitted at top level.
+ * 3. semicolons can be omitted before and after the closing ) or }
+ * on a list of statements or declarations.
+ *
+ * thus the grammar must distinguish productions that
+ * can omit the semicolon terminator and those that can't.
+ * names like Astmt, Avardcl, etc. can drop the semicolon.
+ * names like Bstmt, Bvardcl, etc. can't.
+ */
+
%type <sym> sym sym1 sym2 keyword laconst lname latype lpackatype
%type <node> xdcl xdcl_list_r oxdcl_list
%type <node> common_dcl Acommon_dcl Bcommon_dcl
%type <node> oarg_type_list arg_type_list_r arg_chunk arg_chunk_list_r arg_type_list
-%type <node> else_stmt1 else_stmt2 inc_stmt noninc_stmt
+%type <node> Aelse_stmt Belse_stmt
%type <node> complex_stmt compound_stmt ostmt_list
%type <node> stmt_list_r Astmt_list_r Bstmt_list_r
-%type <node> Astmt Bstmt Cstmt Dstmt
+%type <node> Astmt Bstmt
%type <node> for_stmt for_body for_header
%type <node> if_stmt if_body if_header
%type <node> range_header range_body range_stmt select_stmt
%type <node> structdcl_list_r structdcl
%type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl fnbody
%type <node> keyexpr_list keyval_list_r keyval
-%type <node> typedcl Atypedcl Btypedcl
-%type <type> typedclname
-%type <type> fntype fnlitdcl Afntype Bfntype fullAtype
-%type <type> non_name_Atype non_name_type
-%type <type> type Atype Btype indcl new_type fullBtype
-%type <type> structtype interfacetype convtype
-%type <type> Achantype Bchantype
+%type <type> typedclname new_type
+%type <type> type Atype Btype
+%type <type> othertype Aothertype Bothertype
+%type <type> chantype Achantype Bchantype
+%type <type> fntype Afntype Bfntype
+%type <type> nametype structtype interfacetype convtype
+%type <type> non_name_type Anon_fn_type Bnon_fn_type
+%type <type> Anon_chan_type Bnon_chan_type
+%type <type> indcl fnlitdcl
%type <val> hidden_constant
%type <node> hidden_dcl
| Bvardcl
Avardcl:
- new_name_list_r fullAtype
+ new_name_list_r Atype
{
$$ = rev($1);
dodclvar($$, $2);
}
Bvardcl:
- new_name_list_r fullBtype
+ new_name_list_r Btype
{
$$ = rev($1);
dodclvar($$, $2);
iota += 1;
}
-typedcl:
- Atypedcl
-| Btypedcl
-
typedclname:
new_type
{
defercheckwidth();
}
+typedcl:
+ Atypedcl
+| Btypedcl
+
Atypedcl:
- typedclname fullAtype
+ typedclname Atype
+ {
+ updatetype($1, $2);
+ resumecheckwidth();
+ }
+
+Btypedcl:
+ typedclname Btype
{
updatetype($1, $2);
resumecheckwidth();
updatetype($1, typ(TFORWSTRUCT));
resumecheckwidth();
}
-/*
| typedclname LINTERFACE
{
updatetype($1, typ(TFORWINTER));
resumecheckwidth();
}
-*/
-
-Btypedcl:
- typedclname fullBtype
- {
- updatetype($1, $2);
- resumecheckwidth();
- }
-else_stmt1:
+Aelse_stmt:
complex_stmt
| compound_stmt
-else_stmt2:
+Belse_stmt:
simple_stmt
| semi_stmt
| ';'
}
simple_stmt:
- inc_stmt
-| noninc_stmt
-
-noninc_stmt:
expr
{
$$ = $1;
{
$$ = nod(OPANICN, $3, N);
}
-
-inc_stmt:
- expr LINC
+| expr LINC
{
$$ = nod(OASOP, $1, literal(1));
$$->etype = OADD;
popdcl();
$$ = $2;
}
-| LIF if_stmt LELSE else_stmt1
+| LIF if_stmt LELSE Aelse_stmt
{
popdcl();
$$ = $2;
{
$$ = nod(ORETURN, $2, N);
}
-| LIF if_stmt LELSE else_stmt2
+| LIF if_stmt LELSE Belse_stmt
{
popdcl();
$$ = $2;
}
| structtype
+/*
+ * to avoid parsing conflicts, type is split into
+ * named types
+ * channel types
+ * function types
+ * any other type
+ *
+ * (and also into A/B as described above).
+ *
+ * the type system makes additional restrictions,
+ * but those are not implemented in the grammar.
+ */
type:
- fullAtype
-| fullBtype
+ Atype
+| Btype
-non_name_type:
- non_name_Atype
+Atype:
+ Achantype
| Afntype
-| Achantype
-| fullBtype
+| Aothertype
-Atype:
+Btype:
+ nametype
+| Bchantype
+| Bfntype
+| Bothertype
+
+non_name_type:
+ chantype
+| fntype
+| othertype
+
+Anon_chan_type:
+ Afntype
+| Aothertype
+
+Bnon_chan_type:
+ nametype
+| Bfntype
+| Bothertype
+
+Anon_fn_type:
+ Achantype
+| Aothertype
+
+Bnon_fn_type:
+ nametype
+| Bchantype
+| Bothertype
+
+
+nametype:
LATYPE
{
$$ = oldtype($1);
}
-| non_name_Atype
-non_name_Atype:
- lpackatype
- {
- $$ = oldtype($1);
- }
-| '[' oexpr ']' fullAtype
+othertype:
+ Aothertype
+| Bothertype
+
+Aothertype:
+ '[' oexpr ']' Atype
{
$$ = aindex($2, $4);
}
-| LCOMM LCHAN fullAtype
+| LCOMM LCHAN Atype
{
$$ = typ(TCHAN);
$$->type = $3;
$$->chan = Crecv;
}
-| LCHAN LCOMM Atype /* not full Atype */
+| LCHAN LCOMM Anon_chan_type
{
$$ = typ(TCHAN);
$$->type = $3;
$$->chan = Csend;
}
-| LMAP '[' type ']' fullAtype
+| LMAP '[' type ']' Atype
{
$$ = typ(TMAP);
$$->down = $3;
$$->type = $5;
}
-| structtype
-| interfacetype
-| '*' fullAtype
+| '*' Atype
{
$$ = ptrto($2);
}
+| structtype
+| interfacetype
-Achantype:
- LCHAN fullAtype
+Bothertype:
+ lpackatype
{
- $$ = typ(TCHAN);
- $$->type = $2;
- $$->chan = Cboth;
+ $$ = oldtype($1);
}
+| '*' lname /* TODO(rsc): yank */
+ {
+ Type *t;
-fullAtype:
- Atype
-| Afntype
-| Achantype
-
-Btype:
- '[' oexpr ']' fullBtype
+ t = dodcltype(newtype($2));
+ updatetype(t, typ(TFORWSTRUCT));
+ $$ = ptrto(t);
+ }
+| '[' oexpr ']' Btype
{
$$ = aindex($2, $4);
}
-| LCOMM LCHAN fullBtype
+| LCOMM LCHAN Btype
{
$$ = typ(TCHAN);
$$->type = $3;
$$->chan = Crecv;
}
-| LCHAN LCOMM Btype // not full Btype
+| LCHAN LCOMM Bnon_chan_type
{
$$ = typ(TCHAN);
$$->type = $3;
$$->chan = Csend;
}
-| LMAP '[' type ']' fullBtype
+| LMAP '[' type ']' Btype
{
$$ = typ(TMAP);
$$->down = $3;
$$->type = $5;
}
-| '*' fullBtype
+| '*' Btype
{
$$ = ptrto($2);
}
-| '*' lname
- {
- Type *t;
- t = dodcltype(newtype($2));
- updatetype(t, typ(TFORWSTRUCT));
- $$ = ptrto(t);
+chantype:
+ Achantype
+| Bchantype
+
+Achantype:
+ LCHAN Atype
+ {
+ $$ = typ(TCHAN);
+ $$->type = $2;
+ $$->chan = Cboth;
}
Bchantype:
- LCHAN fullBtype
+ LCHAN Btype
{
$$ = typ(TCHAN);
$$->type = $2;
$$->chan = Cboth;
}
-fullBtype:
- Btype
-| Bfntype
-| Bchantype
-
structtype:
LSTRUCT '{' structdcl_list_r osemi '}'
{
| Bfnres
Afnres:
- Atype
+ Anon_fn_type
{
$$ = nod(ODCLFIELD, N, N);
$$->type = $1;
$$ = cleanidlist($$);
}
-| '(' oarg_type_list ')'
- {
- $$ = $2;
- }
Bfnres:
{
$$ = N;
}
-| Btype
+| Bnon_fn_type
{
$$ = nod(ODCLFIELD, N, N);
$$->type = $1;
$$ = cleanidlist($$);
}
+| '(' oarg_type_list ')'
+ {
+ $$ = $2;
+ }
/*
* lists of things
}
/*
- * need semi in front NO
- * need semi in back NO
+ * statement that doesn't need semicolon terminator
*/
Astmt:
complex_stmt
{
$$ = N;
}
+| new_name ':'
+ {
+ $$ = nod(OLABEL, $1, N);
+ }
+| Bstmt ';'
/*
- * need semi in front NO
- * need semi in back YES
+ * statement that does
*/
Bstmt:
semi_stmt
| Bcommon_dcl
-| error Bstmt
- {
- $$ = N;
- }
-
-/*
- * need semi in front YES
- * need semi in back YES
- */
-Cstmt:
- noninc_stmt
-
-/*
- * need semi in front YES
- * need semi in back NO
- */
-Dstmt:
- inc_stmt
-| new_name ':'
- {
- $$ = nod(OLABEL, $1, N);
- }
+| simple_stmt
/*
- * statement list that ends AorD
+ * statement list that doesn't need semicolon terminator
*/
Astmt_list_r:
Astmt
-| Dstmt
| Astmt_list_r Astmt
{
$$ = list($1, $2);
}
-| Astmt_list_r Dstmt
- {
- $$ = list($1, $2);
- }
-| Bstmt_list_r Astmt
- {
- $$ = list($1, $2);
- }
/*
- * statement list that ends BorC
+ * statement list that needs semicolon terminator
*/
Bstmt_list_r:
Bstmt
-| Cstmt
| Astmt_list_r Bstmt
{
$$ = list($1, $2);
}
-| Astmt_list_r Cstmt
- {
- $$ = list($1, $2);
- }
-| Bstmt_list_r Bstmt
- {
- $$ = list($1, $2);
- }
stmt_list_r:
Astmt_list_r