gc: grammar cleanup:
  * no longer distinguishes const, var, type, package names.
  * all the predefined names are not tokens anymore.

R=ken
OCL=29326
CL=29985
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index cc9caf9..f774df2 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -2,6 +2,30 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+/*
+ * 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
+ *  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.
+ */
+
 %{
 #include "go.h"
 %}
@@ -12,106 +36,90 @@
 	struct	Val	val;
 	int		lint;
 }
-%token	<val>		LLITERAL
-%token	<lint>		LASOP
-%token	<sym>		LNAME LATYPE LPACK
-%token	<sym>		LPACKAGE LIMPORT LDEFER LCLOSE LCLOSED
-%token	<sym>		LMAP LCHAN LINTERFACE LFUNC LSTRUCT
-%token	<sym>		LCOLAS LFALL LRETURN LDDD
-%token	<sym>		LLEN LCAP LPANIC LPANICN LPRINT LPRINTN
-%token	<sym>		LVAR LTYPE LCONST LSELECT LMAKE LNEW
-%token	<sym>		LFOR LIF LELSE LSWITCH LCASE LDEFAULT
-%token	<sym>		LBREAK LCONTINUE LGO LGOTO LRANGE
-%token	<sym>		LNIL LTRUE LFALSE LIOTA
 
-%token			LOROR LANDAND LEQ LNE LLE LLT LGE LGT
-%token			LLSH LRSH LINC LDEC LCOMM LANDNOT
-%token			LIGNORE
+// |sed 's/.*	//' |9 fmt -l1 |sort |9 fmt -l50 | sed 's/^/%xxx		/'
+
+%token	<val>	LLITERAL
+%token	<lint>	LASOP
+%token	<sym>	LBREAK LCASE LCHAN LCOLAS LCONST LCONTINUE LDDD
+%token	<sym>	LDEFAULT LDEFER LELSE LFALL LFOR LFUNC LGO LGOTO
+%token	<sym>	LIF LIMPORT LINTERFACE LMAKE LMAP LNAME LNEW
+%token	<sym>	LPACKAGE LRANGE LRETURN LSELECT LSTRUCT LSWITCH
+%token	<sym>	LTYPE LVAR
+
+%token		LANDAND LANDNOT LBODY LCOMM LDEC LEQ LGE LGT
+%token		LIGNORE LINC LLE LLSH LLT LNE LOROR LRSH
+
+%type	<lint>	lbrace
+%type	<sym>	sym packname
+%type	<val>	oliteral
+
+%type	<node>	Acommon_dcl Aelse_stmt Afnres Astmt Astmt_list_r
+%type	<node>	Avardcl Bcommon_dcl Belse_stmt Bfnres Bstmt
+%type	<node>	Bstmt_list_r Bvardcl arg_type arg_type_list
+%type	<node>	arg_type_list_r braced_keyexpr_list case caseblock
+%type	<node>	caseblock_list_r common_dcl complex_stmt
+%type	<node>	compound_stmt dotname embed expr expr_list
+%type	<node>	expr_list_r expr_or_type expr_or_type_list
+%type	<node>	expr_or_type_list_r fnbody fndcl fnliteral fnres
+%type	<node>	for_body for_header for_stmt if_header if_stmt
+%type	<node>	interfacedcl interfacedcl1 interfacedcl_list_r
+%type	<node>	keyval keyval_list_r labelname loop_body name
+%type	<node>	name_list name_list_r name_or_type new_field
+%type	<node>	new_name oarg_type_list ocaseblock_list oexpr
+%type	<node>	oexpr_list oexpr_or_type_list onew_name
+%type	<node>	osimple_stmt ostmt_list oxdcl_list pexpr
+%type	<node>	pseudocall range_stmt select_stmt semi_stmt
+%type	<node>	simple_stmt stmt_list_r structdcl structdcl_list_r
+%type	<node>	switch_body switch_stmt uexpr vardcl vardcl_list_r
+%type	<node>	xdcl xdcl_list_r xfndcl
+
+%type	<type>	Achantype Afntype Anon_chan_type Anon_fn_type
+%type	<type>	Aothertype Atype Bchantype Bfntype Bnon_chan_type
+%type	<type>	Bnon_fn_type Bothertype Btype convtype dotdotdot
+%type	<type>	fnlitdcl fntype indcl interfacetype nametype
+%type	<type>	new_type structtype type typedclname
+
+%type	<sym>	hidden_importsym hidden_pkg_importsym
+
+%type	<node>	hidden_constant hidden_dcl hidden_funarg_list
+%type	<node>	hidden_funarg_list_r hidden_funres
+%type	<node>	hidden_interfacedcl hidden_interfacedcl_list
+%type	<node>	hidden_interfacedcl_list_r hidden_structdcl
+%type	<node>	hidden_structdcl_list hidden_structdcl_list_r
+%type	<node>	ohidden_funarg_list ohidden_funres
+%type	<node>	ohidden_interfacedcl_list ohidden_structdcl_list
+
+%type	<type>	hidden_type hidden_type1 hidden_type2
+
+%left		LOROR
+%left		LANDAND
+%left		LCOMM
+%left		LEQ LNE LLE LGE LLT LGT
+%left		'+' '-' '|' '^'
+%left		'*' '/' '%' '&' LLSH LRSH LANDNOT
 
 /*
- * 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.
+ * manual override of shift/reduce conflicts.
+ * the general form is that we assign a precedence
+ * to the token being shifted and then introduce
+ * NotToken with lower precedence or PreferToToken with higher
+ * and annotate the reducing rule accordingly.
  */
