- allow reserved words as field and method names

R=r
OCL=14102
CL=14102
diff --git a/usr/gri/gosrc/base.go b/usr/gri/gosrc/base.go
index e7a14c8..456f354 100755
--- a/usr/gri/gosrc/base.go
+++ b/usr/gri/gosrc/base.go
@@ -13,5 +13,12 @@
 export type Node struct {
   left, right *Node;
   val bool;
-  f Foo
+  f Foo;
+  const, type, var, package int;
+}
+
+export func (p *Node) case(x int) {};
+
+export type I interface {
+  func();
 }
diff --git a/usr/gri/gosrc/export.go b/usr/gri/gosrc/export.go
index dced015..cfca1a9 100755
--- a/usr/gri/gosrc/export.go
+++ b/usr/gri/gosrc/export.go
@@ -231,7 +231,7 @@
 	case Object.CONST:
 		E.WriteInt(0);  // should be the correct value
 
-	case Object.VAR:
+	case Object.VAR, Object.FIELD:
 		E.WriteInt(0);  // should be the correct address/offset
 		
 	case Object.FUNC:
diff --git a/usr/gri/gosrc/import.go b/usr/gri/gosrc/import.go
index 4ce3703..2be6e06 100755
--- a/usr/gri/gosrc/import.go
+++ b/usr/gri/gosrc/import.go
@@ -260,7 +260,7 @@
 	case Object.CONST:
 		I.ReadInt();  // should set the value field
 
-	case Object.VAR:
+	case Object.VAR, Object.FIELD:
 		I.ReadInt();  // should set the address/offset field
 
 	case Object.FUNC:
diff --git a/usr/gri/gosrc/object.go b/usr/gri/gosrc/object.go
index 5bd2a6b..81fab9a 100755
--- a/usr/gri/gosrc/object.go
+++ b/usr/gri/gosrc/object.go
@@ -9,7 +9,7 @@
 
 export const /* kind */ (
 	BAD = iota;  // error handling
-	CONST; TYPE; VAR; FUNC; PACKAGE; LABEL;
+	CONST; TYPE; VAR; FIELD; FUNC; PACKAGE; LABEL;
 	END;  // end of scope (import/export only)
 )
 
@@ -25,6 +25,7 @@
 	case CONST: return "CONST";
 	case TYPE: return "TYPE";
 	case VAR: return "VAR";
+	case FIELD: return "FIELD";
 	case FUNC: return "FUNC";
 	case PACKAGE: return "PACKAGE";
 	case LABEL: return "LABEL";
diff --git a/usr/gri/gosrc/parser.go b/usr/gri/gosrc/parser.go
index 2ca3a0f..01bb8c7 100644
--- a/usr/gri/gosrc/parser.go
+++ b/usr/gri/gosrc/parser.go
@@ -246,12 +246,13 @@
 func (P *Parser) ParseDeclaration();
 
 