+%left		NotPackage
+%left		LPACKAGE
 
-%type	<sym>		sym sym1 sym2 sym3 keyword 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>		Aelse_stmt Belse_stmt
-%type	<node>		complex_stmt compound_stmt switch_body ocaseblock_list ostmt_list
-%type	<node>		caseblock_list_r stmt_list_r Astmt_list_r Bstmt_list_r
-%type	<node>		Astmt Bstmt
-%type	<node>		for_stmt for_body for_header
-%type	<node>		if_stmt if_header select_stmt switch_stmt condition case caseblock
-%type	<node>		simple_stmt osimple_stmt range_stmt semi_stmt
-%type	<node>		expr uexpr pexpr expr_list oexpr oexpr_list expr_list_r
-%type	<node>		exprsym3_list_r exprsym3 pseudocall
-%type	<node>		name labelname onew_name new_name new_name_list_r new_field
-%type	<node>		vardcl_list_r vardcl Avardcl Bvardcl
-%type	<node>		interfacedcl_list_r interfacedcl interfacedcl1
-%type	<node>		structdcl_list_r structdcl embed
-%type	<node>		fnres Afnres Bfnres fnliteral xfndcl fndcl fnbody
-%type	<node>		braced_keyexpr_list keyval_list_r keyval
+%left		NotParen
+%left		'('
 
-%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 dotdotdot
-%type	<val>		oliteral
+%left		')'
+%left		PreferToRightParen
 
-%type	<node>		hidden_constant
-%type	<node>		hidden_dcl hidden_structdcl
-%type	<type>		hidden_type hidden_type1 hidden_type2
-%type	<node>		hidden_structdcl_list ohidden_structdcl_list hidden_structdcl_list_r
-%type	<node>		hidden_interfacedcl_list ohidden_interfacedcl_list hidden_interfacedcl_list_r
-%type	<node>		hidden_interfacedcl
-%type	<node>		hidden_funarg_list ohidden_funarg_list hidden_funarg_list_r
-%type	<node>		hidden_funres ohidden_funres hidden_importsym hidden_pkg_importsym
+%left		NotDot
+%left		'.'
 
-%left			LOROR
-%left			LANDAND
-%left			LCOMM
-%left			LEQ LNE LLE LGE LLT LGT
-%left			'+' '-' '|' '^'
-%left			'*' '/' '%' '&' LLSH LRSH LANDNOT
-
-/*
- * resolve { vs condition in favor of condition
- */
-%left			'{'
-%left			Condition
-
-/*
- * resolve LPACKAGE vs not in favor of LPACKAGE
- */
-%left			NotPackage
-%left			LPACKAGE
-
-/*
- * resolve '.' vs not in favor of '.'
- */
-%left			NotDot
-%left			'.'
-
-/*
- * resolve '(' vs not in favor of '('
- */
-%left			NotParen
-%left			'('
+%left		NotBrace
+%left		'{'
 
 %%
 file:
@@ -230,17 +238,17 @@
 		if(my == import && strcmp(import->name, package) == 0)
 			break;
 
-		if(my->lexical != LNAME || my->oname != N || my->otype != T) {
+		if(my->def != N) {
 			// TODO(rsc): this line is only needed because of the
 			//	package net
 			//	import "net"
 			// convention; if we get rid of it, the check can go away
 			// and we can just always print the error
-			if(my->lexical != LPACK || strcmp(my->opack, import->name) != 0)
+			if(my->def->op != OPACK || strcmp(my->name, import->name) != 0)
 				yyerror("redeclaration of %S by import", my);
 		}
-		my->lexical = LPACK;
-		my->opack = import->name;
+		my->def = nod(OPACK, N, N);
+		my->def->sym = import;
 	}
 
 hidden_import_list:
@@ -343,9 +351,8 @@
 |	Bvardcl
 
 Avardcl:
-	new_name_list_r Atype
+	name_list Atype
 	{
-		$$ = rev($1);
 		dodclvar($$, $2);
 
 		if(funcdepth == 0) {
@@ -357,9 +364,8 @@
 	}
 
 Bvardcl:
-	new_name_list_r Btype
+	name_list Btype
 	{
-		$$ = rev($1);
 		dodclvar($$, $2);
 
 		if(funcdepth == 0) {
@@ -369,7 +375,7 @@
 			addtotop($$);
 		}
 	}
-|	new_name_list_r type '=' expr_list
+|	name_list type '=' expr_list
 	{
 		if(addtop != N)
 			fatal("new_name_list_r type '=' expr_list");
@@ -377,7 +383,7 @@
 		$$ = variter($1, $2, $4);
 		addtotop($$);
 	}
-|	new_name_list_r '=' expr_list
+|	name_list '=' expr_list
 	{
 		if(addtop != N)
 			fatal("new_name_list_r '=' expr_list");
@@ -387,22 +393,22 @@
 	}
 
 constdcl:
-	new_name_list_r type '=' expr_list
+	name_list type '=' expr_list
 	{
 		constiter($1, $2, $4);
 	}
-|	new_name_list_r '=' expr_list
+|	name_list '=' expr_list
 	{
 		constiter($1, T, $3);
 	}
 
 constdcl1:
 	constdcl
-|	new_name_list_r type
+|	name_list type
 	{
 		constiter($1, $2, N);
 	}
-|	new_name_list_r
+|	name_list
 	{
 		constiter($1, T, N);
 	}
@@ -464,41 +470,23 @@
 		$$ = nod(OASOP, $1, $3);
 		$$->etype = $2;			// rathole to pass opcode
 	}
-|	exprsym3_list_r '=' expr_list
+|	expr_list '=' expr_list
 	{
-		$$ = rev($1);
 		$$ = nod(OAS, $$, $3);
 	}
-|	exprsym3_list_r LCOLAS expr_list
+|	expr_list LCOLAS expr_list
 	{
 		if(addtop != N)
-			fatal("exprsym3_list_r LCOLAS expr_list");
+			fatal("expr_list LCOLAS expr_list");
 		if($3->op == OTYPESW) {
 			$$ = nod(OTYPESW, $1, $3->left);
 			break;
 		}
-		$$ = rev($1);
 		$$ = colas($$, $3);
 		$$ = nod(OAS, $$, $3);
 		$$->colas = 1;
 		addtotop($$);
 	}
-|	LPRINT '(' oexpr_list ')'
-	{
-		$$ = nod(OPRINT, $3, N);
-	}
-|	LPRINTN '(' oexpr_list ')'
-	{
-		$$ = nod(OPRINTN, $3, N);
-	}
-|	LPANIC '(' oexpr_list ')'
-	{
-		$$ = nod(OPANIC, $3, N);
-	}
-|	LPANICN '(' oexpr_list ')'
-	{
-		$$ = nod(OPANICN, $3, N);
-	}
 |	expr LINC
 	{
 		$$ = nod(OASOP, $1, nodintconst(1));
@@ -533,15 +521,36 @@
 		// right will point to next case
 		// done in casebody()
 		poptodcl();
-		if(typeswvar != N && typeswvar->right != N)
-		if($2->op == OLITERAL && $2->val.ctype == CTNIL) {
-			// this version in type switch case nil
-			$$ = nod(OTYPESW, N, N);
-			$$ = nod(OXCASE, $$, N);
-			break;
+		if(typeswvar != N && typeswvar->right != N) {
+			if($2->op == OLITERAL && $2->val.ctype == CTNIL) {
+				// this version in type switch case nil
+				$$ = nod(OTYPESW, N, N);
+				$$ = nod(OXCASE, $$, N);
+				break;
+			}
+			if($2->op == OTYPE) {
+				$$ = old2new(typeswvar->right, $2->type);
+				$$ = nod(OTYPESW, $$, N);
+				$$ = nod(OXCASE, $$, N);
+				addtotop($$);
+				break;
+			}
+			yyerror("non-type case in type switch");
 		}
 		$$ = nod(OXCASE, $2, N);
 	}
+|	LCASE type ':'
+	{
+		poptodcl();
+		if(typeswvar == N || typeswvar->right == N) {
+			yyerror("type case not in a type switch");
+			$$ = N;
+		} else
+			$$ = old2new(typeswvar->right, $2);
+		$$ = nod(OTYPESW, $$, N);
+		$$ = nod(OXCASE, $$, N);
+		addtotop($$);
+	}
 |	LCASE name '=' expr ':'
 	{
 		// will be converted to OCASE
@@ -561,18 +570,6 @@
 		$$ = nod(OXCASE, $$, N);
 		addtotop($$);
 	}
-|	LCASE type ':'
-	{
-		poptodcl();
-		if(typeswvar == N || typeswvar->right == N) {
-			yyerror("type case not in a type switch");
-			$$ = N;
-		} else
-			$$ = old2new(typeswvar->right, $2);
-		$$ = nod(OTYPESW, $$, N);
-		$$ = nod(OXCASE, $$, N);
-		addtotop($$);
-	}
 |	LDEFAULT ':'
 	{
 		poptodcl();
@@ -620,7 +617,8 @@
 	'{'
 	{
 		markdcl();
-	} ostmt_list '}'
+	}
+	ostmt_list '}'
 	{
 		$$ = $3;
 		if($$ == N)
@@ -629,7 +627,7 @@
 	}
 
 switch_body:
-	'{'
+	LBODY
 	{
 		markdcl();
 	}
@@ -655,13 +653,26 @@
 		$$ = nod(OLIST, $1, $2);
 	}
 