-func (P *Parser) ParseIdent() (pos int, ident string) {
+func (P *Parser) ParseIdent(allow_keyword bool) (pos int, ident string) {
 	P.Trace("Ident");
 
-	pos = P.pos;
-	ident = "";
-	if P.tok == Scanner.IDENT {
+	pos, ident = P.pos, "";
+	// NOTE Can make this faster by not doing the keyword lookup in the
+	// scanner if we don't care about keywords.
+	if P.tok == Scanner.IDENT || allow_keyword && P.tok > Scanner.IDENT {
 		ident = P.val;
 		if P.verbose {
 			P.PrintIndent();
@@ -270,7 +271,7 @@
 func (P *Parser) ParseIdentDecl(kind int) *Globals.Object {
 	P.Trace("IdentDecl");
 	
-	pos, ident := P.ParseIdent();
+	pos, ident := P.ParseIdent(kind == Object.FIELD);
 	obj := Globals.NewObject(pos, kind, ident);
 	P.Declare(obj);
 	
@@ -296,10 +297,10 @@
 
 func (P *Parser) ParseIdentList() {
 	P.Trace("IdentList");
-	P.ParseIdent();
+	P.ParseIdent(false);
 	for P.tok == Scanner.COMMA {
 		P.Next();
-		P.ParseIdent();
+		P.ParseIdent(false);
 	}
 	P.Ecart();
 }
@@ -309,7 +310,7 @@
 	P.Trace("QualifiedIdent");
 
 	if pos < 0 {
-		pos, ident = P.ParseIdent();
+		pos, ident = P.ParseIdent(false);
 	}
 	
 	if P.semantic_checks {
@@ -328,7 +329,7 @@
 			//	panic "pkg.obj.ident != ident";
 			//}
 			P.Next();  // consume "."
-			pos, ident = P.ParseIdent();
+			pos, ident = P.ParseIdent(false);
 			obj = pkg.scope.Lookup(ident);
 			if obj == nil {
 				P.Error(pos, `"` + ident + `" is not declared in package "` + pkg.obj.ident + `"`);
@@ -342,7 +343,7 @@
 	} else {
 		if P.tok == Scanner.PERIOD {
 			P.Next();
-			P.ParseIdent();
+			P.ParseIdent(false);
 		}
 		P.Ecart();
 		return nil;
@@ -453,10 +454,10 @@
 }
 
 
-func (P *Parser) ParseVarDeclList() {
+func (P *Parser) ParseVarDeclList(kind int) {
 	P.Trace("VarDeclList");
 	
-	list := P.ParseIdentDeclList(Object.VAR);
+	list := P.ParseIdentDeclList(kind);
 	typ := P.ParseVarType();
 	for p := list.first; p != nil; p = p.next {
 		p.obj.typ = typ;  // TODO should use/have set_type()
@@ -466,20 +467,13 @@
 }
 
 
-func (P *Parser) ParseParameterSection() {
-	P.Trace("ParameterSection");
-	P.ParseVarDeclList();
-	P.Ecart();
-}
-
-
 func (P *Parser) ParseParameterList() {
 	P.Trace("ParameterList");
 	
-	P.ParseParameterSection();
+	P.ParseVarDeclList(Object.VAR);
 	for P.tok == Scanner.COMMA {
 		P.Next();
-		P.ParseParameterSection();
+		P.ParseVarDeclList(Object.VAR);
 	}
 	
 	P.Ecart();
@@ -586,7 +580,7 @@
 		}
 	}
 	
-	pos, ident = P.ParseIdent();
+	pos, ident = P.ParseIdent(true);
 
 	P.ParseParameters();
 	
@@ -614,7 +608,7 @@
 func (P *Parser) ParseMethodDecl(recv_typ *Globals.Type) {
 	P.Trace("MethodDecl");
 	
-	pos, ident := P.ParseIdent();
+	pos, ident := P.ParseIdent(true);
 	P.OpenScope();
 	P.level--;
 	sig := P.top_scope;
@@ -649,7 +643,7 @@
 	P.level--;
 	typ := Globals.NewType(Type.INTERFACE);
 	typ.scope = P.top_scope;
-	for P.tok == Scanner.IDENT {
+	for P.tok >= Scanner.IDENT {
 		P.ParseMethodDecl(typ);
 	}
 	P.level++;
@@ -676,13 +670,6 @@
 }
 
 
-func (P *Parser) ParseFieldDecl() {
-	P.Trace("FieldDecl");
-	P.ParseVarDeclList();
-	P.Ecart();
-}
-
-
 func (P *Parser) ParseStructType() *Globals.Type {
 	P.Trace("StructType");
 	
@@ -692,8 +679,8 @@
 	P.level--;
 	typ := Globals.NewType(Type.STRUCT);
 	typ.scope = P.top_scope;
-	for P.tok == Scanner.IDENT {
-		P.ParseFieldDecl();
+	for P.tok >= Scanner.IDENT {
+		P.ParseVarDeclList(Object.FIELD);
 		if P.tok != Scanner.RBRACE {
 			P.Expect(Scanner.SEMICOLON);
 		}
@@ -738,7 +725,7 @@
 			
 			P.Next();  // consume package name
 			P.Expect(Scanner.PERIOD);
-			pos, ident := P.ParseIdent();
+			pos, ident := P.ParseIdent(false);
 			obj := pkg.scope.Lookup(ident);
 			if obj == nil {
 				elt = Globals.NewType(Type.FORWARD);
@@ -760,7 +747,7 @@
 			if P.Lookup(P.val) == nil {
 				// implicit type forward declaration
 				// create a named forward type 
-				pos, ident := P.ParseIdent();
+				pos, ident := P.ParseIdent(false);
 				obj := Globals.NewObject(pos, Object.TYPE, ident);
 				elt = Globals.NewType(Type.FORWARD);
 				obj.typ = elt;
@@ -1110,8 +1097,8 @@
 	period_pos := P.pos;
 	P.Expect(Scanner.PERIOD);
 	
-	if P.tok == Scanner.IDENT {
-		ident_pos, ident := P.ParseIdent();
+	if P.tok >= Scanner.IDENT {
+		ident_pos, ident := P.ParseIdent(true);
 		
 		if P.semantic_checks {
 			switch typ := x.typ(); typ.form {
@@ -1519,7 +1506,7 @@
 	
 	P.Expect(tok);
 	if P.tok == Scanner.IDENT {
-		P.ParseIdent();
+		P.ParseIdent(false);
 	}
 	
 	P.Ecart();
@@ -1659,7 +1646,7 @@
 	} else {
 		// receive
 		if P.tok != Scanner.LSS {
-			P.ParseIdent();
+			P.ParseIdent(false);
 			P.Expect(Scanner.ASSIGN);
 		}
 		P.Expect(Scanner.LSS);
@@ -1831,7 +1818,7 @@
 
 	var typ *Globals.Type;
 	
-	pos, ident := P.ParseIdent();
+	pos, ident := P.ParseIdent(false);
 	obj := P.Lookup(ident);
 	
 	if !P.comp.flags.sixg && obj != nil {
@@ -1990,7 +1977,7 @@
 		has_paren = true;
 	}
 	for P.tok == Scanner.IDENT {
-		pos, ident := P.ParseIdent();
+		pos, ident := P.ParseIdent(false);
 		P.exports.AddStr(ident);
 		P.Optional(Scanner.COMMA);  // TODO this seems wrong
 	}
diff --git a/usr/gri/gosrc/printer.go b/usr/gri/gosrc/printer.go
index 3269fe2..c053cae 100755
--- a/usr/gri/gosrc/printer.go
+++ b/usr/gri/gosrc/printer.go
@@ -149,7 +149,7 @@
 		print " ";
 		P.PrintTypeStruct(obj.typ);
 
-	case Object.VAR:
+	case Object.VAR, Object.FIELD:
 		if P.level == 0 {
 			print "var ";
 		}
diff --git a/usr/gri/gosrc/scanner.go b/usr/gri/gosrc/scanner.go
index 9598180..5ff6910 100644
--- a/usr/gri/gosrc/scanner.go
+++ b/usr/gri/gosrc/scanner.go
@@ -11,7 +11,6 @@
 export const (
 	ILLEGAL = iota;
 	EOF;
-	IDENT;
 	INT;
 	FLOAT;
 	STRING;
@@ -74,6 +73,9 @@
 	LAND;
 	LOR;
 	
+	// IDENT must be immediately before keywords
+	IDENT;
+
 	// keywords
 	KEYWORDS_BEG;
 	BREAK;
@@ -118,7 +120,6 @@
 	switch (tok) {
 	case ILLEGAL: return "illegal";
 	case EOF: return "eof";
-	case IDENT: return "ident";
 	case INT: return "int";
 	case FLOAT: return "float";
 	case STRING: return "string";
@@ -181,6 +182,8 @@
 	case LAND: return "&&";
 	case LOR: return "||";
 
+	case IDENT: return "ident";
+
 	case BREAK: return "break";
 	case CASE: return "case";
 	case CHAN: return "chan";