+loop_body:
+	LBODY
+	{
+		markdcl();
+	}
+	ostmt_list '}'
+	{
+		$$ = $3;
+		if($$ == N)
+			$$ = nod(OEMPTY, N, N);
+		popdcl();
+	}
+
 range_stmt:
-	exprsym3_list_r '=' LRANGE expr
+	expr_list '=' LRANGE expr
 	{
 		$$ = nod(ORANGE, $1, $4);
 		$$->etype = 0;	// := flag
 	}
-|	exprsym3_list_r LCOLAS LRANGE expr
+|	expr_list LCOLAS LRANGE expr
 	{
 		$$ = nod(ORANGE, $1, $4);
 		$$->etype = 1;
@@ -678,7 +689,7 @@
 		$$->ntest = $3;
 		$$->nincr = $5;
 	}
-|	condition
+|	osimple_stmt
 	{
 		// normal test
 		$$ = nod(OFOR, N, N);
@@ -693,7 +704,7 @@
 	}
 
 for_body:
-	for_header compound_stmt
+	for_header loop_body
 	{
 		$$ = $1;
 		$$->nbody = list($$->nbody, $2);
@@ -710,30 +721,15 @@
 		popdcl();
 	}
 
-/*
- * using cond instead of osimple_stmt creates
- * a shift/reduce conflict on an input like
- *
- *	if x == []int { true } { true }
- *
- * at the first {, giving us an opportunity
- * to resolve it by reduce, which implements
- * the rule about { } inside if conditions
- * needing parens.
- */
-condition:
-	osimple_stmt	%prec Condition
-
-
 if_header:
-	condition
+	osimple_stmt
 	{
 		// test
 		$$ = nod(OIF, N, N);
 		$$->ninit = N;
 		$$->ntest = $1;
 	}
-|	osimple_stmt ';' condition
+|	osimple_stmt ';' osimple_stmt
 	{
 		// init ; test
 		$$ = nod(OIF, N, N);
@@ -746,7 +742,7 @@
 	{
 		markdcl();
 	}
-	if_header compound_stmt
+	if_header loop_body
 	{
 		$$ = $3;
 		$$->nbody = $4;
@@ -878,6 +874,10 @@
 	pexpr
 |	'*' uexpr
 	{
+		if($2->op == OTYPE) {
+			$$ = typenod(ptrto($2->type));
+			break;
+		}
 		$$ = nod(OIND, $2, N);
 	}
 |	'&' uexpr
@@ -915,15 +915,26 @@
  * can be preceeded by 'defer' and 'go'
  */
 pseudocall:
-	pexpr '(' oexpr_list ')'
+	pexpr '(' oexpr_or_type_list ')'
 	{
 		$$ = unsafenmagic($1, $3);
-		if($$ == N)
-			$$ = nod(OCALL, $1, $3);
-	}
-|	LCLOSE '(' expr ')'
-	{
-		$$ = nod(OCLOSE, $3, N);
+		if($$)
+			break;
+		if($1->op == OTYPE) {
+			// type conversion
+			if($3 == N)
+				yyerror("conversion to %T missing expr", $1->type);
+			else if($3->op == OLIST)
+				yyerror("conversion to %T has too many exprs", $1->type);
+			$$ = nod(OCONV, $3, N);
+			$$->type = $1->type;
+			break;
+		}
+		if($1->op == ONAME && $1->etype != 0) {	// builtin OLEN, OCAP, etc
+			$$ = nod($1->etype, $3, N);
+			break;
+		}
+		$$ = nod(OCALL, $1, $3);
 	}
 
 pexpr:
@@ -931,39 +942,28 @@
 	{
 		$$ = nodlit($1);
 	}
-|	LNIL
+|	name	%prec NotBrace
+|	pexpr '.' sym
 	{
-		Val v;
-		v.ctype = CTNIL;
-		$$ = nodlit(v);
-	}
-|	LTRUE
-	{
-		$$ = nodbool(1);
-	}
-|	LFALSE
-	{
-		$$ = nodbool(0);
-	}
-|	LIOTA
-	{
-		$$ = nodintconst(iota);
-		$$->iota = 1;	// flag to reevaluate on copy
-	}
-|	name
-|	'(' expr ')'
-	{
-		$$ = $2;
-	}
-|	pexpr '.' sym2
-	{
+		if($1->op == OPACK) {
+			Sym *s;
+			s = pkglookup($3->name, $1->sym->name);
+			$$ = oldname(s);
+			break;
+		}
 		$$ = nod(ODOT, $1, newname($3));
 		$$ = adddot($$);
 	}
-|	pexpr '.' '(' type ')'
+|	'(' expr_or_type ')'
+	{
+		$$ = $2;
+	}
+|	pexpr '.' '(' expr_or_type ')'
 	{
 		$$ = nod(ODOTTYPE, $1, N);
-		$$->type = $4;
+		if($4->op != OTYPE)
+			yyerror("expected type got %O", $4->op);
+		$$->type = $4->type;
 	}
 |	pexpr '.' '(' LTYPE ')'
 	{
@@ -978,48 +978,13 @@
 		$$ = nod(OSLICE, $1, $3);
 	}
 |	pseudocall
-|	LLEN '(' expr ')'
-	{
-		$$ = nod(OLEN, $3, N);
-	}
-|	LCLOSED '(' expr ')'
-	{
-		$$ = nod(OCLOSED, $3, N);
-	}
-|	LCAP '(' expr ')'
-	{
-		$$ = nod(OCAP, $3, N);
-	}
-|	LNEW '(' type ')'
-	{
-		$$ = nod(ONEW, N, N);
-		$$->type = $3;
-	}
-|	LNEW '(' type ',' expr_list ')'
-	{
-		$$ = nod(ONEW, $5, N);
-		$$->type = $3;
-	}
-|	LMAKE '(' type ')'
-	{
-		$$ = nod(OMAKE, N, N);
-		$$->type = $3;
-	}
-|	LMAKE '(' type ',' expr_list ')'
-	{
-		$$ = nod(OMAKE, $5, N);
-		$$->type = $3;
-	}
 |	convtype '(' expr ')'
 	{
 		// conversion
-		$$ = rev($3);
-		if($$ == N)
-			$$ = nod(OEMPTY, N, N);
-		$$ = nod(OCONV, $$, N);
+		$$ = nod(OCONV, $3, N);
 		$$->type = $1;
 	}
-|	convtype '{' braced_keyexpr_list '}'
+|	convtype lbrace braced_keyexpr_list '}'
 	{
 		// composite expression
 		$$ = rev($3);
@@ -1027,44 +992,49 @@
 			$$ = nod(OEMPTY, N, N);
 		$$ = nod(OCOMPOS, $$, N);
 		$$->type = $1;
+
+		// If the opening brace was an LBODY,
+		// set up for another one now that we're done.
+		// See comment in lex.c about loophack.
+		if($2 == LBODY)
+			loophack = 1;
+	}
+|	pexpr '{' braced_keyexpr_list '}'
+	{
+		// composite expression
+		$$ = rev($3);
+		if($$ == N)
+			$$ = nod(OEMPTY, N, N);
+		$$ = nod(OCOMPOS, $$, N);
+		if($1->op != OTYPE)
+			yyerror("expected type in composite literal");
+		else
+			$$->type = $1->type;
 	}
 |	fnliteral
 
-/*
- * lexical symbols that can be
- * from other packages
- */
-lpack:
-	LPACK
+expr_or_type:
+	expr
+|	type	%prec PreferToRightParen
 	{
-		context = $1->opack;
-	}
-/*
- * adding this would enable gri's nested package idea
- *
-|	lpack '.' LPACK
-	{
-		context = $3->opack;
-	}
- */
-
-lname:
-	LNAME
-|	lpack '.' LNAME
-	{
-		$$ = $3;
-		context = nil;
+		$$ = typenod($1);
 	}
 
-latype:
-	LATYPE
-|	lpackatype
-
-lpackatype:
-	lpack '.' LATYPE
+name_or_type:
+	dotname
+|	type
 	{
-		$$ = $3;
-		context = nil;
+		$$ = typenod($1);
+	}
+
+lbrace:
+	LBODY
+	{
+		$$ = LBODY;
+	}
+|	'{'
+	{
+		$$ = '{';
 	}
 
 /*
@@ -1073,19 +1043,19 @@
  *	oldname is used after declared
  */
 new_name:
-	sym1
+	sym
 	{
 		$$ = newname($1);
 	}
 
 new_field:
-	sym2
+	sym
 	{
 		$$ = newname($1);
 	}
 
 new_type:
-	sym1
+	sym
 	{
 		$$ = newtype($1);
 	}
@@ -1097,84 +1067,19 @@
 |	new_name
 
 sym:
-	LATYPE
-|	LNAME
-|	LPACK
-
-sym1:
-	sym
-|	keyword
-
-/*
- * keywords that can be field names
- * pretty much any name can be allowed
- * limited only by good taste
- */
-sym2:
-	sym1
-
-/*
- * keywords that can be variables
- * but are not already legal expressions
- */
-sym3:
-	LLEN
-|	LCAP
-|	LCLOSE
-|	LCLOSED
-|	LPANIC
-|	LPANICN
-|	LPRINT
-|	LPRINTN
-|	LNEW
-|	LMAKE
-
-/*
- * keywords that we can
- * use as variable/type names
- */
-keyword:
-	sym3
-|	LNIL
-|	LTRUE
-|	LFALSE
-|	LIOTA
+	LNAME
 
 name:
-	lname
-	{
-		$$ = oldname($1);
-	}
-	/*
-	 * this rule introduces 1 reduce/reduce conflict
-	 * with the rule lpack: LPACK above.
-	 * the reduce/reduce conflict is only with
-	 * lookahead '.', in which case the correct
-	 * resolution is the lpack rule.  (and it wins
-	 * because it is above.)
-	 */
-|	LPACK	%prec NotDot
+	sym	%prec NotDot
 	{
 		$$ = oldname($1);
 	}
 
 labelname:
 	name
-|	LATYPE
-	{
-		$$ = oldname($1);
-	}
-|	keyword
-	{
-		$$ = oldname($1);
-	}
 
 convtype:
-	latype
-	{
-		$$ = oldtype($1);
-	}
-|	'[' oexpr ']' type
+	'[' oexpr ']' type
 	{
 		// array literal
 		$$ = aindex($2, $4);
@@ -1191,10 +1096,6 @@
 		$$ = maptype($3, $5);
 	}
 |	structtype
-|	'(' type ')'
-	{
-		$$ = $2;
-	}
 
 /*
  * to avoid parsing conflicts, type is split into
@@ -1227,12 +1128,6 @@
 		$$ = $2;
 	}
 
-non_name_type:
-	chantype
-|	fntype
-|	othertype
-|	dotdotdot
-
 dotdotdot:
 	LDDD
 	{
@@ -1262,17 +1157,28 @@
 |	Bothertype
 
 nametype:
-	LATYPE
+	dotname
 	{
-		if($1->otype != T && $1->otype->etype == TANY)
+		if($1->op == OTYPE)
+		if($1->type->etype == TANY)
 		if(strcmp(package, "PACKAGE") != 0)
 			yyerror("the any type is restricted");
-		$$ = oldtype($1);
+		$$ = oldtype($1->sym);
 	}
 
-othertype:
-	Aothertype
-|	Bothertype
+dotname:
+	name	%prec NotDot
+|	name '.' sym
+	{
+		if($1->op == OPACK) {
+			Sym *s;
+			s = pkglookup($3->name, $1->sym->name);
+			$$ = oldname(s);
+			break;
+		}
+		$$ = nod(ODOT, $1, newname($3));
+		$$ = adddot($$);
+	}
 
 Aothertype:
 	'[' oexpr ']' Atype
@@ -1303,11 +1209,7 @@
 |	interfacetype
 
 Bothertype:
-	lpackatype
-	{
-		$$ = oldtype($1);
-	}
-|	'[' oexpr ']' Btype
+	'[' oexpr ']' Btype
 	{
 		$$ = aindex($2, $4);
 	}
@@ -1332,10 +1234,6 @@
 		$$ = ptrto($2);
 	}
 
-chantype:
-	Achantype
-|	Bchantype
-
 Achantype:
 	LCHAN Atype
 	{
@@ -1378,10 +1276,6 @@
 	{
 		$$ = nod(OKEY, $1, $3);
 	}
-|	LATYPE ':' expr
-	{
-		$$ = nod(OKEY, newname($1), $3);
-	}
 
 
 /*
@@ -1574,16 +1468,25 @@
 		$$->val = $3;
 	}
 
+packname:
+	LNAME
+|	LNAME '.' sym
+	{
+		char *pkg;
+
+		if($1->def == N || $1->def->op != OPACK) {
+			yyerror("%S is not a package", $1);
+			pkg = $1->name;
+		} else
+			pkg = $1->def->sym->name;
+		$$ = pkglookup($3->name, pkg);
+	}
+
 embed:
-	LATYPE
+	packname
 	{
 		$$ = embedded($1);
 	}
-|	lpack '.' LATYPE
-	{
-		$$ = embedded($3);
-		context = nil;
-	}
 
 interfacedcl1:
 	new_name ',' interfacedcl1
@@ -1599,7 +1502,7 @@
 
 interfacedcl:
 	interfacedcl1
-|	latype
+|	packname
 	{
 		$$ = nod(ODCLFIELD, N, N);
 		$$->type = oldtype($1);
@@ -1614,65 +1517,44 @@
 
 /*
  * function arguments.
- *
- * the hard part is that when we're reading a list of names,
- * we don't know if they are going to be the names of
- * parameters (like "a,b,c int") or the types of anonymous
- * parameters (like "int, string, bool").
- *
- * an arg_chunk is a comma-separated list of arguments
- * that ends in an obvious type, either "a, b, c x" or "a, b, c, *x".
- * in the first case, a, b, c are parameters of type x.
- * in the second case, a, b, c, and *x are types of anonymous parameters.
  */
-arg_chunk:
-	new_name_list_r type
+arg_type:
+	name_or_type
+|	sym name_or_type
 	{
-		$$ = nametodcl($1, $2);
+		$$ = $1->def;
+		if($$ == N) {
+			$$ = nod(ONONAME, N, N);
+			$$->sym = $1;
+		}
+		$$ = nod(OKEY, $$, $2);
 	}
-|	new_name_list_r dotdotdot
+|	sym dotdotdot
 	{
-		$$ = nametodcl($1, $2);
+		$$ = $1->def;
+		if($$ == N) {
+			$$ = nod(ONONAME, N, N);
+			$$->sym = $1;
+		}
+		$$ = nod(OKEY, $$, typenod($2));
 	}
-|	non_name_type
+|	dotdotdot
 	{
-		$$ = anondcl($1);
-	}
-|	new_name_list_r ',' non_name_type
-	{
-		$1 = nametoanondcl($1);
-		$$ = appendr($1, anondcl($3));
+		$$ = typenod($1);
 	}
 
-arg_chunk_list_r:
-	arg_chunk
-|	arg_chunk_list_r ',' arg_chunk
-	{
-		$$ = appendr($1, $3);
-	}
-
-/*
- * an arg type list is a sequence of arg chunks,
- * possibly ending in a list of names (plain "a,b,c"),
- * which must be the types of anonymous parameters.
- */
 arg_type_list_r:
-	arg_chunk_list_r
-|	arg_chunk_list_r ',' new_name_list_r
+	arg_type
+|	arg_type_list_r ',' arg_type
 	{
-		$3 = nametoanondcl($3);
-		$$ = appendr($1, $3);
-	}
-|	new_name_list_r
-	{
-		$$ = nametoanondcl($1);
+		$$ = nod(OLIST, $1, $3);
 	}
 
 arg_type_list:
 	arg_type_list_r
 	{
 		$$ = rev($1);
-		checkarglist($$);
+		$$ = checkarglist($$);
 	}
 
 /*
@@ -1728,6 +1610,16 @@
 	Astmt_list_r
 |	Bstmt_list_r
 
+name_list_r:
+	name
+	{
+		$$ = newname($1->sym);
+	}
+|	name_list_r ',' name
+	{
+		$$ = nod(OLIST, $1, newname($3->sym));
+	}
+
 expr_list_r:
 	expr
 |	expr_list_r ',' expr
@@ -1735,27 +1627,9 @@
 		$$ = nod(OLIST, $1, $3);
 	}
 
-new_name_list_r:
-	new_name
-|	new_name_list_r ',' new_name
-	{
-		$$ = nod(OLIST, $1, $3);
-	}
-
-exprsym3:
-	expr
-|	sym3
-	{
-		$$ = newname($1);
-	}
-|	LATYPE
-	{
-		$$ = newname($1);
-	}
-
-exprsym3_list_r:
-	exprsym3
-|	exprsym3_list_r ',' exprsym3
+expr_or_type_list_r:
+	expr_or_type
+|	expr_or_type_list_r ',' expr_or_type
 	{
 		$$ = nod(OLIST, $1, $3);
 	}
@@ -1844,6 +1718,18 @@
 		$$ = rev($1);
 	}
 
+expr_or_type_list:
+	expr_or_type_list_r
+	{
+		$$ = rev($1);
+	}
+
+name_list:
+	name_list_r
+	{
+		$$ = rev($1);
+	}
+
 
 /*
  * optional things
@@ -1866,6 +1752,12 @@
 	}
 |	expr_list
 
+oexpr_or_type_list:
+	{
+		$$ = N;
+	}
+|	expr_or_type_list
+
 osimple_stmt:
 	{
 		$$ = N;
@@ -1934,7 +1826,7 @@
  * an output package
  */
 hidden_import:
-	LPACKAGE sym1
+	LPACKAGE sym
 	/* variables */
 |	LVAR hidden_pkg_importsym hidden_type
 	{
@@ -1956,7 +1848,7 @@
 	{
 		importvar($2, functype(N, $4, $6), PFUNC);
 	}
-|	LFUNC '(' hidden_funarg_list ')' sym1 '(' ohidden_funarg_list ')' ohidden_funres
+|	LFUNC '(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres
 	{
 		if($3->op != ODCLFIELD) {
 			yyerror("bad receiver in method");
@@ -1972,9 +1864,9 @@
 hidden_type1:
 	hidden_importsym
 	{
-		$$ = pkgtype($1->sym->name, $1->psym->name);
+		$$ = pkgtype($1);
 	}
-|	LATYPE
+|	LNAME
 	{
 		$$ = oldtype($1);
 	}
@@ -2034,7 +1926,7 @@
 	}
 
 hidden_dcl:
-	sym1 hidden_type
+	sym hidden_type
 	{
 		$$ = nod(ODCLFIELD, newname($1), N);
 		$$->type = $2;
@@ -2046,7 +1938,7 @@
 	}
 
 hidden_structdcl:
-	sym1 hidden_type oliteral
+	sym hidden_type oliteral
 	{
 		$$ = nod(ODCLFIELD, newname($1), N);
 		$$->type = $2;
@@ -2063,7 +1955,7 @@
 	}
 
 hidden_interfacedcl:
-	sym1 '(' ohidden_funarg_list ')' ohidden_funres
+	sym '(' ohidden_funarg_list ')' ohidden_funres
 	{
 		$$ = nod(ODCLFIELD, newname($1), N);
 		$$->type = functype(fakethis(), $3, $5);
@@ -2105,72 +1997,24 @@
 			yyerror("bad negated constant");
 		}
 	}
-|	LTRUE
+|	name
 	{
-		$$ = nodbool(1);
-	}
-|	LFALSE
-	{
-		$$ = nodbool(0);
+		$$ = $1;
+		if($$->op != OLITERAL)
+			yyerror("bad constant %S", $$->sym);
 	}
 
 hidden_importsym:
-	sym1 '.' sym2
+	sym '.' sym
 	{
-		$$ = nod(OIMPORT, N, N);
-		$$->psym = $1;
-		$$->sym = $3;
+		$$ = pkglookup($3->name, $1->name);
 	}
 
 hidden_pkg_importsym:
 	hidden_importsym
 	{
 		$$ = $1;
-		pkgcontext = $$->psym->name;
+		structpkg = $$->package;
 	}
 
 
-/*
- * helpful error messages.
- * THIS SECTION MUST BE AT THE END OF THE FILE.
- *
- * these rules trigger reduce/reduce conflicts in the grammar.
- * they are safe because reduce/reduce conflicts are resolved
- * in favor of rules appearing earlier in the grammar, and these
- * are at the end of the file.
- *
- * to check whether the rest of the grammar is free of
- * reduce/reduce conflicts, comment this section out by
- * removing the slash on the next line.
- *
- * there should be exactly 1 reduce/reduce conflict
- * when this block is commented out.
- */
-lpack:
-	LATYPE
-	{
-		yyerror("%s is type, not package", $1->name);
-		YYERROR;
-	}
-
-latype:
-	LPACK
-	{
-		yyerror("%s is package, not type", $1->name);
-		YYERROR;
-	}
-|	LNAME
-	{
-		yyerror("no type %s", $1->name);
-		YYERROR;
-	}
-
-nametype:
-	LNAME
-	{
-		yyerror("no type %s", $1->name);
-		YYERROR;
-	}
-
-/**/
-