Repository: jhump/protoreflect
Pull request #263 (2019-08-03 16:04:47)

more explicit AST node types to distinguish between terminals and productions
Several node types were awkwardly re-used across terminals and productions, such as string literals, float literals, and identifiers. These could be terminals for the lexemes. But there were also productions to handle, for example, string concatenation, floats that had a unary `+` or `-` preceding them, and qualified identifiers with whitespaces

The types are now more clear: `stringLiteralNode`, `floatLiteralNode`, and `identNode` are terminals; `compoundStringNode`, `compoudFloatNode`, and `compoundIdentNode` are productions. This also adds a `compoundUintNode` to handle integer literals with a unary `+` preceding them (previously, the location information for the `+` token was simply discarded and only the terminal node was kept). Finally, it simplifies the productions for enum values by unifying the `numberP` and `numberN` cases, for when the numeric value was positive vs. negative.

This change also renames `labelNode` to `fieldLabel` and has the two referring types inline it (instead of use a pointer). Inlining it removes unnecessary/wasteful heap allocations.

This also simplifies the lexer and productions regarding compound identifiers. At one point, this one done completely in the lexer, so it could return `_FQNAME` and `_TYPENAME` tokens, distinct from `_NAME` in that they could contain dots. But, in order to properly support compound names the way `protoc` does (including multi-line names), these have been moved into the `ident` and `typeIdent` productions. So we've now simplified things by removing them from the lexer completely. In the process of tweaking these productions, this fixes some other places that were lacking correct support for multi-line compound identifiers, such as in option names.



Patch:
diff --git a/desc/protoparse/ast.go b/desc/protoparse/ast.go
index 0fb965e..e1eb4df 100644
--- a/desc/protoparse/ast.go
+++ b/desc/protoparse/ast.go
@@ -235,47 +235,39 @@ func (n *fileElement) get() node {
 
 type syntaxNode struct {
 	basicCompositeNode
-	syntax *stringLiteralNode
+	syntax *compoundStringNode
 }
 
 type importNode struct {
 	basicCompositeNode
-	name   *stringLiteralNode
+	name   *compoundStringNode
 	public bool
 	weak   bool
 }
 
 type packageNode struct {
 	basicCompositeNode
-	name *identNode
+	name *compoundIdentNode
 }
 
 type identifier string
 
-type identKind int
-
-const (
-	identSimpleName identKind = iota
-	identQualified
-	identTypeName
-)
-
 type identNode struct {
-	basicCompositeNode
-	val  string
-	kind identKind
+	basicNode
+	val string
 }
 
 func (n *identNode) value() interface{} {
 	return identifier(n.val)
 }
 
-func (n *identNode) popLeadingComment() comment {
-	return n.first.(terminalNode).popLeadingComment()
+type compoundIdentNode struct {
+	basicCompositeNode
+	val string
 }
 
-func (n *identNode) pushTrailingComment(c comment) {
-	n.last.(terminalNode).pushTrailingComment(c)
+func (n *compoundIdentNode) value() interface{} {
+	return identifier(n.val)
 }
 
 type compactOptionsNode struct {
@@ -311,7 +303,7 @@ type optionNameNode struct {
 
 type optionNamePartNode struct {
 	basicCompositeNode
-	text        *identNode
+	text        *compoundIdentNode
 	offset      int
 	length      int
 	isExtension bool
@@ -350,17 +342,21 @@ type valueNode interface {
 }
 
 var _ valueNode = (*identNode)(nil)
+var _ valueNode = (*compoundIdentNode)(nil)
 var _ valueNode = (*stringLiteralNode)(nil)
+var _ valueNode = (*compoundStringNode)(nil)
 var _ valueNode = (*intLiteralNode)(nil)
-var _ valueNode = (*negativeIntLiteralNode)(nil)
+var _ valueNode = (*compoundIntNode)(nil)
+var _ valueNode = (*compoundUintNode)(nil)
 var _ valueNode = (*floatLiteralNode)(nil)
+var _ valueNode = (*compoundFloatNode)(nil)
 var _ valueNode = (*boolLiteralNode)(nil)
 var _ valueNode = (*sliceLiteralNode)(nil)
 var _ valueNode = (*aggregateLiteralNode)(nil)
 var _ valueNode = (*noSourceNode)(nil)
 
 type stringLiteralNode struct {
-	basicCompositeNode
+	basicNode
 	val string
 }
 
@@ -368,12 +364,13 @@ func (n *stringLiteralNode) value() interface{} {
 	return n.val
 }
 
-func (n *stringLiteralNode) popLeadingComment() comment {
-	return n.first.(terminalNode).popLeadingComment()
+type compoundStringNode struct {
+	basicCompositeNode
+	val string
 }
 
-func (n *stringLiteralNode) pushTrailingComment(c comment) {
-	n.last.(terminalNode).pushTrailingComment(c)
+func (n *compoundStringNode) value() interface{} {
+	return n.val
 }
 
 type intLiteralNode struct {
@@ -385,17 +382,26 @@ func (n *intLiteralNode) value() interface{} {
 	return n.val
 }
 
-type negativeIntLiteralNode struct {
+type compoundUintNode struct {
+	basicCompositeNode
+	val uint64
+}
+
+func (n *compoundUintNode) value() interface{} {
+	return n.val
+}
+
+type compoundIntNode struct {
 	basicCompositeNode
 	val int64
 }
 
-func (n *negativeIntLiteralNode) value() interface{} {
+func (n *compoundIntNode) value() interface{} {
 	return n.val
 }
 
 type floatLiteralNode struct {
-	basicCompositeNode
+	basicNode
 	val float64
 }
 
@@ -403,12 +409,13 @@ func (n *floatLiteralNode) value() interface{} {
 	return n.val
 }
 
-func (n *floatLiteralNode) popLeadingComment() comment {
-	return n.first.(terminalNode).popLeadingComment()
+type compoundFloatNode struct {
+	basicCompositeNode
+	val float64
 }
 
-func (n *floatLiteralNode) pushTrailingComment(c comment) {
-	n.last.(terminalNode).pushTrailingComment(c)
+func (n *compoundFloatNode) value() interface{} {
+	return n.val
 }
 
 type boolLiteralNode struct {
@@ -446,7 +453,7 @@ type aggregateEntryNode struct {
 
 type aggregateNameNode struct {
 	basicCompositeNode
-	name        *identNode
+	name        *compoundIdentNode
 	isExtension bool
 }
 
@@ -460,8 +467,8 @@ func (a *aggregateNameNode) value() string {
 
 type fieldNode struct {
 	basicCompositeNode
-	label   *labelNode
-	fldType *identNode
+	label   fieldLabel
+	fldType *compoundIdentNode
 	name    *identNode
 	tag     *intLiteralNode
 	options *compactOptionsNode
@@ -477,10 +484,10 @@ func (n *fieldNode) fieldLabel() node {
 	// proto3 fields and fields inside one-ofs will not have a label and we need
 	// this check in order to return a nil node -- otherwise we'd return a
 	// non-nil node that has a nil pointer value in it :/
-	if n.label == nil {
+	if n.label.identNode == nil {
 		return nil
 	}
-	return n.label
+	return n.label.identNode
 }
 
 func (n *fieldNode) fieldName() node {
@@ -506,7 +513,7 @@ func (n *fieldNode) getGroupKeyword() node {
 	return nil
 }
 
-type labelNode struct {
+type fieldLabel struct {
 	*identNode
 	repeated bool
 	required bool
@@ -515,7 +522,7 @@ type labelNode struct {
 type groupNode struct {
 	basicCompositeNode
 	groupKeyword *identNode
-	label        *labelNode
+	label        fieldLabel
 	name         *identNode
 	tag          *intLiteralNode
 	decls        []*messageElement
@@ -528,11 +535,11 @@ type groupNode struct {
 }
 
 func (n *groupNode) fieldLabel() node {
-	if n.label == nil {
+	if n.label.identNode == nil {
 		// return nil interface to indicate absence, not a typed nil
 		return nil
 	}
-	return n.label
+	return n.label.identNode
 }
 
 func (n *groupNode) fieldName() node {
@@ -607,7 +614,7 @@ type mapTypeNode struct {
 	basicCompositeNode
 	mapKeyword *identNode
 	keyType    *identNode
-	valueType  *identNode
+	valueType  *compoundIdentNode
 }
 
 type mapFieldNode struct {
@@ -647,14 +654,17 @@ func (n *mapFieldNode) messageName() node {
 }
 
 func (n *mapFieldNode) keyField() *syntheticMapField {
-	return newSyntheticMapField(n.mapType.keyType, 1)
+	k := n.mapType.keyType
+	t := &compoundIdentNode{val: k.val}
+	t.setRange(k, k)
+	return newSyntheticMapField(t, 1)
 }
 
 func (n *mapFieldNode) valueField() *syntheticMapField {
 	return newSyntheticMapField(n.mapType.valueType, 2)
 }
 
-func newSyntheticMapField(ident *identNode, tagNum uint64) *syntheticMapField {
+func newSyntheticMapField(ident *compoundIdentNode, tagNum uint64) *syntheticMapField {
 	tag := &intLiteralNode{
 		basicNode: basicNode{
 			posRange: posRange{start: *ident.start(), end: *ident.end()},
@@ -665,7 +675,7 @@ func newSyntheticMapField(ident *identNode, tagNum uint64) *syntheticMapField {
 }
 
 type syntheticMapField struct {
-	ident *identNode
+	ident *compoundIdentNode
 	tag   *intLiteralNode
 }
 
@@ -732,7 +742,7 @@ func (n *rangeNode) rangeEnd() node {
 type reservedNode struct {
 	basicCompositeNode
 	ranges []*rangeNode
-	names  []*stringLiteralNode
+	names  []*compoundStringNode
 }
 
 type enumNode struct {
@@ -780,11 +790,7 @@ type enumValueNode struct {
 	basicCompositeNode
 	name    *identNode
 	options *compactOptionsNode
-
-	// only one of these two will be set:
-
-	numberP *intLiteralNode         // positive numeric value
-	numberN *negativeIntLiteralNode // negative numeric value
+	number  *compoundIntNode
 }
 
 func (n *enumValueNode) getName() node {
@@ -792,10 +798,7 @@ func (n *enumValueNode) getName() node {
 }
 
 func (n *enumValueNode) getNumber() node {
-	if n.numberP != nil {
-		return n.numberP
-	}
-	return n.numberN
+	return n.number
 }
 
 type messageNode struct {
@@ -868,7 +871,7 @@ func (n *messageElement) get() node {
 
 type extendNode struct {
 	basicCompositeNode
-	extendee *identNode
+	extendee *compoundIdentNode
 	decls    []*extendElement
 }
 
@@ -964,7 +967,7 @@ func (n *methodNode) getOutputType() node {
 
 type rpcTypeNode struct {
 	basicCompositeNode
-	msgType       *identNode
+	msgType       *compoundIdentNode
 	streamKeyword node
 }
 
diff --git a/desc/protoparse/lexer.go b/desc/protoparse/lexer.go
index bf33666..b0b5f5b 100644
--- a/desc/protoparse/lexer.go
+++ b/desc/protoparse/lexer.go
@@ -196,19 +196,12 @@ func (l *protoLex) Lex(lval *protoSymType) int {
 		}
 
 		if c == '.' {
-			// tokens that start with a dot include type names and decimal literals
+			// decimal literals could start with a dot
 			cn, _, err := l.input.readRune()
 			if err != nil {
 				l.setRune(lval)
 				return int(c)
 			}
-			if cn == '_' || (cn >= 'a' && cn <= 'z') || (cn >= 'A' && cn <= 'Z') {
-				l.adjustPos(cn)
-				token := []rune{c, cn}
-				token = l.readIdentifier(token)
-				l.setIdent(lval, string(token), identTypeName)
-				return _TYPENAME
-			}
 			if cn >= '0' && cn <= '9' {
 				l.adjustPos(cn)
 				token := []rune{c, cn}
@@ -231,15 +224,11 @@ func (l *protoLex) Lex(lval *protoSymType) int {
 			token := []rune{c}
 			token = l.readIdentifier(token)
 			str := string(token)
-			if strings.Contains(str, ".") {
-				l.setIdent(lval, str, identQualified)
-				return _FQNAME
-			}
 			if t, ok := keywords[str]; ok {
-				l.setIdent(lval, str, identSimpleName)
+				l.setIdent(lval, str)
 				return t
 			}
-			l.setIdent(lval, str, identSimpleName)
+			l.setIdent(lval, str)
 			return _NAME
 		}
 
@@ -441,28 +430,22 @@ func (l *protoLex) setPrev(n terminalNode) {
 }
 
 func (l *protoLex) setString(lval *protoSymType, val string) {
-	b := l.newBasicNode()
-	lval.str = &stringLiteralNode{val: val}
-	lval.str.setRange(&b, &b)
-	l.setPrev(lval.str)
+	lval.s = &stringLiteralNode{basicNode: l.newBasicNode(), val: val}
+	l.setPrev(lval.s)
 }
 
-func (l *protoLex) setIdent(lval *protoSymType, val string, kind identKind) {
-	b := l.newBasicNode()
-	lval.id = &identNode{val: val, kind: kind}
-	lval.id.setRange(&b, &b)
+func (l *protoLex) setIdent(lval *protoSymType, val string) {
+	lval.id = &identNode{basicNode: l.newBasicNode(), val: val}
 	l.setPrev(lval.id)
 }
 
 func (l *protoLex) setInt(lval *protoSymType, val uint64) {
-	lval.ui = &intLiteralNode{basicNode: l.newBasicNode(), val: val}
-	l.setPrev(lval.ui)
+	lval.i = &intLiteralNode{basicNode: l.newBasicNode(), val: val}
+	l.setPrev(lval.i)
 }
 
 func (l *protoLex) setFloat(lval *protoSymType, val float64) {
-	b := l.newBasicNode()
-	lval.f = &floatLiteralNode{val: val}
-	lval.f.setRange(&b, &b)
+	lval.f = &floatLiteralNode{basicNode: l.newBasicNode(), val: val}
 	l.setPrev(lval.f)
 }
 
@@ -558,21 +541,7 @@ func (l *protoLex) readIdentifier(sofar []rune) []rune {
 		if err != nil {
 			break
 		}
-		if c == '.' {
-			cn, _, err := l.input.readRune()
-			if err != nil {
-				l.input.unreadRune(c)
-				break
-			}
-			if cn != '_' && (cn < 'a' || cn > 'z') && (cn < 'A' || cn > 'Z') {
-				l.input.unreadRune(cn)
-				l.input.unreadRune(c)
-				break
-			}
-			l.adjustPos(c)
-			token = append(token, c)
-			c = cn
-		} else if c != '_' && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') {
+		if c != '_' && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') {
 			l.input.unreadRune(c)
 			break
 		}
diff --git a/desc/protoparse/parser.go b/desc/protoparse/parser.go
index 1d95d73..6eb1acc 100644
--- a/desc/protoparse/parser.go
+++ b/desc/protoparse/parser.go
@@ -29,8 +29,6 @@ func init() {
 	setTokenName(_INT_LIT, "int literal")
 	setTokenName(_FLOAT_LIT, "float literal")
 	setTokenName(_NAME, "identifier")
-	setTokenName(_FQNAME, "fully-qualified name")
-	setTokenName(_TYPENAME, "type name")
 	setTokenName(_ERROR, "error")
 	// for keywords, just show the keyword itself wrapped in quotes
 	for str, i := range keywords {
@@ -771,8 +769,8 @@ func (r *parseResult) addExtensions(ext *extendNode, flds *[]*dpb.FieldDescripto
 	}
 }
 
-func asLabel(lbl *labelNode) *dpb.FieldDescriptorProto_Label {
-	if lbl == nil {
+func asLabel(lbl *fieldLabel) *dpb.FieldDescriptorProto_Label {
+	if lbl.identNode == nil {
 		return nil
 	}
 	switch {
@@ -786,7 +784,7 @@ func asLabel(lbl *labelNode) *dpb.FieldDescriptorProto_Label {
 }
 
 func (r *parseResult) asFieldDescriptor(node *fieldNode) *dpb.FieldDescriptorProto {
-	fd := newFieldDescriptor(node.name.val, node.fldType.val, int32(node.tag.val), asLabel(node.label))
+	fd := newFieldDescriptor(node.name.val, node.fldType.val, int32(node.tag.val), asLabel(&node.label))
 	r.putFieldNode(fd, node)
 	if opts := node.options.Elements(); len(opts) > 0 {
 		fd.Options = &dpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
@@ -837,7 +835,7 @@ func (r *parseResult) asGroupDescriptors(group *groupNode, isProto3 bool) (*dpb.
 		Name:     proto.String(fieldName),
 		JsonName: proto.String(internal.JsonName(fieldName)),
 		Number:   proto.Int32(int32(group.tag.val)),
-		Label:    asLabel(group.label),
+		Label:    asLabel(&group.label),
 		Type:     dpb.FieldDescriptorProto_TYPE_GROUP.Enum(),
 		TypeName: proto.String(group.name.val),
 	}
@@ -890,12 +888,7 @@ func (r *parseResult) asExtensionRanges(node *extensionRangeNode) []*dpb.Descrip
 }
 
 func (r *parseResult) asEnumValue(ev *enumValueNode) *dpb.EnumValueDescriptorProto {
-	var num int32
-	if ev.numberP != nil {
-		num = int32(ev.numberP.val)
-	} else {
-		num = int32(ev.numberN.val)
-	}
+	num := int32(ev.number.val)
 	evd := &dpb.EnumValueDescriptorProto{Name: proto.String(ev.name.val), Number: proto.Int32(num)}
 	r.putEnumValueNode(evd, ev)
 	if opts := ev.options.Elements(); len(opts) > 0 {
@@ -1049,7 +1042,7 @@ func (r *parseResult) asServiceDescriptor(svc *serviceNode) *dpb.ServiceDescript
 	return sd
 }
 
-func toNameParts(ident *identNode, offset int) []*optionNamePartNode {
+func toNameParts(ident *compoundIdentNode, offset int) []*optionNamePartNode {
 	parts := strings.Split(ident.val[offset:], ".")
 	ret := make([]*optionNamePartNode, len(parts))
 	for i, p := range parts {
diff --git a/desc/protoparse/proto.y b/desc/protoparse/proto.y
index f354cbb..a795fe7 100644
--- a/desc/protoparse/proto.y
+++ b/desc/protoparse/proto.y
@@ -44,14 +44,16 @@ import (
 	optNm     []*optionNamePartNode
 	cmpctOpts *compactOptionsNode
 	rngs      []*rangeNode
-	names     []*stringLiteralNode
+	names     []*compoundStringNode
+	cid       *compoundIdentNode
 	sl        []valueNode
 	agg       []*aggregateEntryNode
 	aggName   *aggregateNameNode
 	v         valueNode
-	str       *stringLiteralNode
-	i         *negativeIntLiteralNode
-	ui        *intLiteralNode
+	il        *compoundIntNode
+	str       *compoundStringNode
+	s         *stringLiteralNode
+	i         *intLiteralNode
 	f         *floatLiteralNode
 	id        *identNode
 	b         *basicNode
@@ -68,12 +70,11 @@ import (
 %type <opts>      option compactOption compactOptionDecls rpcOption rpcOptions
 %type <optNm>     optionName optionNameRest optionNameComponent
 %type <cmpctOpts> compactOptions
-%type <v>         constant scalarConstant aggregate
-%type <id>        name ident typeIdent keyType
+%type <v>         constant scalarConstant aggregate uintLit floatLit
+%type <il>        intLit negIntLit
+%type <id>        name keyType
+%type <cid>       ident typeIdent
 %type <aggName>   aggName
-%type <i>         negIntLit
-%type <ui>        intLit
-%type <f>         floatLit
 %type <sl>        constantList
 %type <agg>       aggFields aggField aggFieldEntry
 %type <fld>       field oneofField
@@ -100,10 +101,10 @@ import (
 %type <rpcType>   rpcType
 
 // same for terminals
-%token <str> _STRING_LIT
-%token <ui>  _INT_LIT
+%token 
 _STRING_LIT
+%token <i>  _INT_LIT
 %token <f>   _FLOAT_LIT
-%token <id>  _NAME _FQNAME _TYPENAME
+%token <id>  _NAME
 %token <id>  _SYNTAX _IMPORT _WEAK _PUBLIC _PACKAGE _OPTION _TRUE _FALSE _INF _NAN _REPEATED _OPTIONAL _REQUIRED
 %token <id>  _DOUBLE _FLOAT _INT32 _INT64 _UINT32 _UINT64 _SINT32 _SINT64 _FIXED32 _FIXED64 _SFIXED32 _SFIXED64
 %token <id>  _BOOL _STRING _BYTES _GROUP _ONEOF _MAP _EXTENSIONS _TO _MAX _RESERVED _ENUM _MESSAGE _EXTEND
@@ -201,8 +202,14 @@ package : _PACKAGE ident ';' {
 		$$.setRange($1, $3)
 	}
 
-ident : name
-	| _FQNAME
+ident : name {
+        $$ = &compoundIdentNode{val: $1.val}
+        $$.setRange($1, $1)
+    }
+	| ident '.' name {
+        $$ = &compoundIdentNode{val: $1.val + "." + $3.val}
+        $$.setRange($1, $3)
+	}
 
 option : _OPTION optionName '=' constant ';' {
 		n := &optionNameNode{parts: $2}
@@ -233,7 +240,7 @@ optionNameRest : optionNameComponent
 		$$ = append($1, $2...)
 	}
 
-optionNameComponent : _TYPENAME {
+optionNameComponent : typeIdent {
 		$$ = toNameParts($1, 1 /* exclude leading dot */)
 	}
 	| '.' '(' typeIdent ')' {
@@ -248,26 +255,22 @@ constant : scalarConstant
 scalarConstant : stringLit {
 		$$ = $1
 	}
-	| intLit {
-		$$ = $1
-	}
+	| uintLit
 	| negIntLit {
-		$$ = $1
-	}
-	| floatLit {
-		$$ = $1
+	    $$ = $1
 	}
+	| floatLit
 	| name {
 		if $1.val == "true" {
 			$$ = &boolLiteralNode{identNode: $1, val: true}
 		} else if $1.val == "false" {
 			$$ = &boolLiteralNode{identNode: $1, val: false}
 		} else if $1.val == "inf" {
-			f := &floatLiteralNode{val: math.Inf(1)}
+			f := &compoundFloatNode{val: math.Inf(1)}
 			f.setRange($1, $1)
 			$$ = f
 		} else if $1.val == "nan" {
-			f := &floatLiteralNode{val: math.NaN()}
+			f := &compoundFloatNode{val: math.NaN()}
 			f.setRange($1, $1)
 			$$ = f
 		} else {
@@ -275,40 +278,65 @@ scalarConstant : stringLit {
 		}
 	}
 
-intLit : _INT_LIT
+uintLit : _INT_LIT {
+        i := &compoundUintNode{val: $1.val}
+        i.setRange($1, $1)
+        $$ = i
+    }
 	| '+' _INT_LIT {
-		$$ = $2
+        i := &compoundUintNode{val: $2.val}
+        i.setRange($1, $2)
+        $$ = i
 	}
 
 negIntLit : '-' _INT_LIT {
 		if $2.val > math.MaxInt64 + 1 {
 			lexError(protolex, $2.start(), fmt.Sprintf("numeric constant %d would underflow (allowed range is %d to %d)", $2.val, int64(math.MinInt64), int64(math.MaxInt64)))
 		}
-		$$ = &negativeIntLiteralNode{val: -int64($2.val)}
-		$$.setRange($1, $2)
-	}
+		i := &compoundIntNode{val: -int64($2.val)}
+		i.setRange($1, $2)
+		$$ = i
+	}
+
+intLit : negIntLit
+    | _INT_LIT {
+        // we don't allow uintLit because this is for enum numeric vals, which don't allow '+'
+        checkUint64InInt32Range(protolex, $1.start(), $1.val)
+		i := &compoundIntNode{val: int64($1.val)}
+		i.setRange($1, $1)
+		$$ = i
+    }
 
-floatLit : _FLOAT_LIT
+floatLit : _FLOAT_LIT {
+        $$ = $1
+    }
 	| '-' _FLOAT_LIT {
-		$$ = &floatLiteralNode{val: -$2.val}
-		$$.setRange($1, $2)
+		f := &compoundFloatNode{val: -$2.val}
+		f.setRange($1, $2)
+		$$ = f
 	}
 	| '+' _FLOAT_LIT {
-		$$ = &floatLiteralNode{val: $2.val}
-		$$.setRange($1, $2)
+		f := &compoundFloatNode{val: $2.val}
+		f.setRange($1, $2)
+		$$ = f
 	}
 	| '+' _INF {
-		$$ = &floatLiteralNode{val: math.Inf(1)}
-		$$.setRange($1, $2)
+		f := &compoundFloatNode{val: math.Inf(1)}
+		f.setRange($1, $2)
+		$$ = f
 	}
 	| '-' _INF {
-		$$ = &floatLiteralNode{val: math.Inf(-1)}
-		$$.setRange($1, $2)
+		f := &compoundFloatNode{val: math.Inf(-1)}
+		f.setRange($1, $2)
+		$$ = f
 	}
 
-stringLit : _STRING_LIT
+stringLit : _STRING_LIT {
+        $$ = &compoundStringNode{val: $1.val}
+        $$.setRange($1, $1)
+    }
     | stringLit _STRING_LIT {
-        $$ = &stringLiteralNode{val: $1.val + $2.val}
+        $$ = &compoundStringNode{val: $1.val + $2.val}
         $$.setRange($1, $2)
     }
 
@@ -391,10 +419,12 @@ aggFieldEntry : aggName ':' scalarConstant {
 	}
 
 aggName : name {
-		$$ = &aggregateNameNode{name: $1}
+        n := &compoundIdentNode{val: $1.val}
+        n.setRange($1, $1)
+		$$ = &aggregateNameNode{name: n}
 		$$.setRange($1, $1)
 	}
-	| '[' ident ']' {
+	| '[' typeIdent ']' {
 		$$ = &aggregateNameNode{name: $2, isExtension: true}
 		$$.setRange($1, $3)
 	}
@@ -433,35 +463,26 @@ constantList : constant {
 	}
 
 typeIdent : ident
-	| _TYPENAME
-	| '.' ident {
-        $$ = &identNode{val: "." + $2.val}
-        $$.setRange($1, $2)
-	}
-	| typeIdent _TYPENAME {
-        $$ = &identNode{val: $1.val + $2.val}
-        $$.setRange($1, $2)
-	}
-	| typeIdent '.' ident {
-        $$ = &identNode{val: $1.val + "." + $3.val}
-        $$.setRange($1, $3)
-	}
+    | '.' ident {
+          $$ = &compoundIdentNode{val: "." + $2.val}
+          $$.setRange($1, $2)
+    }
 
 field : _REQUIRED typeIdent name '=' _INT_LIT ';' {
 		checkTag(protolex, $5.start(), $5.val)
-		lbl := &labelNode{identNode: $1, required: true}
+		lbl := fieldLabel{identNode: $1, required: true}
 		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5}
 		$$.setRange($1, $6)
 	}
 	| _OPTIONAL typeIdent name '=' _INT_LIT ';' {
 		checkTag(protolex, $5.start(), $5.val)
-		lbl := &labelNode{identNode: $1}
+		lbl := fieldLabel{identNode: $1}
 		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5}
 		$$.setRange($1, $6)
 	}
 	| _REPEATED typeIdent name '=' _INT_LIT ';' {
 		checkTag(protolex, $5.start(), $5.val)
-		lbl := &labelNode{identNode: $1, repeated: true}
+		lbl := fieldLabel{identNode: $1, repeated: true}
 		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5}
 		$$.setRange($1, $6)
 	}
@@ -472,19 +493,19 @@ field : _REQUIRED typeIdent name '=' _INT_LIT ';' {
 	}
 	| _REQUIRED typeIdent name '=' _INT_LIT compactOptions ';' {
 		checkTag(protolex, $5.start(), $5.val)
-		lbl := &labelNode{identNode: $1, required: true}
+		lbl := fieldLabel{identNode: $1, required: true}
 		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5, options: $6}
 		$$.setRange($1, $7)
 	}
 	| _OPTIONAL typeIdent name '=' _INT_LIT compactOptions ';' {
 		checkTag(protolex, $5.start(), $5.val)
-		lbl := &labelNode{identNode: $1}
+		lbl := fieldLabel{identNode: $1}
 		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5, options: $6}
 		$$.setRange($1, $7)
 	}
 	| _REPEATED typeIdent name '=' _INT_LIT compactOptions ';' {
 		checkTag(protolex, $5.start(), $5.val)
-		lbl := &labelNode{identNode: $1, repeated: true}
+		lbl := fieldLabel{identNode: $1, repeated: true}
 		$$ = &fieldNode{label: lbl, fldType: $2, name: $3, tag: $5, options: $6}
 		$$.setRange($1, $7)
 	}
@@ -517,7 +538,7 @@ group : _REQUIRED _GROUP name '=' _INT_LIT '{' messageBody '}' {
 		if !unicode.IsUpper(rune($3.val[0])) {
 			lexError(protolex, $3.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", $3.val))
 		}
-		lbl := &labelNode{identNode: $1, required: true}
+		lbl := fieldLabel{identNode: $1, required: true}
 		$$ = &groupNode{groupKeyword: $2, label: lbl, name: $3, tag: $5, decls: $7}
 		$$.setRange($1, $8)
 	}
@@ -526,7 +547,7 @@ group : _REQUIRED _GROUP name '=' _INT_LIT '{' messageBody '}' {
 		if !unicode.IsUpper(rune($3.val[0])) {
 			lexError(protolex, $3.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", $3.val))
 		}
-		lbl := &labelNode{identNode: $1}
+		lbl := fieldLabel{identNode: $1}
 		$$ = &groupNode{groupKeyword: $2, label: lbl, name: $3, tag: $5, decls: $7}
 		$$.setRange($1, $8)
 	}
@@ -535,7 +556,7 @@ group : _REQUIRED _GROUP name '=' _INT_LIT '{' messageBody '}' {
 		if !unicode.IsUpper(rune($3.val[0])) {
 			lexError(protolex, $3.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", $3.val))
 		}
-		lbl := &labelNode{identNode: $1, repeated: true}
+		lbl := fieldLabel{identNode: $1, repeated: true}
 		$$ = &groupNode{groupKeyword: $2, label: lbl, name: $3, tag: $5, decls: $7}
 		$$.setRange($1, $8)
 	}
@@ -678,29 +699,13 @@ enumRanges : enumRanges ',' enumRange {
 	}
 	| enumRange
 
-enumRange : _INT_LIT {
-		checkUint64InInt32Range(protolex, $1.start(), $1.val)
-		r := &rangeNode{stNode: $1, enNode: $1, st: int32($1.val), en: int32($1.val)}
-		r.setRange($1, $1)
-		$$ = []*rangeNode{r}
-	}
-	| negIntLit {
+enumRange : intLit {
 		checkInt64InInt32Range(protolex, $1.start(), $1.val)
 		r := &rangeNode{stNode: $1, enNode: $1, st: int32($1.val), en: int32($1.val)}
 		r.setRange($1, $1)
 		$$ = []*rangeNode{r}
 	}
-	| _INT_LIT _TO _INT_LIT {
-		checkUint64InInt32Range(protolex, $1.start(), $1.val)
-		checkUint64InInt32Range(protolex, $3.start(), $3.val)
-		if $1.val > $3.val {
-			lexError(protolex, $1.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", $1.val, $3.val))
-		}
-		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: int32($3.val)}
-		r.setRange($1, $3)
-		$$ = []*rangeNode{r}
-	}
-	| negIntLit _TO negIntLit {
+	| intLit _TO intLit {
 		checkInt64InInt32Range(protolex, $1.start(), $1.val)
 		checkInt64InInt32Range(protolex, $3.start(), $3.val)
 		if $1.val > $3.val {
@@ -710,20 +715,7 @@ enumRange : _INT_LIT {
 		r.setRange($1, $3)
 		$$ = []*rangeNode{r}
 	}
-	| negIntLit _TO _INT_LIT {
-		checkInt64InInt32Range(protolex, $1.start(), $1.val)
-		checkUint64InInt32Range(protolex, $3.start(), $3.val)
-		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: int32($3.val)}
-		r.setRange($1, $3)
-		$$ = []*rangeNode{r}
-	}
-	| _INT_LIT _TO _MAX {
-		checkUint64InInt32Range(protolex, $1.start(), $1.val)
-		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: math.MaxInt32}
-		r.setRange($1, $3)
-		$$ = []*rangeNode{r}
-	}
-	| negIntLit _TO _MAX {
+	| intLit _TO _MAX {
 		checkInt64InInt32Range(protolex, $1.start(), $1.val)
 		r := &rangeNode{stNode: $1, enNode: $3, st: int32($1.val), en: math.MaxInt32}
 		r.setRange($1, $3)
@@ -759,7 +751,7 @@ fieldNames : fieldNames ',' stringLit {
 		$$ = append($1, $3)
 	}
 	| stringLit {
-		$$ = []*stringLiteralNode{$1}
+		$$ = []*compoundStringNode{$1}
 	}
 
 enum : _ENUM name '{' enumBody '}' {
@@ -801,24 +793,14 @@ enumItem : option {
 	| error {
 	}
 
-enumField : name '=' _INT_LIT ';' {
-		checkUint64InInt32Range(protolex, $3.start(), $3.val)
-		$$ = &enumValueNode{name: $1, numberP: $3}
-		$$.setRange($1, $4)
-	}
-	|  name '=' _INT_LIT compactOptions ';' {
-		checkUint64InInt32Range(protolex, $3.start(), $3.val)
-		$$ = &enumValueNode{name: $1, numberP: $3, options: $4}
-		$$.setRange($1, $5)
-	}
-	| name '=' negIntLit ';' {
+enumField : name '=' intLit ';' {
 		checkInt64InInt32Range(protolex, $3.start(), $3.val)
-		$$ = &enumValueNode{name: $1, numberN: $3}
+		$$ = &enumValueNode{name: $1, number: $3}
 		$$.setRange($1, $4)
 	}
-	|  name '=' negIntLit compactOptions ';' {
+	|  name '=' intLit compactOptions ';' {
 		checkInt64InInt32Range(protolex, $3.start(), $3.val)
-		$$ = &enumValueNode{name: $1, numberN: $3, options: $4}
+		$$ = &enumValueNode{name: $1, number: $3, options: $4}
 		$$.setRange($1, $5)
 	}
 
diff --git a/desc/protoparse/proto.y.go b/desc/protoparse/proto.y.go
index 0bed21b..843df01 100644
--- a/desc/protoparse/proto.y.go
+++ b/desc/protoparse/proto.y.go
@@ -48,14 +48,16 @@ type protoSymType struct {
 	optNm     []*optionNamePartNode
 	cmpctOpts *compactOptionsNode
 	rngs      []*rangeNode
-	names     []*stringLiteralNode
+	names     []*compoundStringNode
+	cid       *compoundIdentNode
 	sl        []valueNode
 	agg       []*aggregateEntryNode
 	aggName   *aggregateNameNode
 	v         valueNode
-	str       *stringLiteralNode
-	i         *negativeIntLiteralNode
-	ui        *intLiteralNode
+	il        *compoundIntNode
+	str       *compoundStringNode
+	s         *stringLiteralNode
+	i         *intLiteralNode
 	f         *floatLiteralNode
 	id        *identNode
 	b         *basicNode
@@ -66,51 +68,49 @@ const _STRING_LIT = 57346
 const _INT_LIT = 57347
 const _FLOAT_LIT = 57348
 const _NAME = 57349
-const _FQNAME = 57350
-const _TYPENAME = 57351
-const _SYNTAX = 57352
-const _IMPORT = 57353
-const _WEAK = 57354
-const _PUBLIC = 57355
-const _PACKAGE = 57356
-const _OPTION = 57357
-const _TRUE = 57358
-const _FALSE = 57359
-const _INF = 57360
-const _NAN = 57361
-const _REPEATED = 57362
-const _OPTIONAL = 57363
-const _REQUIRED = 57364
-const _DOUBLE = 57365
-const _FLOAT = 57366
-const _INT32 = 57367
-const _INT64 = 57368
-const _UINT32 = 57369
-const _UINT64 = 57370
-const _SINT32 = 57371
-const _SINT64 = 57372
-const _FIXED32 = 57373
-const _FIXED64 = 57374
-const _SFIXED32 = 57375
-const _SFIXED64 = 57376
-const _BOOL = 57377
-const _STRING = 57378
-const _BYTES = 57379
-const _GROUP = 57380
-const _ONEOF = 57381
-const _MAP = 57382
-const _EXTENSIONS = 57383
-const _TO = 57384
-const _MAX = 57385
-const _RESERVED = 57386
-const _ENUM = 57387
-const _MESSAGE = 57388
-const _EXTEND = 57389
-const _SERVICE = 57390
-const _RPC = 57391
-const _STREAM = 57392
-const _RETURNS = 57393
-const _ERROR = 57394
+const _SYNTAX = 57350
+const _IMPORT = 57351
+const _WEAK = 57352
+const _PUBLIC = 57353
+const _PACKAGE = 57354
+const _OPTION = 57355
+const _TRUE = 57356
+const _FALSE = 57357
+const _INF = 57358
+const _NAN = 57359
+const _REPEATED = 57360
+const _OPTIONAL = 57361
+const _REQUIRED = 57362
+const _DOUBLE = 57363
+const _FLOAT = 57364
+const _INT32 = 57365
+const _INT64 = 57366
+const _UINT32 = 57367
+const _UINT64 = 57368
+const _SINT32 = 57369
+const _SINT64 = 57370
+const _FIXED32 = 57371
+const _FIXED64 = 57372
+const _SFIXED32 = 57373
+const _SFIXED64 = 57374
+const _BOOL = 57375
+const _STRING = 57376
+const _BYTES = 57377
+const _GROUP = 57378
+const _ONEOF = 57379
+const _MAP = 57380
+const _EXTENSIONS = 57381
+const _TO = 57382
+const _MAX = 57383
+const _RESERVED = 57384
+const _ENUM = 57385
+const _MESSAGE = 57386
+const _EXTEND = 57387
+const _SERVICE = 57388
+const _RPC = 57389
+const _STREAM = 57390
+const _RETURNS = 57391
+const _ERROR = 57392
 
 var protoToknames = [...]string{
 	"$end",
@@ -120,8 +120,6 @@ var protoToknames = [...]string{
 	"_INT_LIT",
 	"_FLOAT_LIT",
 	"_NAME",
-	"_FQNAME",
-	"_TYPENAME",
 	"_SYNTAX",
 	"_IMPORT",
 	"_WEAK",
@@ -200,7 +198,7 @@ const protoEofCode = 1
 const protoErrCode = 2
 const protoInitialStackSize = 16
 
-//line proto.y:1023
+//line proto.y:1005
 
 //line yacctab:1
 var protoExca = [...]int{
@@ -219,548 +217,543 @@ var protoExca = [...]int{
 	-1, 22,
 	1, 3,
 	-2, 0,
+	-1, 93,
+	55, 162,
+	-2, 0,
 	-1, 94,
-	57, 169,
+	55, 150,
 	-2, 0,
 	-1, 95,
-	57, 155,
+	55, 179,
 	-2, 0,
-	-1, 98,
-	57, 186,
+	-1, 97,
+	55, 188,
 	-2, 0,
-	-1, 100,
-	57, 195,
+	-1, 110,
+	55, 54,
 	-2, 0,
-	-1, 112,
-	57, 52,
+	-1, 229,
+	61, 54,
 	-2, 0,
-	-1, 231,
-	63, 52,
+	-1, 246,
+	55, 103,
 	-2, 0,
-	-1, 248,
-	57, 104,
+	-1, 272,
+	61, 54,
 	-2, 0,
-	-1, 276,
-	63, 52,
+	-1, 316,
+	61, 54,
 	-2, 0,
-	-1, 325,
-	63, 52,
+	-1, 354,
+	55, 162,
 	-2, 0,
-	-1, 364,
-	57, 169,
+	-1, 357,
+	55, 162,
 	-2, 0,
-	-1, 367,
-	57, 169,
+	-1, 360,
+	55, 162,
 	-2, 0,
 	-1, 370,
-	57, 169,
-	-2, 0,
-	-1, 380,
-	63, 52,
+	61, 54,
 	-2, 0,
-	-1, 382,
-	63, 52,
+	-1, 372,
+	61, 54,
 	-2, 0,
-	-1, 403,
-	57, 169,
+	-1, 393,
+	55, 162,
 	-2, 0,
-	-1, 414,
-	57, 207,
+	-1, 404,
+	55, 200,
 	-2, 0,
 }
 
 const protoPrivate = 57344
 
-const protoLast = 2638
+const protoLast = 2634
 
 var protoAct = [...]int{
 
-	31, 126, 8, 416, 8, 8, 118, 119, 318, 172,
-	76, 135, 292, 104, 297, 199, 212, 125, 105, 79,
-	80, 184, 85, 107, 8, 82, 171, 164, 244, 106,
-	109, 120, 81, 144, 357, 147, 96, 356, 340, 26,
-	158, 243, 30, 77, 198, 355, 339, 401, 86, 245,
-	368, 89, 90, 354, 365, 362, 246, 347, 337, 310,
-	308, 280, 246, 96, 279, 246, 411, 352, 96, 246,
-	246, 316, 246, 246, 246, 246, 393, 29, 213, 213,
-	272, 235, 206, 229, 112, 307, 269, 403, 97, 186,
-	93, 266, 231, 111, 268, 330, 153, 148, 228, 96,
-	251, 370, 165, 228, 367, 422, 227, 408, 252, 317,
-	99, 227, 406, 176, 364, 97, 160, 248, 100, 228,
-	97, 96, 117, 156, 95, 228, 189, 227, 384, 155,
-	159, 94, 215, 227, 361, 409, 197, 80, 79, 215,
-	215, 187, 201, 202, 191, 193, 195, 153, 148, 228,
-	81, 97, 215, 377, 250, 228, 226, 227, 329, 413,
-	88, 414, 245, 227, 225, 165, 77, 205, 98, 389,
-	222, 419, 176, 97, 14, 160, 387, 168, 205, 385,
-	155, 224, 208, 15, 17, 214, 16, 17, 203, 159,
-	17, 220, 236, 237, 238, 239, 240, 241, 217, 88,
-	14, 419, 376, 232, 88, 230, 371, 234, 4, 15,
-	103, 351, 16, 17, 17, 168, 88, 19, 18, 20,
-	21, 350, 344, 418, 169, 289, 13, 221, 17, 167,
-	111, 218, 176, 209, 190, 170, 91, 25, 375, 374,
-	341, 267, 287, 19, 18, 20, 21, 281, 273, 102,
-	298, 313, 13, 418, 101, 286, 420, 293, 277, 275,
-	303, 290, 169, 285, 284, 378, 87, 167, 283, 282,
-	219, 249, 77, 242, 210, 111, 306, 176, 176, 92,
-	24, 271, 294, 270, 320, 312, 247, 224, 324, 314,
-	123, 11, 29, 11, 11, 309, 311, 392, 298, 214,
-	27, 28, 315, 326, 345, 346, 121, 10, 303, 10,
-	10, 343, 5, 11, 29, 200, 23, 338, 391, 349,
-	295, 122, 9, 336, 9, 9, 176, 176, 335, 10,
-	334, 353, 181, 182, 348, 23, 224, 178, 179, 333,
-	332, 331, 111, 305, 9, 183, 200, 288, 181, 88,
-	180, 293, 358, 372, 29, 373, 111, 111, 3, 176,
-	363, 22, 366, 166, 369, 163, 77, 12, 224, 379,
-	381, 386, 157, 149, 388, 146, 124, 390, 211, 150,
-	129, 176, 204, 176, 296, 142, 128, 300, 127, 299,
-	173, 322, 110, 108, 189, 176, 189, 176, 189, 175,
-	253, 185, 404, 415, 224, 320, 224, 394, 291, 396,
-	410, 7, 6, 2, 1, 0, 417, 417, 189, 421,
-	402, 323, 0, 29, 113, 116, 33, 0, 0, 34,
-	35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
-	45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
-	55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
-	65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
-	75, 0, 0, 0, 0, 112, 0, 0, 0, 0,
-	0, 0, 0, 325, 114, 115, 0, 0, 0, 321,
-	29, 113, 116, 33, 0, 0, 34, 35, 36, 37,
+	31, 124, 8, 406, 8, 8, 116, 117, 169, 75,
+	309, 288, 293, 209, 196, 107, 210, 103, 181, 78,
+	79, 161, 83, 104, 8, 168, 123, 81, 133, 118,
+	155, 195, 102, 142, 105, 145, 391, 358, 346, 331,
+	241, 355, 352, 242, 30, 76, 345, 330, 243, 80,
+	26, 244, 244, 338, 344, 244, 244, 244, 328, 84,
+	347, 304, 87, 88, 276, 275, 401, 212, 244, 342,
+	321, 29, 212, 244, 115, 383, 244, 268, 212, 227,
+	110, 226, 203, 367, 303, 226, 90, 412, 229, 225,
+	398, 101, 109, 225, 396, 151, 146, 266, 393, 162,
+	226, 360, 399, 308, 226, 265, 92, 226, 225, 374,
+	96, 173, 225, 351, 357, 225, 320, 403, 354, 404,
+	89, 249, 157, 379, 186, 156, 213, 90, 153, 250,
+	248, 213, 377, 246, 194, 79, 78, 213, 243, 226,
+	198, 199, 224, 97, 183, 151, 146, 225, 95, 94,
+	223, 93, 165, 375, 366, 361, 86, 341, 335, 188,
+	190, 192, 162, 17, 14, 80, 76, 220, 211, 173,
+	4, 15, 165, 200, 16, 17, 202, 222, 153, 86,
+	205, 157, 218, 17, 156, 215, 86, 202, 409, 234,
+	235, 236, 237, 238, 239, 86, 228, 166, 285, 17,
+	219, 232, 164, 230, 100, 19, 18, 20, 21, 409,
+	216, 183, 96, 206, 13, 187, 167, 166, 25, 365,
+	17, 368, 164, 211, 264, 217, 14, 99, 109, 364,
+	173, 332, 283, 15, 98, 282, 16, 17, 408, 281,
+	280, 410, 290, 85, 279, 269, 278, 247, 294, 240,
+	207, 271, 91, 24, 289, 273, 267, 245, 286, 408,
+	29, 197, 277, 382, 381, 327, 326, 19, 18, 20,
+	21, 109, 76, 173, 173, 299, 13, 325, 291, 306,
+	324, 211, 222, 211, 307, 302, 121, 11, 323, 11,
+	11, 322, 119, 10, 294, 10, 10, 311, 317, 301,
+	336, 337, 5, 315, 197, 334, 23, 284, 305, 11,
+	178, 178, 179, 175, 176, 10, 86, 173, 173, 29,
+	163, 299, 180, 29, 177, 23, 222, 160, 329, 27,
+	28, 3, 340, 109, 22, 12, 154, 147, 144, 343,
+	122, 289, 348, 362, 208, 339, 109, 109, 148, 173,
+	127, 120, 9, 201, 9, 9, 292, 222, 140, 76,
+	126, 376, 296, 125, 378, 363, 353, 380, 356, 295,
+	359, 173, 170, 173, 9, 313, 172, 251, 369, 371,
+	108, 106, 182, 405, 186, 173, 186, 173, 186, 287,
+	7, 6, 2, 222, 394, 222, 384, 1, 386, 0,
+	400, 0, 0, 0, 0, 0, 407, 407, 186, 411,
+	0, 0, 311, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 314, 392, 29, 111, 114, 32,
+	33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+	53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+	63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+	73, 74, 0, 0, 0, 0, 110, 0, 0, 0,
+	0, 0, 0, 0, 316, 112, 113, 0, 0, 0,
+	312, 29, 111, 114, 32, 33, 34, 35, 36, 37,
 	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
 	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	68, 69, 70, 71, 72, 73, 74, 75, 0, 0,
-	0, 0, 112, 0, 0, 0, 0, 0, 0, 0,
-	276, 114, 115, 0, 0, 274, 29, 113, 116, 33,
-	0, 0, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
-	72, 73, 74, 75, 0, 0, 0, 0, 112, 0,
-	0, 0, 0, 0, 0, 0, 382, 114, 115, 29,
-	113, 116, 33, 0, 0, 34, 35, 36, 37, 38,
-	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
-	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
-	69, 70, 71, 72, 73, 74, 75, 0, 0, 0,
-	0, 112, 0, 0, 0, 0, 0, 174, 0, 380,
-	114, 115, 33, 0, 0, 34, 35, 36, 37, 38,
-	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
-	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
-	69, 70, 71, 72, 73, 74, 75, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 174, 407, 0,
-	0, 0, 33, 0, 177, 34, 35, 36, 37, 38,
-	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
-	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
-	69, 70, 71, 72, 73, 74, 75, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 174, 405, 0,
-	0, 0, 33, 0, 177, 34, 35, 36, 37, 38,
-	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
-	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
-	69, 70, 71, 72, 73, 74, 75, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 383, 29,
-	113, 116, 33, 0, 177, 34, 35, 36, 37, 38,
-	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
-	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
-	69, 70, 71, 72, 73, 74, 75, 0, 0, 0,
-	0, 112, 0, 0, 174, 0, 0, 0, 0, 33,
-	114, 115, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
-	72, 73, 74, 75, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 174, 360, 0, 0, 0, 33,
-	0, 177, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
-	72, 73, 74, 75, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 174, 328, 0, 0, 0, 33,
-	0, 177, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
-	72, 73, 74, 75, 0, 0, 0, 0, 0, 223,
-	0, 0, 0, 0, 397, 0, 0, 0, 0, 33,
-	0, 177, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
-	72, 73, 74, 75, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 395, 0, 0, 0, 0, 33,
-	0, 177, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
-	72, 73, 74, 75, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 359, 0, 0, 0, 0, 33,
-	0, 177, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
-	72, 73, 74, 75, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 327, 0, 0, 0, 0, 33,
-	0, 177, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
-	72, 73, 74, 75, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 278, 0, 0, 0, 0, 33,
-	0, 177, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
-	72, 73, 74, 75, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 174, 0, 0, 0, 0, 33,
-	0, 177, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
-	72, 73, 74, 75, 254, 255, 256, 257, 258, 259,
-	260, 261, 262, 263, 264, 265, 0, 0, 0, 33,
-	32, 177, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
-	72, 73, 74, 75, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 131, 0, 0, 0, 78,
-	33, 32, 83, 34, 35, 36, 37, 38, 140, 40,
-	41, 42, 43, 134, 133, 132, 47, 48, 49, 50,
-	51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
-	61, 62, 141, 145, 139, 66, 67, 143, 136, 137,
-	138, 72, 73, 74, 75, 0, 0, 130, 0, 0,
-	412, 131, 0, 0, 84, 0, 33, 32, 83, 34,
-	35, 36, 37, 38, 140, 40, 41, 42, 43, 134,
-	133, 132, 47, 48, 49, 50, 51, 52, 53, 54,
-	55, 56, 57, 58, 59, 60, 61, 62, 141, 145,
-	139, 66, 67, 143, 136, 137, 138, 72, 73, 74,
-	75, 0, 0, 130, 0, 0, 400, 131, 0, 0,
-	84, 0, 33, 32, 83, 34, 35, 36, 37, 38,
-	140, 40, 41, 42, 43, 134, 133, 132, 47, 48,
-	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 62, 141, 145, 139, 66, 67, 143,
-	136, 137, 138, 72, 73, 74, 75, 0, 0, 130,
-	0, 0, 399, 131, 0, 0, 84, 0, 33, 32,
-	83, 34, 35, 36, 37, 38, 140, 40, 41, 42,
-	43, 134, 133, 132, 47, 48, 49, 50, 51, 52,
-	53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
-	141, 145, 139, 66, 67, 143, 136, 137, 138, 72,
-	73, 74, 75, 0, 0, 130, 0, 0, 398, 302,
-	0, 0, 84, 0, 33, 32, 83, 34, 35, 36,
-	37, 38, 140, 40, 41, 42, 43, 44, 45, 46,
-	47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
-	57, 58, 59, 60, 61, 304, 63, 64, 65, 66,
-	67, 68, 69, 70, 71, 72, 73, 74, 75, 0,
-	0, 301, 0, 0, 342, 162, 0, 0, 84, 0,
-	33, 32, 83, 34, 35, 36, 37, 38, 39, 40,
-	41, 42, 43, 134, 133, 132, 47, 48, 49, 50,
-	51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
-	61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
-	71, 72, 73, 74, 75, 0, 0, 161, 0, 0,
-	216, 131, 0, 0, 84, 0, 33, 32, 83, 34,
-	35, 36, 37, 38, 140, 40, 41, 42, 43, 134,
-	133, 132, 47, 48, 49, 50, 51, 52, 53, 54,
-	55, 56, 57, 58, 59, 60, 61, 62, 141, 145,
-	139, 66, 67, 143, 136, 137, 138, 72, 73, 74,
-	75, 0, 0, 130, 0, 0, 188, 131, 0, 0,
-	84, 0, 33, 32, 83, 34, 35, 36, 37, 38,
-	140, 40, 41, 42, 43, 134, 133, 132, 47, 48,
-	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 62, 141, 145, 139, 66, 67, 143,
-	136, 137, 138, 72, 73, 74, 75, 0, 0, 130,
-	0, 0, 302, 0, 0, 0, 84, 33, 32, 83,
-	34, 35, 36, 37, 38, 140, 40, 41, 42, 43,
-	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
-	54, 55, 56, 57, 58, 59, 60, 61, 304, 63,
-	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
-	74, 75, 0, 0, 301, 0, 0, 162, 0, 0,
-	0, 84, 33, 32, 83, 34, 35, 36, 37, 38,
-	39, 40, 41, 42, 43, 134, 133, 132, 47, 48,
-	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
-	69, 70, 71, 72, 73, 74, 75, 0, 0, 161,
-	0, 0, 0, 0, 0, 0, 84, 33, 32, 83,
+	68, 69, 70, 71, 72, 73, 74, 0, 0, 0,
+	0, 110, 0, 0, 0, 0, 0, 0, 0, 272,
+	112, 113, 0, 0, 270, 29, 111, 114, 32, 33,
 	34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
 	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
 	54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
-	319, 75, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 84, 33, 32, 83, 34, 35, 36, 37, 38,
-	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
-	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
-	69, 70, 71, 72, 73, 74, 75, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 84, 33, 32, 83,
+	74, 0, 0, 0, 0, 110, 0, 0, 0, 0,
+	0, 0, 0, 372, 112, 113, 29, 111, 114, 32,
+	33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+	53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+	63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+	73, 74, 0, 0, 0, 0, 110, 0, 0, 0,
+	0, 0, 171, 0, 370, 112, 113, 32, 33, 34,
+	35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+	45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+	55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+	65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 397, 0, 171, 0, 0, 0, 174, 32, 33,
 	34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
 	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
-	54, 55, 56, 57, 58, 59, 60, 61, 196, 63,
+	54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
-	74, 75, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 84, 33, 32, 83, 34, 35, 36, 37, 38,
+	74, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 395, 0, 171, 0, 0, 0, 174, 32,
+	33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+	53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+	63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+	73, 74, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 373, 0, 0, 0, 0, 0, 174,
+	29, 111, 114, 32, 33, 34, 35, 36, 37, 38,
 	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
 	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 194, 63, 64, 65, 66, 67, 68,
-	69, 70, 71, 72, 73, 74, 75, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 84, 33, 32, 83,
-	34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
-	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
-	54, 55, 56, 57, 58, 59, 60, 61, 192, 63,
-	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
-	74, 75, 0, 0, 0, 0, 0, 0, 0, 0,
-	33, 84, 96, 34, 35, 36, 37, 38, 39, 40,
+	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+	69, 70, 71, 72, 73, 74, 0, 0, 0, 0,
+	110, 0, 0, 0, 0, 0, 171, 0, 0, 112,
+	113, 32, 33, 34, 35, 36, 37, 38, 39, 40,
 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
 	51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
 	61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
-	71, 72, 73, 74, 75, 0, 0, 152, 0, 0,
-	0, 0, 33, 0, 97, 34, 35, 36, 37, 38,
-	140, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+	71, 72, 73, 74, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 350, 0, 171, 0, 0,
+	0, 174, 32, 33, 34, 35, 36, 37, 38, 39,
+	40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+	50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+	60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+	70, 71, 72, 73, 74, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 319, 0, 171, 0,
+	0, 0, 174, 32, 33, 34, 35, 36, 37, 38,
+	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
 	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
-	59, 60, 61, 62, 63, 64, 65, 66, 67, 154,
-	69, 70, 71, 72, 73, 74, 75, 0, 152, 151,
-	0, 0, 207, 33, 0, 0, 34, 35, 36, 37,
-	38, 140, 40, 41, 42, 43, 44, 45, 46, 47,
-	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	154, 69, 70, 71, 72, 73, 74, 75, 233, 0,
-	151, 0, 0, 33, 32, 0, 34, 35, 36, 37,
+	59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+	69, 70, 71, 72, 73, 74, 0, 0, 0, 0,
+	0, 221, 0, 0, 0, 0, 0, 0, 0, 387,
+	0, 0, 0, 174, 32, 33, 34, 35, 36, 37,
 	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
 	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	68, 69, 70, 71, 72, 73, 74, 75, 33, 32,
-	0, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+	68, 69, 70, 71, 72, 73, 74, 252, 253, 254,
+	255, 256, 257, 258, 259, 260, 261, 262, 263, 0,
+	385, 0, 0, 0, 174, 32, 33, 34, 35, 36,
+	37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+	47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+	57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+	67, 68, 69, 70, 71, 72, 73, 74, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 349, 0, 0, 0, 174, 32, 33, 34, 35,
+	36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+	46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+	56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+	66, 67, 68, 69, 70, 71, 72, 73, 74, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 318, 0, 0, 0, 174, 32, 33, 34,
+	35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+	45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+	55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+	65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 274, 0, 0, 0, 174, 32, 33,
+	34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+	54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+	74, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 171, 0, 0, 0, 174, 32,
+	33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
 	43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
 	53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
 	63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
-	73, 74, 75, 33, 0, 0, 34, 35, 36, 37,
+	73, 74, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 174,
+	32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+	72, 73, 74, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 77, 32,
+	33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+	53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+	63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+	73, 74, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 129, 0, 0, 0, 233, 32, 33,
+	34, 35, 36, 37, 138, 39, 40, 41, 42, 132,
+	131, 130, 46, 47, 48, 49, 50, 51, 52, 53,
+	54, 55, 56, 57, 58, 59, 60, 61, 139, 143,
+	137, 65, 66, 141, 134, 135, 136, 71, 72, 73,
+	74, 0, 0, 128, 0, 0, 402, 129, 0, 0,
+	82, 0, 32, 33, 34, 35, 36, 37, 138, 39,
+	40, 41, 42, 132, 131, 130, 46, 47, 48, 49,
+	50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+	60, 61, 139, 143, 137, 65, 66, 141, 134, 135,
+	136, 71, 72, 73, 74, 0, 0, 128, 0, 0,
+	390, 129, 0, 0, 82, 0, 32, 33, 34, 35,
+	36, 37, 138, 39, 40, 41, 42, 132, 131, 130,
+	46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+	56, 57, 58, 59, 60, 61, 139, 143, 137, 65,
+	66, 141, 134, 135, 136, 71, 72, 73, 74, 0,
+	0, 128, 0, 0, 389, 129, 0, 0, 82, 0,
+	32, 33, 34, 35, 36, 37, 138, 39, 40, 41,
+	42, 132, 131, 130, 46, 47, 48, 49, 50, 51,
+	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+	139, 143, 137, 65, 66, 141, 134, 135, 136, 71,
+	72, 73, 74, 0, 0, 128, 0, 0, 388, 298,
+	0, 0, 82, 0, 32, 33, 34, 35, 36, 37,
+	138, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+	58, 59, 60, 300, 62, 63, 64, 65, 66, 67,
+	68, 69, 70, 71, 72, 73, 74, 0, 0, 297,
+	0, 0, 333, 159, 0, 0, 82, 0, 32, 33,
+	34, 35, 36, 37, 38, 39, 40, 41, 42, 132,
+	131, 130, 46, 47, 48, 49, 50, 51, 52, 53,
+	54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+	64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+	74, 0, 0, 158, 0, 0, 214, 129, 0, 0,
+	82, 0, 32, 33, 34, 35, 36, 37, 138, 39,
+	40, 41, 42, 132, 131, 130, 46, 47, 48, 49,
+	50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+	60, 61, 139, 143, 137, 65, 66, 141, 134, 135,
+	136, 71, 72, 73, 74, 0, 0, 128, 0, 0,
+	185, 129, 0, 0, 82, 0, 32, 33, 34, 35,
+	36, 37, 138, 39, 40, 41, 42, 132, 131, 130,
+	46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+	56, 57, 58, 59, 60, 61, 139, 143, 137, 65,
+	66, 141, 134, 135, 136, 71, 72, 73, 74, 0,
+	0, 128, 0, 0, 298, 0, 0, 0, 82, 32,
+	33, 34, 35, 36, 37, 138, 39, 40, 41, 42,
+	43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+	53, 54, 55, 56, 57, 58, 59, 60, 300, 62,
+	63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+	73, 74, 0, 0, 297, 0, 0, 159, 0, 0,
+	0, 82, 32, 33, 34, 35, 36, 37, 38, 39,
+	40, 41, 42, 132, 131, 130, 46, 47, 48, 49,
+	50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+	60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+	70, 71, 72, 73, 74, 0, 0, 158, 0, 0,
+	231, 0, 0, 0, 82, 32, 33, 34, 35, 36,
+	37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+	47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+	57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+	67, 68, 69, 70, 71, 72, 73, 74, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 82, 32, 33,
+	34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+	44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+	54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+	64, 65, 66, 67, 68, 69, 70, 71, 72, 310,
+	74, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	82, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+	41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+	51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+	61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+	71, 72, 73, 74, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 82, 32, 33, 34, 35, 36, 37,
 	38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
 	58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
-	68, 69, 70, 71, 72, 73, 74, 75,
+	68, 69, 70, 71, 72, 73, 74, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 184, 32, 33, 34,
+	35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+	45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+	55, 56, 57, 58, 59, 60, 193, 62, 63, 64,
+	65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 82,
+	32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+	52, 53, 54, 55, 56, 57, 58, 59, 60, 191,
+	62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+	72, 73, 74, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 82, 32, 33, 34, 35, 36, 37, 38,
+	39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+	49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+	59, 60, 189, 62, 63, 64, 65, 66, 67, 68,
+	69, 70, 71, 72, 73, 74, 0, 0, 0, 0,
+	0, 150, 0, 0, 0, 82, 32, 33, 34, 35,
+	36, 37, 138, 39, 40, 41, 42, 43, 44, 45,
+	46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+	56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+	66, 152, 68, 69, 70, 71, 72, 73, 74, 0,
+	150, 149, 0, 0, 204, 32, 33, 34, 35, 36,
+	37, 138, 39, 40, 41, 42, 43, 44, 45, 46,
+	47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+	57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
+	152, 68, 69, 70, 71, 72, 73, 74, 0, 0,
+	149, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+	41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+	51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+	61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+	71, 72, 73, 74,
 }
 var protoPact = [...]int{
 
-	198, -1000, 172, 172, 227, -1000, -1000, -1000, -1000, -1000,
-	-1000, -1000, -1000, -1000, 183, 288, 2541, 1452, 2586, 2586,
-	2125, 2586, 172, -1000, 350, -1000, 212, 350, 350, -1000,
-	182, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-	-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+	162, -1000, 224, 224, 202, -1000, -1000, -1000, -1000, -1000,
+	-1000, -1000, -1000, -1000, 166, 319, 2584, 1463, 2584, 2584,
+	2224, 2584, 224, -1000, 315, -1000, 191, 315, 315, -1000,
+	68, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
 	-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
 	-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-	-1000, -1000, -1000, -1000, -1000, -1000, 226, -1000, 2125, 75,
-	68, 112, -1000, -1000, 2541, 62, 200, -1000, -1000, 195,
-	156, -1000, 855, 54, 1905, 2446, -1000, 2541, 2015, -1000,
-	175, -1000, -1000, -1000, 181, -1000, -1000, 345, -1000, -1000,
-	-1000, -1000, 1392, -1000, 332, 327, -1000, 80, 1849, -1000,
 	-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-	-1000, 180, 2290, 2235, 2180, 2343, 2586, 2586, 2125, 341,
-	1452, 2586, 2586, 310, -1000, 18, 2395, -1000, -1000, -1000,
-	-1000, -1000, 179, 221, 73, -1000, -1000, 1793, -1000, -1000,
-	-1000, -1000, 177, 213, -1000, -1000, -1000, -1000, 173, 2586,
-	-1000, 1032, -1000, 102, 101, 28, -1000, 2496, -1000, -1000,
-	-1000, -1000, -1000, -1000, -1000, 80, -1000, 14, -1000, -1000,
-	-1000, 2343, 2586, 2343, 2586, 2343, 2586, 220, -13, -1000,
-	244, 61, 218, 100, 46, 345, 1419, -1000, -1000, -1000,
-	86, 32, -1000, 241, 239, 343, -1000, -1000, -1000, -1000,
-	-1000, -1000, 13, -1000, -1000, -1000, -1000, -1000, -1000, 486,
-	-1000, 1332, -6, -9, -1000, 2125, 216, 215, 211, 210,
-	202, 189, 342, -1000, 171, 341, 1452, 277, 1960, 338,
-	-1000, -1000, 350, 23, -1000, -1000, -1000, -1000, -1000, -1000,
-	-1000, -1000, -1000, -1000, -1000, -1000, 6, 5, 74, -1000,
-	246, 66, 2070, -1000, 419, -1000, 1272, 972, 95, -1000,
-	-1000, 27, 336, 335, 334, 325, 323, 318, 4, -1000,
-	-1000, -24, -1000, 187, -1000, -1000, 1737, -1000, -1000, -1000,
-	-1000, -1000, 168, 2343, 2586, 3, 345, 2125, -1000, 167,
-	-1000, 157, -1000, -1000, -1000, -1000, -1000, -1000, -1, 2125,
-	59, -1000, -17, -36, -1000, 1212, 912, 71, -1000, -1000,
-	-1000, 1, 58, 0, 48, -4, 45, -1000, 152, -1000,
-	1452, 855, -1000, -1000, -1000, 186, 185, -1000, 148, 90,
-	-1000, -1000, 214, 59, -1000, 615, 552, -1000, 795, 65,
-	-1000, -1000, -1000, 125, 1905, -1000, 122, 1905, -1000, 115,
-	1905, -1000, -1000, -1000, 313, 292, -1000, -1000, 9, -1000,
-	1152, -1000, 1092, -1000, -1000, -1000, 1681, -1000, 1625, -1000,
-	1569, -7, 31, 2070, 735, 49, 675, 44, -1000, -1000,
-	-1000, -1000, 81, 1905, -2, -1000, -1000, -1000, -1000, -1000,
-	1513, 105, -1000, -1000, 169, 199, -1000, -1000, -1000, 51,
+	-1000, -1000, -1000, -1000, -1000, 201, 27, 2224, 97, 95,
+	94, 27, 2584, 89, 182, -1000, -1000, 175, 152, -1000,
+	2584, 856, 8, 1959, 2538, 2065, 27, 150, -1000, -1000,
+	-1000, -1000, 164, -1000, -1000, 312, -1000, -1000, -1000, -1000,
+	1402, -1000, 308, 306, -1000, 2277, 1905, -1000, -1000, -1000,
+	-1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 163,
+	2436, 2383, 2330, 2584, 2584, 2584, 2224, 299, 1463, 2584,
+	2584, 256, -1000, 20, 2489, -1000, -1000, -1000, -1000, -1000,
+	161, 199, 67, -1000, 1851, -1000, -1000, -1000, -1000, 158,
+	170, -1000, -1000, -1000, -1000, 148, 2584, -1000, 1036, -1000,
+	90, 87, 26, -1000, 2118, -1000, -1000, -1000, -1000, -1000,
+	-1000, -1000, 2277, -1000, 1522, -1000, -1000, -1000, 2584, 2584,
+	2584, 2584, 2584, 2584, 198, -12, -1000, 217, 79, 196,
+	78, 69, 312, 1124, -1000, -1000, -1000, 73, 45, -1000,
+	216, -1000, -1000, 305, -1000, -1000, -1000, -1000, -1000, -1000,
+	12, -1000, -1000, -1000, -1000, -1000, -1000, 487, -1000, 1341,
+	-3, -4, -1000, 2224, 195, 193, 189, 188, 184, 181,
+	302, -1000, 146, 299, 1463, 237, 2012, 294, -1000, -1000,
+	315, 24, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
+	-1000, -1000, -1000, -1000, 9, 73, -1000, 62, 2171, -1000,
+	422, -1000, 1280, 975, 55, -1000, -1000, 4, 286, 283,
+	275, 272, 261, 260, 6, -1000, -1000, -21, -1000, 180,
+	-1000, -1000, 1797, -1000, -1000, -1000, -1000, -1000, 106, 2584,
+	2584, 1, 312, 2224, -1000, 105, -1000, -1000, -1000, 3,
+	2224, -1000, -1000, -14, -8, -1000, 1219, 914, 52, -1000,
+	-1000, -1000, -10, 64, -11, 60, -15, 47, -1000, 103,
+	-1000, 1463, 856, -1000, -1000, -1000, 178, 168, -1000, 102,
+	22, -1000, 172, -1000, -1000, 612, 551, -1000, 792, 48,
+	-1000, -1000, -1000, 101, 1959, -1000, 80, 1959, -1000, 71,
+	1959, -1000, -1000, -1000, 259, 258, -1000, -1000, 10, -1000,
+	1158, -1000, 1097, -1000, -1000, -1000, 1743, -1000, 1689, -1000,
+	1635, -16, 44, 2171, 731, 33, 670, 29, -1000, -1000,
+	-1000, -1000, 50, 1959, 0, -1000, -1000, -1000, -1000, -1000,
+	1581, 65, -1000, -1000, 207, 186, -1000, -1000, -1000, 35,
 	-1000, -1000, -1000,
 }
 var protoPgo = [...]int{
 
-	0, 414, 413, 312, 358, 412, 411, 1, 12, 408,
-	3, 403, 10, 21, 401, 28, 13, 18, 29, 0,
-	25, 11, 400, 399, 30, 393, 392, 391, 26, 9,
-	390, 31, 389, 388, 17, 387, 386, 385, 321, 7,
-	6, 14, 384, 382, 380, 379, 33, 15, 44, 16,
-	378, 376, 306, 35, 375, 373, 290, 40, 372, 23,
-	367, 27, 365, 363, 8,
+	0, 397, 392, 302, 331, 391, 390, 1, 11, 389,
+	3, 383, 9, 18, 382, 43, 32, 17, 23, 381,
+	380, 16, 15, 0, 377, 27, 28, 376, 375, 25,
+	8, 372, 29, 369, 363, 26, 362, 360, 358, 351,
+	7, 6, 12, 356, 353, 350, 348, 33, 14, 31,
+	13, 344, 340, 292, 35, 338, 337, 286, 30, 336,
+	34, 335, 21, 327, 320, 10,
 }
 var protoR1 = [...]int{
 
 	0, 1, 1, 1, 1, 4, 4, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 2, 5, 5,
-	5, 6, 20, 20, 7, 12, 12, 12, 13, 13,
-	14, 14, 16, 16, 17, 17, 17, 17, 17, 25,
-	25, 24, 26, 26, 26, 26, 26, 59, 59, 18,
-	28, 28, 28, 29, 29, 29, 29, 29, 29, 30,
-	30, 30, 30, 30, 30, 30, 30, 30, 30, 23,
-	23, 23, 27, 27, 27, 27, 27, 27, 27, 27,
-	27, 21, 21, 21, 21, 21, 31, 31, 31, 31,
-	31, 31, 31, 31, 15, 9, 9, 8, 34, 34,
-	34, 33, 42, 42, 42, 41, 41, 41, 41, 41,
-	41, 32, 32, 35, 36, 36, 37, 22, 22, 22,
-	22, 22, 22, 22, 22, 22, 22, 22, 22, 51,
-	51, 48, 48, 47, 47, 47, 50, 50, 49, 49,
-	49, 49, 49, 49, 49, 44, 44, 45, 45, 46,
-	43, 43, 52, 54, 54, 54, 53, 53, 53, 53,
-	53, 53, 55, 55, 55, 55, 38, 40, 40, 40,
-	39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
-	39, 39, 39, 56, 58, 58, 58, 57, 57, 57,
-	57, 57, 60, 62, 62, 62, 61, 61, 61, 61,
-	61, 63, 63, 64, 64, 11, 11, 11, 10, 10,
-	10, 10, 19, 19, 19, 19, 19, 19, 19, 19,
-	19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-	19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-	19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-	19, 19, 19, 19, 19,
+	5, 6, 25, 25, 7, 12, 12, 12, 13, 13,
+	14, 14, 16, 16, 17, 17, 17, 17, 17, 19,
+	19, 22, 21, 21, 20, 20, 20, 20, 20, 60,
+	60, 18, 29, 29, 29, 30, 30, 30, 30, 30,
+	30, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+	31, 27, 27, 27, 28, 28, 28, 28, 28, 28,
+	28, 28, 28, 26, 26, 32, 32, 32, 32, 32,
+	32, 32, 32, 15, 9, 9, 8, 35, 35, 35,
+	34, 43, 43, 43, 42, 42, 42, 42, 42, 42,
+	33, 33, 36, 37, 37, 38, 24, 24, 24, 24,
+	24, 24, 24, 24, 24, 24, 24, 24, 52, 52,
+	49, 49, 48, 48, 48, 51, 51, 50, 50, 50,
+	45, 45, 46, 46, 47, 44, 44, 53, 55, 55,
+	55, 54, 54, 54, 54, 54, 54, 56, 56, 39,
+	41, 41, 41, 40, 40, 40, 40, 40, 40, 40,
+	40, 40, 40, 40, 40, 40, 57, 59, 59, 59,
+	58, 58, 58, 58, 58, 61, 63, 63, 63, 62,
+	62, 62, 62, 62, 64, 64, 65, 65, 11, 11,
+	11, 10, 10, 10, 10, 23, 23, 23, 23, 23,
+	23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	23, 23, 23, 23, 23, 23, 23, 23,
 }
 var protoR2 = [...]int{
 
 	0, 1, 1, 2, 0, 2, 1, 1, 1, 1,
 	1, 1, 1, 1, 1, 2, 1, 4, 3, 4,
-	4, 3, 1, 1, 5, 1, 3, 4, 1, 2,
+	4, 3, 1, 3, 5, 1, 3, 4, 1, 2,
 	1, 4, 1, 1, 1, 1, 1, 1, 1, 1,
-	2, 2, 1, 2, 2, 2, 2, 1, 2, 3,
-	1, 2, 0, 1, 2, 2, 2, 2, 1, 3,
-	4, 5, 5, 3, 2, 5, 4, 5, 4, 1,
-	3, 3, 1, 3, 3, 3, 5, 5, 3, 5,
-	5, 1, 1, 2, 2, 3, 6, 6, 6, 5,
-	7, 7, 7, 6, 3, 3, 1, 3, 8, 8,
-	8, 5, 2, 1, 0, 1, 1, 1, 1, 2,
-	1, 5, 6, 7, 5, 6, 6, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
-	4, 3, 1, 1, 3, 3, 3, 1, 1, 1,
-	3, 3, 3, 3, 3, 3, 1, 3, 1, 3,
-	3, 1, 5, 2, 1, 0, 1, 1, 1, 1,
-	2, 1, 4, 5, 4, 5, 5, 2, 1, 0,
+	2, 2, 1, 1, 1, 2, 2, 2, 2, 1,
+	2, 3, 1, 2, 0, 1, 2, 2, 2, 2,
+	1, 3, 4, 5, 5, 3, 2, 5, 4, 5,
+	4, 1, 3, 3, 1, 3, 3, 3, 5, 5,
+	3, 5, 5, 1, 2, 6, 6, 6, 5, 7,
+	7, 7, 6, 3, 3, 1, 3, 8, 8, 8,
+	5, 2, 1, 0, 1, 1, 1, 1, 2, 1,
+	5, 6, 7, 5, 6, 6, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 3, 4,
+	3, 1, 1, 3, 3, 3, 1, 1, 3, 3,
+	3, 1, 3, 1, 3, 3, 1, 5, 2, 1,
+	0, 1, 1, 1, 1, 2, 1, 4, 5, 5,
+	2, 1, 0, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 2, 1, 5, 2, 1, 0,
+	1, 1, 1, 2, 1, 5, 2, 1, 0, 1,
+	1, 1, 2, 1, 10, 12, 2, 1, 2, 1,
+	0, 1, 1, 2, 1, 1, 1, 1, 1, 1,
 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-	1, 2, 1, 5, 2, 1, 0, 1, 1, 1,
-	2, 1, 5, 2, 1, 0, 1, 1, 1, 2,
-	1, 10, 12, 2, 1, 2, 1, 0, 1, 1,
-	2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-	1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
 }
 var protoChk = [...]int{
 
-	-1000, -1, -2, -4, 10, -3, -5, -6, -7, -38,
-	-52, -56, -60, 54, 2, 11, 14, 15, 46, 45,
-	47, 48, -4, -3, 53, 54, -59, 12, 13, 4,
-	-20, -19, 8, 7, 10, 11, 12, 13, 14, 15,
-	16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
-	26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
-	36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
-	46, 47, 48, 49, 50, 51, -12, -20, 67, -19,
-	-19, -21, -20, 9, 61, -19, -59, 54, 4, -59,
-	-59, 54, 53, -21, 56, 56, 9, 61, 56, -20,
-	56, 54, 54, 54, -16, -17, -18, -59, -25, -24,
-	-26, -19, 56, 5, 65, 66, 6, 68, -40, -39,
-	-31, -52, -38, -56, -51, -34, -7, -33, -36, -44,
-	54, 2, 22, 21, 20, -21, 45, 46, 47, 41,
-	15, 39, -37, 44, -46, 40, -54, -53, -7, -55,
-	-45, 54, 2, -19, 44, -46, -20, -58, -57, -31,
-	-34, 54, 2, -62, -61, -7, -63, 54, 2, 49,
-	54, -28, -29, -30, 2, -23, -19, 69, 5, 6,
-	18, 5, 6, 18, -13, -14, 9, 61, 57, -39,
-	54, -21, 38, -21, 38, -21, 38, -19, -48, -47,
-	5, -19, -19, -48, -43, -59, 64, 57, -53, 54,
-	53, -50, -49, 5, -24, 66, 57, -57, 54, 57,
-	-61, 54, -19, 57, -29, 62, 54, 62, 54, 55,
-	-18, 64, -20, 2, -13, 67, -19, -19, -19, -19,
-	-19, -19, 53, 54, -15, 62, 69, 42, 56, 53,
-	54, 54, 62, -22, 25, 26, 27, 28, 29, 30,
-	31, 32, 33, 34, 35, 36, 5, -24, 62, 54,
-	42, 42, 67, -17, 69, -18, 64, -28, 2, 70,
-	70, -21, 53, 53, 53, 53, 53, 53, 5, 54,
-	-47, -9, -8, -12, 5, 43, -42, -41, -7, -32,
-	-35, 54, 2, -21, 38, 5, -59, 62, 54, -15,
-	54, -15, -49, 5, 43, -24, 5, 43, -64, 50,
-	-21, 70, -27, 2, -16, 64, -28, 2, 63, 63,
-	68, 5, 5, 5, 5, 5, 5, 54, -15, 70,
-	62, 53, 57, -41, 54, -19, -19, 54, -15, -21,
-	54, 54, 68, -21, 70, 62, 54, 70, -28, 2,
-	63, 63, 54, -15, 56, 54, -15, 56, 54, -15,
-	56, 54, -8, -16, 53, 53, 54, 63, 51, -16,
-	64, -16, 64, 63, 63, 54, -40, 54, -40, 54,
-	-40, 5, 5, 67, -28, 2, -28, 2, 57, 57,
-	57, 54, -15, 56, -64, 63, 63, 63, 63, 54,
-	-40, 68, 57, 54, 56, -11, -10, -7, 54, 2,
-	57, -10, 54,
+	-1000, -1, -2, -4, 8, -3, -5, -6, -7, -39,
+	-53, -57, -61, 52, 2, 9, 12, 13, 44, 43,
+	45, 46, -4, -3, 51, 52, -60, 10, 11, 4,
+	-25, -23, 7, 8, 9, 10, 11, 12, 13, 14,
+	15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+	25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+	35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+	45, 46, 47, 48, 49, -12, -25, 65, -23, -23,
+	-26, -25, 59, -23, -60, 52, 4, -60, -60, 52,
+	59, 51, -26, 54, 54, 54, -25, 54, 52, 52,
+	52, -23, -16, -17, -18, -60, -19, -22, -20, -23,
+	54, 5, 63, 64, 6, 66, -41, -40, -32, -53,
+	-39, -57, -52, -35, -7, -34, -37, -45, 52, 2,
+	20, 19, 18, -26, 43, 44, 45, 39, 13, 37,
+	-38, 42, -47, 38, -55, -54, -7, -56, -46, 52,
+	2, -23, 42, -47, -59, -58, -32, -35, 52, 2,
+	-63, -62, -7, -64, 52, 2, 47, 52, -29, -30,
+	-31, 2, -27, -23, 67, 5, 6, 16, 5, 6,
+	16, -13, -14, -26, 59, 55, -40, 52, -26, 36,
+	-26, 36, -26, 36, -23, -49, -48, 5, -23, -23,
+	-49, -44, -60, 62, 55, -54, 52, 51, -51, -50,
+	-21, -22, 5, 64, 55, -58, 52, 55, -62, 52,
+	-23, 55, -30, 60, 52, 60, 52, 53, -18, 62,
+	-26, 2, -13, 65, -23, -23, -23, -23, -23, -23,
+	51, 52, -15, 60, 67, 40, 54, 51, 52, 52,
+	60, -24, 23, 24, 25, 26, 27, 28, 29, 30,
+	31, 32, 33, 34, -21, 60, 52, 40, 65, -17,
+	67, -18, 62, -29, 2, 68, 68, -26, 51, 51,
+	51, 51, 51, 51, 5, 52, -48, -9, -8, -12,
+	5, 41, -43, -42, -7, -33, -36, 52, 2, -26,
+	36, 5, -60, 60, 52, -15, -50, -21, 41, -65,
+	48, -26, 68, -28, 2, -16, 62, -29, 2, 61,
+	61, 66, 5, 5, 5, 5, 5, 5, 52, -15,
+	68, 60, 51, 55, -42, 52, -23, -23, 52, -15,
+	-26, 52, 66, -26, 68, 60, 52, 68, -29, 2,
+	61, 61, 52, -15, 54, 52, -15, 54, 52, -15,
+	54, 52, -8, -16, 51, 51, 52, 61, 49, -16,
+	62, -16, 62, 61, 61, 52, -41, 52, -41, 52,
+	-41, 5, 5, 65, -29, 2, -29, 2, 55, 55,
+	55, 52, -15, 54, -65, 61, 61, 61, 61, 52,
+	-41, 66, 55, 52, 54, -11, -10, -7, 52, 2,
+	55, -10, 52,
 }
 var protoDef = [...]int{
 
 	-2, -2, -2, -2, 0, 6, 7, 8, 9, 10,
 	11, 12, 13, 14, 16, 0, 0, 0, 0, 0,
-	0, 0, -2, 5, 0, 15, 0, 0, 0, 47,
-	0, 22, 23, 212, 213, 214, 215, 216, 217, 218,
-	219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
-	229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
-	239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
-	249, 250, 251, 252, 253, 254, 0, 25, 0, 0,
-	0, 0, 81, 82, 0, 0, 0, 18, 48, 0,
-	0, 21, 0, 0, -2, -2, 84, 0, -2, 83,
-	-2, 17, 19, 20, 0, 32, 33, 34, 35, 36,
-	37, 38, -2, 39, 0, 0, 42, 26, 0, 168,
-	170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
-	180, 182, 0, 0, 0, 0, 248, 249, 0, 244,
-	218, 242, 0, 247, 146, 243, 0, 154, 156, 157,
-	158, 159, 161, 0, 247, 148, 85, 0, 185, 187,
-	188, 189, 191, 0, 194, 196, 197, 198, 200, 0,
-	24, 0, 50, 53, 58, 0, 69, 0, 40, 44,
-	45, 41, 43, 46, 27, 28, 30, 0, 166, 167,
-	181, 0, 241, 0, 241, 0, 241, 0, 0, 132,
-	133, 0, 0, 0, 0, 151, 0, 152, 153, 160,
-	0, 0, 137, 138, 139, 0, 183, 184, 190, 192,
-	193, 199, 0, 49, 51, 54, 55, 56, 57, 0,
-	64, -2, 0, 0, 29, 0, 0, 0, 0, 0,
-	0, 0, 0, 129, 0, 0, 0, 0, -2, 0,
-	145, 149, 0, 0, 117, 118, 119, 120, 121, 122,
-	123, 124, 125, 126, 127, 128, 0, 0, 0, 147,
-	0, 0, 0, 59, 0, 63, -2, 0, 58, 70,
-	71, 0, 0, 0, 0, 0, 0, 0, 0, 130,
-	131, 0, 96, 0, 134, 135, 0, 103, 105, 106,
-	107, 108, 110, 0, 241, 0, 150, 0, 162, 0,
-	164, 0, 136, 140, 143, 141, 142, 144, 0, 253,
-	204, 60, 0, 0, 72, -2, 0, 58, 66, 68,
-	31, 0, 0, 0, 0, 0, 0, 89, 0, 94,
-	0, 0, 101, 102, 109, 0, 0, 114, 0, 0,
-	163, 165, 0, 203, 61, 0, 0, 62, 0, 58,
-	65, 67, 86, 0, -2, 87, 0, -2, 88, 0,
-	-2, 93, 95, 97, 0, 0, 115, 116, 0, 73,
-	-2, 74, -2, 75, 78, 90, 0, 91, 0, 92,
-	0, 0, 0, 0, 0, 58, 0, 58, 98, 99,
-	100, 111, 0, -2, 0, 76, 79, 77, 80, 112,
-	0, 0, 113, 201, -2, 0, 206, 208, 209, 211,
-	202, 205, 210,
+	0, 0, -2, 5, 0, 15, 0, 0, 0, 49,
+	0, 22, 205, 206, 207, 208, 209, 210, 211, 212,
+	213, 214, 215, 216, 217, 218, 219, 220, 221, 222,
+	223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
+	233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
+	243, 244, 245, 246, 247, 0, 25, 0, 0, 0,
+	0, 83, 0, 0, 0, 18, 50, 0, 0, 21,
+	0, 0, 0, -2, -2, -2, 84, -2, 17, 19,
+	20, 23, 0, 32, 33, 34, 35, 36, 37, 38,
+	-2, 39, 0, 0, 44, 26, 0, 161, 163, 164,
+	165, 166, 167, 168, 169, 170, 171, 172, 173, 175,
+	0, 0, 0, 0, 241, 242, 0, 237, 211, 235,
+	0, 240, 141, 236, 0, 149, 151, 152, 153, 154,
+	156, 0, 240, 143, 0, 178, 180, 181, 182, 184,
+	0, 187, 189, 190, 191, 193, 0, 24, 0, 52,
+	55, 60, 0, 71, 0, 40, 46, 47, 41, 45,
+	48, 27, 28, 30, 0, 159, 160, 174, 0, 234,
+	0, 234, 0, 234, 0, 0, 131, 132, 0, 0,
+	0, 0, 146, 0, 147, 148, 155, 0, 0, 136,
+	137, 42, 43, 0, 176, 177, 183, 185, 186, 192,
+	0, 51, 53, 56, 57, 58, 59, 0, 66, -2,
+	0, 0, 29, 0, 0, 0, 0, 0, 0, 0,
+	0, 128, 0, 0, 0, 0, -2, 0, 140, 144,
+	0, 0, 116, 117, 118, 119, 120, 121, 122, 123,
+	124, 125, 126, 127, 0, 0, 142, 0, 0, 61,
+	0, 65, -2, 0, 60, 72, 73, 0, 0, 0,
+	0, 0, 0, 0, 0, 129, 130, 0, 95, 0,
+	133, 134, 0, 102, 104, 105, 106, 107, 109, 0,
+	234, 0, 145, 0, 157, 0, 135, 138, 139, 0,
+	246, 197, 62, 0, 0, 74, -2, 0, 60, 68,
+	70, 31, 0, 0, 0, 0, 0, 0, 88, 0,
+	93, 0, 0, 100, 101, 108, 0, 0, 113, 0,
+	0, 158, 0, 196, 63, 0, 0, 64, 0, 60,
+	67, 69, 85, 0, -2, 86, 0, -2, 87, 0,
+	-2, 92, 94, 96, 0, 0, 114, 115, 0, 75,
+	-2, 76, -2, 77, 80, 89, 0, 90, 0, 91,
+	0, 0, 0, 0, 0, 60, 0, 60, 97, 98,
+	99, 110, 0, -2, 0, 78, 81, 79, 82, 111,
+	0, 0, 112, 194, -2, 0, 199, 201, 202, 204,
+	195, 198, 203,
 }
 var protoTok1 = [...]int{
 
 	1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 78, 3, 76, 75, 74, 72, 3,
-	67, 68, 71, 65, 62, 66, 61, 59, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3, 55, 54,
-	64, 53, 63, 60, 77, 3, 3, 3, 3, 3,
+	3, 3, 3, 76, 3, 74, 73, 72, 70, 3,
+	65, 66, 69, 63, 60, 64, 59, 57, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 53, 52,
+	62, 51, 61, 58, 75, 3, 3, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 69, 58, 70, 73, 3, 80, 3, 3, 3,
+	3, 67, 56, 68, 71, 3, 78, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
 	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 56, 3, 57, 79,
+	3, 3, 3, 54, 3, 55, 77,
 }
 var protoTok2 = [...]int{
 
@@ -768,8 +761,7 @@ var protoTok2 = [...]int{
 	12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
 	22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
-	52,
+	42, 43, 44, 45, 46, 47, 48, 49, 50,
 }
 var protoTok3 = [...]int{
 	0,
@@ -1114,7 +1106,7 @@ protodefault:
 
 	case 1:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:118
+//line proto.y:119
 		{
 			protoVAL.file = &fileNode{syntax: protoDollar[1].syn}
 			protoVAL.file.setRange(protoDollar[1].syn, protoDollar[1].syn)
@@ -1122,7 +1114,7 @@ protodefault:
 		}
 	case 2:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:123
+//line proto.y:124
 		{
 			protoVAL.file = &fileNode{decls: protoDollar[1].fileDecls}
 			if len(protoDollar[1].fileDecls) > 0 {
@@ -1132,7 +1124,7 @@ protodefault:
 		}
 	case 3:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:130
+//line proto.y:131
 		{
 			protoVAL.file = &fileNode{syntax: protoDollar[1].syn, decls: protoDollar[2].fileDecls}
 			var end node
@@ -1146,76 +1138,76 @@ protodefault:
 		}
 	case 4:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:141
+//line proto.y:142
 		{
 		}
 	case 5:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:144
+//line proto.y:145
 		{
 			protoVAL.fileDecls = append(protoDollar[1].fileDecls, protoDollar[2].fileDecls...)
 		}
 	case 7:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:149
+//line proto.y:150
 		{
 			protoVAL.fileDecls = []*fileElement{{imp: protoDollar[1].imprt}}
 		}
 	case 8:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:152
+//line proto.y:153
 		{
 			protoVAL.fileDecls = []*fileElement{{pkg: protoDollar[1].pkg}}
 		}
 	case 9:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:155
+//line proto.y:156
 		{
 			protoVAL.fileDecls = []*fileElement{{option: protoDollar[1].opts[0]}}
 		}
 	case 10:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:158
+//line proto.y:159
 		{
 			protoVAL.fileDecls = []*fileElement{{message: protoDollar[1].msg}}
 		}
 	case 11:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:161
+//line proto.y:162
 		{
 			protoVAL.fileDecls = []*fileElement{{enum: protoDollar[1].en}}
 		}
 	case 12:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:164
+//line proto.y:165
 		{
 			protoVAL.fileDecls = []*fileElement{{extend: protoDollar[1].extend}}
 		}
 	case 13:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:167
+//line proto.y:168
 		{
 			protoVAL.fileDecls = []*fileElement{{service: protoDollar[1].svc}}
 		}
 	case 14:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:170
+//line proto.y:171
 		{
 			protoVAL.fileDecls = []*fileElement{{empty: protoDollar[1].b}}
 		}
 	case 15:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:173
+//line proto.y:174
 		{
 		}
 	case 16:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:175
+//line proto.y:176
 		{
 		}
 	case 17:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:178
+//line proto.y:179
 		{
 			if protoDollar[3].str.val != "proto2" && protoDollar[3].str.val != "proto3" {
 				lexError(protolex, protoDollar[3].str.start(), "syntax value must be 'proto2' or 'proto3'")
@@ -1225,35 +1217,49 @@ protodefault:
 		}
 	case 18:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:186
+//line proto.y:187
 		{
 			protoVAL.imprt = &importNode{name: protoDollar[2].str}
 			protoVAL.imprt.setRange(protoDollar[1].id, protoDollar[3].b)
 		}
 	case 19:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:190
+//line proto.y:191
 		{
 			protoVAL.imprt = &importNode{name: protoDollar[3].str, weak: true}
 			protoVAL.imprt.setRange(protoDollar[1].id, protoDollar[4].b)
 		}
 	case 20:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:194
+//line proto.y:195
 		{
 			protoVAL.imprt = &importNode{name: protoDollar[3].str, public: true}
 			protoVAL.imprt.setRange(protoDollar[1].id, protoDollar[4].b)
 		}
 	case 21:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:199
+//line proto.y:200
 		{
-			protoVAL.pkg = &packageNode{name: protoDollar[2].id}
+			protoVAL.pkg = &packageNode{name: protoDollar[2].cid}
 			protoVAL.pkg.setRange(protoDollar[1].id, protoDollar[3].b)
 		}
+	case 22:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:205
+		{
+			protoVAL.cid = &compoundIdentNode{val: protoDollar[1].id.val}
+			protoVAL.cid.setRange(protoDollar[1].id, protoDollar[1].id)
+		}
+	case 23:
+		protoDollar = protoS[protopt-3 : protopt+1]
+//line proto.y:209
+		{
+			protoVAL.cid = &compoundIdentNode{val: protoDollar[1].cid.val + "." + protoDollar[3].id.val}
+			protoVAL.cid.setRange(protoDollar[1].cid, protoDollar[3].id)
+		}
 	case 24:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:207
+//line proto.y:214
 		{
 			n := &optionNameNode{parts: protoDollar[2].optNm}
 			n.setRange(protoDollar[2].optNm[0], protoDollar[2].optNm[len(protoDollar[2].optNm)-1])
@@ -1263,23 +1269,23 @@ protodefault:
 		}
 	case 25:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:215
+//line proto.y:222
 		{
-			protoVAL.optNm = toNameParts(protoDollar[1].id, 0)
+			protoVAL.optNm = toNameParts(protoDollar[1].cid, 0)
 		}
 	case 26:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:218
+//line proto.y:225
 		{
-			p := &optionNamePartNode{text: protoDollar[2].id, isExtension: true}
+			p := &optionNamePartNode{text: protoDollar[2].cid, isExtension: true}
 			p.setRange(protoDollar[1].b, protoDollar[3].b)
 			protoVAL.optNm = []*optionNamePartNode{p}
 		}
 	case 27:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:223
+//line proto.y:230
 		{
-			p := &optionNamePartNode{text: protoDollar[2].id, isExtension: true}
+			p := &optionNamePartNode{text: protoDollar[2].cid, isExtension: true}
 			p.setRange(protoDollar[1].b, protoDollar[3].b)
 			ps := make([]*optionNamePartNode, 1, len(protoDollar[4].optNm)+1)
 			ps[0] = p
@@ -1287,177 +1293,203 @@ protodefault:
 		}
 	case 29:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:232
+//line proto.y:239
 		{
 			protoVAL.optNm = append(protoDollar[1].optNm, protoDollar[2].optNm...)
 		}
 	case 30:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:236
+//line proto.y:243
 		{
-			protoVAL.optNm = toNameParts(protoDollar[1].id, 1 /* exclude leading dot */)
+			protoVAL.optNm = toNameParts(protoDollar[1].cid, 1 /* exclude leading dot */)
 		}
 	case 31:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:239
+//line proto.y:246
 		{
-			p := &optionNamePartNode{text: protoDollar[3].id, isExtension: true}
+			p := &optionNamePartNode{text: protoDollar[3].cid, isExtension: true}
 			p.setRange(protoDollar[2].b, protoDollar[4].b)
 			protoVAL.optNm = []*optionNamePartNode{p}
 		}
 	case 34:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:248
+//line proto.y:255
 		{
 			protoVAL.v = protoDollar[1].str
 		}
-	case 35:
-		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:251
-		{
-			protoVAL.v = protoDollar[1].ui
-		}
 	case 36:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:254
+//line proto.y:259
 		{
-			protoVAL.v = protoDollar[1].i
-		}
-	case 37:
-		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:257
-		{
-			protoVAL.v = protoDollar[1].f
+			protoVAL.v = protoDollar[1].il
 		}
 	case 38:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:260
+//line proto.y:263
 		{
 			if protoDollar[1].id.val == "true" {
 				protoVAL.v = &boolLiteralNode{identNode: protoDollar[1].id, val: true}
 			} else if protoDollar[1].id.val == "false" {
 				protoVAL.v = &boolLiteralNode{identNode: protoDollar[1].id, val: false}
 			} else if protoDollar[1].id.val == "inf" {
-				f := &floatLiteralNode{val: math.Inf(1)}
+				f := &compoundFloatNode{val: math.Inf(1)}
 				f.setRange(protoDollar[1].id, protoDollar[1].id)
 				protoVAL.v = f
 			} else if protoDollar[1].id.val == "nan" {
-				f := &floatLiteralNode{val: math.NaN()}
+				f := &compoundFloatNode{val: math.NaN()}
 				f.setRange(protoDollar[1].id, protoDollar[1].id)
 				protoVAL.v = f
 			} else {
 				protoVAL.v = protoDollar[1].id
 			}
 		}
+	case 39:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:281
+		{
+			i := &compoundUintNode{val: protoDollar[1].i.val}
+			i.setRange(protoDollar[1].i, protoDollar[1].i)
+			protoVAL.v = i
+		}
 	case 40:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:279
+//line proto.y:286
 		{
-			protoVAL.ui = protoDollar[2].ui
+			i := &compoundUintNode{val: protoDollar[2].i.val}
+			i.setRange(protoDollar[1].b, protoDollar[2].i)
+			protoVAL.v = i
 		}
 	case 41:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:283
+//line proto.y:292
 		{
-			if protoDollar[2].ui.val > math.MaxInt64+1 {
-				lexError(protolex, protoDollar[2].ui.start(), fmt.Sprintf("numeric constant %d would underflow (allowed range is %d to %d)", protoDollar[2].ui.val, int64(math.MinInt64), int64(math.MaxInt64)))
+			if protoDollar[2].i.val > math.MaxInt64+1 {
+				lexError(protolex, protoDollar[2].i.start(), fmt.Sprintf("numeric constant %d would underflow (allowed range is %d to %d)", protoDollar[2].i.val, int64(math.MinInt64), int64(math.MaxInt64)))
 			}
-			protoVAL.i = &negativeIntLiteralNode{val: -int64(protoDollar[2].ui.val)}
-			protoVAL.i.setRange(protoDollar[1].b, protoDollar[2].ui)
+			i := &compoundIntNode{val: -int64(protoDollar[2].i.val)}
+			i.setRange(protoDollar[1].b, protoDollar[2].i)
+			protoVAL.il = i
 		}
 	case 43:
-		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:292
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:302
 		{
-			protoVAL.f = &floatLiteralNode{val: -protoDollar[2].f.val}
-			protoVAL.f.setRange(protoDollar[1].b, protoDollar[2].f)
+			// we don't allow uintLit because this is for enum numeric vals, which don't allow '+'
+			checkUint64InInt32Range(protolex, protoDollar[1].i.start(), protoDollar[1].i.val)
+			i := &compoundIntNode{val: int64(protoDollar[1].i.val)}
+			i.setRange(protoDollar[1].i, protoDollar[1].i)
+			protoVAL.il = i
 		}
 	case 44:
-		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:296
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:310
 		{
-			protoVAL.f = &floatLiteralNode{val: protoDollar[2].f.val}
-			protoVAL.f.setRange(protoDollar[1].b, protoDollar[2].f)
+			protoVAL.v = protoDollar[1].f
 		}
 	case 45:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:300
+//line proto.y:313
 		{
-			protoVAL.f = &floatLiteralNode{val: math.Inf(1)}
-			protoVAL.f.setRange(protoDollar[1].b, protoDollar[2].id)
+			f := &compoundFloatNode{val: -protoDollar[2].f.val}
+			f.setRange(protoDollar[1].b, protoDollar[2].f)
+			protoVAL.v = f
 		}
 	case 46:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:304
+//line proto.y:318
+		{
+			f := &compoundFloatNode{val: protoDollar[2].f.val}
+			f.setRange(protoDollar[1].b, protoDollar[2].f)
+			protoVAL.v = f
+		}
+	case 47:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:323
 		{
-			protoVAL.f = &floatLiteralNode{val: math.Inf(-1)}
-			protoVAL.f.setRange(protoDollar[1].b, protoDollar[2].id)
+			f := &compoundFloatNode{val: math.Inf(1)}
+			f.setRange(protoDollar[1].b, protoDollar[2].id)
+			protoVAL.v = f
 		}
 	case 48:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:310
+//line proto.y:328
 		{
-			protoVAL.str = &stringLiteralNode{val: protoDollar[1].str.val + protoDollar[2].str.val}
-			protoVAL.str.setRange(protoDollar[1].str, protoDollar[2].str)
+			f := &compoundFloatNode{val: math.Inf(-1)}
+			f.setRange(protoDollar[1].b, protoDollar[2].id)
+			protoVAL.v = f
 		}
 	case 49:
+		protoDollar = protoS[protopt-1 : protopt+1]
+//line proto.y:334
+		{
+			protoVAL.str = &compoundStringNode{val: protoDollar[1].s.val}
+			protoVAL.str.setRange(protoDollar[1].s, protoDollar[1].s)
+		}
+	case 50:
+		protoDollar = protoS[protopt-2 : protopt+1]
+//line proto.y:338
+		{
+			protoVAL.str = &compoundStringNode{val: protoDollar[1].str.val + protoDollar[2].s.val}
+			protoVAL.str.setRange(protoDollar[1].str, protoDollar[2].s)
+		}
+	case 51:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:315
+//line proto.y:343
 		{
 			a := &aggregateLiteralNode{elements: protoDollar[2].agg}
 			a.setRange(protoDollar[1].b, protoDollar[3].b)
 			protoVAL.v = a
 		}
-	case 51:
+	case 53:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:322
+//line proto.y:350
 		{
 			protoVAL.agg = append(protoDollar[1].agg, protoDollar[2].agg...)
 		}
-	case 52:
+	case 54:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:325
+//line proto.y:353
 		{
 			protoVAL.agg = nil
 		}
-	case 54:
+	case 56:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:330
+//line proto.y:358
 		{
 			protoVAL.agg = protoDollar[1].agg
 		}
-	case 55:
+	case 57:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:333
+//line proto.y:361
 		{
 			protoVAL.agg = protoDollar[1].agg
 		}
-	case 56:
+	case 58:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:336
+//line proto.y:364
 		{
 		}
-	case 57:
+	case 59:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:338
+//line proto.y:366
 		{
 		}
-	case 58:
+	case 60:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:340
+//line proto.y:368
 		{
 		}
-	case 59:
+	case 61:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:343
+//line proto.y:371
 		{
 			a := &aggregateEntryNode{name: protoDollar[1].aggName, val: protoDollar[3].v}
 			a.setRange(protoDollar[1].aggName, protoDollar[3].v)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 60:
+	case 62:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:348
+//line proto.y:376
 		{
 			s := &sliceLiteralNode{}
 			s.setRange(protoDollar[3].b, protoDollar[4].b)
@@ -1465,9 +1497,9 @@ protodefault:
 			a.setRange(protoDollar[1].aggName, protoDollar[4].b)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 61:
+	case 63:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:355
+//line proto.y:383
 		{
 			s := &sliceLiteralNode{elements: protoDollar[4].sl}
 			s.setRange(protoDollar[3].b, protoDollar[5].b)
@@ -1475,30 +1507,30 @@ protodefault:
 			a.setRange(protoDollar[1].aggName, protoDollar[5].b)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 62:
+	case 64:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:362
+//line proto.y:390
 		{
 		}
-	case 63:
+	case 65:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:364
+//line proto.y:392
 		{
 			a := &aggregateEntryNode{name: protoDollar[1].aggName, val: protoDollar[3].v}
 			a.setRange(protoDollar[1].aggName, protoDollar[3].v)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 64:
+	case 66:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:369
+//line proto.y:397
 		{
 			a := &aggregateEntryNode{name: protoDollar[1].aggName, val: protoDollar[2].v}
 			a.setRange(protoDollar[1].aggName, protoDollar[2].v)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 65:
+	case 67:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:374
+//line proto.y:402
 		{
 			s := &aggregateLiteralNode{elements: protoDollar[4].agg}
 			s.setRange(protoDollar[3].b, protoDollar[5].b)
@@ -1506,9 +1538,9 @@ protodefault:
 			a.setRange(protoDollar[1].aggName, protoDollar[5].b)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 66:
+	case 68:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:381
+//line proto.y:409
 		{
 			s := &aggregateLiteralNode{elements: protoDollar[3].agg}
 			s.setRange(protoDollar[2].b, protoDollar[4].b)
@@ -1516,199 +1548,187 @@ protodefault:
 			a.setRange(protoDollar[1].aggName, protoDollar[4].b)
 			protoVAL.agg = []*aggregateEntryNode{a}
 		}
-	case 67:
+	case 69:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:388
+//line proto.y:416
 		{
 		}
-	case 68:
+	case 70:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:390
+//line proto.y:418
 		{
 		}
-	case 69:
+	case 71:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:393
+//line proto.y:421
 		{
-			protoVAL.aggName = &aggregateNameNode{name: protoDollar[1].id}
+			n := &compoundIdentNode{val: protoDollar[1].id.val}
+			n.setRange(protoDollar[1].id, protoDollar[1].id)
+			protoVAL.aggName = &aggregateNameNode{name: n}
 			protoVAL.aggName.setRange(protoDollar[1].id, protoDollar[1].id)
 		}
-	case 70:
+	case 72:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:397
+//line proto.y:427
 		{
-			protoVAL.aggName = &aggregateNameNode{name: protoDollar[2].id, isExtension: true}
+			protoVAL.aggName = &aggregateNameNode{name: protoDollar[2].cid, isExtension: true}
 			protoVAL.aggName.setRange(protoDollar[1].b, protoDollar[3].b)
 		}
-	case 71:
+	case 73:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:401
+//line proto.y:431
 		{
 		}
-	case 72:
+	case 74:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:404
+//line proto.y:434
 		{
 			protoVAL.sl = []valueNode{protoDollar[1].v}
 		}
-	case 73:
+	case 75:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:407
+//line proto.y:437
 		{
 			protoVAL.sl = append(protoDollar[1].sl, protoDollar[3].v)
 		}
-	case 74:
+	case 76:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:410
+//line proto.y:440
 		{
 			protoVAL.sl = append(protoDollar[1].sl, protoDollar[3].v)
 		}
-	case 75:
+	case 77:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:413
+//line proto.y:443
 		{
 			s := &aggregateLiteralNode{elements: protoDollar[2].agg}
 			s.setRange(protoDollar[1].b, protoDollar[3].b)
 			protoVAL.sl = []valueNode{s}
 		}
-	case 76:
+	case 78:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:418
+//line proto.y:448
 		{
 			s := &aggregateLiteralNode{elements: protoDollar[4].agg}
 			s.setRange(protoDollar[3].b, protoDollar[5].b)
 			protoVAL.sl = append(protoDollar[1].sl, s)
 		}
-	case 77:
+	case 79:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:423
+//line proto.y:453
 		{
 			s := &aggregateLiteralNode{elements: protoDollar[4].agg}
 			s.setRange(protoDollar[3].b, protoDollar[5].b)
 			protoVAL.sl = append(protoDollar[1].sl, s)
 		}
-	case 78:
+	case 80:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:428
+//line proto.y:458
 		{
 		}
-	case 79:
+	case 81:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:430
+//line proto.y:460
 		{
 		}
-	case 80:
+	case 82:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:432
-		{
-		}
-	case 83:
-		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:437
+//line proto.y:462
 		{
-			protoVAL.id = &identNode{val: "." + protoDollar[2].id.val}
-			protoVAL.id.setRange(protoDollar[1].b, protoDollar[2].id)
 		}
 	case 84:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:441
+//line proto.y:466
 		{
-			protoVAL.id = &identNode{val: protoDollar[1].id.val + protoDollar[2].id.val}
-			protoVAL.id.setRange(protoDollar[1].id, protoDollar[2].id)
+			protoVAL.cid = &compoundIdentNode{val: "." + protoDollar[2].cid.val}
+			protoVAL.cid.setRange(protoDollar[1].b, protoDollar[2].cid)
 		}
 	case 85:
-		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:445
+		protoDollar = protoS[protopt-6 : protopt+1]
+//line proto.y:471
 		{
-			protoVAL.id = &identNode{val: protoDollar[1].id.val + "." + protoDollar[3].id.val}
-			protoVAL.id.setRange(protoDollar[1].id, protoDollar[3].id)
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
+			lbl := fieldLabel{identNode: protoDollar[1].id, required: true}
+			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].cid, name: protoDollar[3].id, tag: protoDollar[5].i}
+			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[6].b)
 		}
 	case 86:
 		protoDollar = protoS[protopt-6 : protopt+1]
-//line proto.y:450
+//line proto.y:477
 		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
-			lbl := &labelNode{identNode: protoDollar[1].id, required: true}
-			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].id, name: protoDollar[3].id, tag: protoDollar[5].ui}
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
+			lbl := fieldLabel{identNode: protoDollar[1].id}
+			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].cid, name: protoDollar[3].id, tag: protoDollar[5].i}
 			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[6].b)
 		}
 	case 87:
 		protoDollar = protoS[protopt-6 : protopt+1]
-//line proto.y:456
+//line proto.y:483
 		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
-			lbl := &labelNode{identNode: protoDollar[1].id}
-			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].id, name: protoDollar[3].id, tag: protoDollar[5].ui}
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
+			lbl := fieldLabel{identNode: protoDollar[1].id, repeated: true}
+			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].cid, name: protoDollar[3].id, tag: protoDollar[5].i}
 			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[6].b)
 		}
 	case 88:
-		protoDollar = protoS[protopt-6 : protopt+1]
-//line proto.y:462
+		protoDollar = protoS[protopt-5 : protopt+1]
+//line proto.y:489
 		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
-			lbl := &labelNode{identNode: protoDollar[1].id, repeated: true}
-			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].id, name: protoDollar[3].id, tag: protoDollar[5].ui}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[6].b)
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			protoVAL.fld = &fieldNode{fldType: protoDollar[1].cid, name: protoDollar[2].id, tag: protoDollar[4].i}
+			protoVAL.fld.setRange(protoDollar[1].cid, protoDollar[5].b)
 		}
 	case 89:
-		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:468
+		protoDollar = protoS[protopt-7 : protopt+1]
+//line proto.y:494
 		{
-			checkTag(protolex, protoDollar[4].ui.start(), protoDollar[4].ui.val)
-			protoVAL.fld = &fieldNode{fldType: protoDollar[1].id, name: protoDollar[2].id, tag: protoDollar[4].ui}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[5].b)
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
+			lbl := fieldLabel{identNode: protoDollar[1].id, required: true}
+			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].cid, name: protoDollar[3].id, tag: protoDollar[5].i, options: protoDollar[6].cmpctOpts}
+			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[7].b)
 		}
 	case 90:
 		protoDollar = protoS[protopt-7 : protopt+1]
-//line proto.y:473
+//line proto.y:500
 		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
-			lbl := &labelNode{identNode: protoDollar[1].id, required: true}
-			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].id, name: protoDollar[3].id, tag: protoDollar[5].ui, options: protoDollar[6].cmpctOpts}
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
+			lbl := fieldLabel{identNode: protoDollar[1].id}
+			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].cid, name: protoDollar[3].id, tag: protoDollar[5].i, options: protoDollar[6].cmpctOpts}
 			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[7].b)
 		}
 	case 91:
 		protoDollar = protoS[protopt-7 : protopt+1]
-//line proto.y:479
+//line proto.y:506
 		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
-			lbl := &labelNode{identNode: protoDollar[1].id}
-			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].id, name: protoDollar[3].id, tag: protoDollar[5].ui, options: protoDollar[6].cmpctOpts}
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
+			lbl := fieldLabel{identNode: protoDollar[1].id, repeated: true}
+			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].cid, name: protoDollar[3].id, tag: protoDollar[5].i, options: protoDollar[6].cmpctOpts}
 			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[7].b)
 		}
 	case 92:
-		protoDollar = protoS[protopt-7 : protopt+1]
-//line proto.y:485
-		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
-			lbl := &labelNode{identNode: protoDollar[1].id, repeated: true}
-			protoVAL.fld = &fieldNode{label: lbl, fldType: protoDollar[2].id, name: protoDollar[3].id, tag: protoDollar[5].ui, options: protoDollar[6].cmpctOpts}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[7].b)
-		}
-	case 93:
 		protoDollar = protoS[protopt-6 : protopt+1]
-//line proto.y:491
+//line proto.y:512
 		{
-			checkTag(protolex, protoDollar[4].ui.start(), protoDollar[4].ui.val)
-			protoVAL.fld = &fieldNode{fldType: protoDollar[1].id, name: protoDollar[2].id, tag: protoDollar[4].ui, options: protoDollar[5].cmpctOpts}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[6].b)
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			protoVAL.fld = &fieldNode{fldType: protoDollar[1].cid, name: protoDollar[2].id, tag: protoDollar[4].i, options: protoDollar[5].cmpctOpts}
+			protoVAL.fld.setRange(protoDollar[1].cid, protoDollar[6].b)
 		}
-	case 94:
+	case 93:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:497
+//line proto.y:518
 		{
 			protoVAL.cmpctOpts = &compactOptionsNode{decls: protoDollar[2].opts}
 			protoVAL.cmpctOpts.setRange(protoDollar[1].b, protoDollar[3].b)
 		}
-	case 95:
+	case 94:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:502
+//line proto.y:523
 		{
 			protoVAL.opts = append(protoDollar[1].opts, protoDollar[3].opts...)
 		}
-	case 97:
+	case 96:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:507
+//line proto.y:528
 		{
 			n := &optionNameNode{parts: protoDollar[1].optNm}
 			n.setRange(protoDollar[1].optNm[0], protoDollar[1].optNm[len(protoDollar[1].optNm)-1])
@@ -1716,45 +1736,45 @@ protodefault:
 			o.setRange(protoDollar[1].optNm[0], protoDollar[3].v)
 			protoVAL.opts = []*optionNode{o}
 		}
-	case 98:
+	case 97:
 		protoDollar = protoS[protopt-8 : protopt+1]
-//line proto.y:515
+//line proto.y:536
 		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
 			if !unicode.IsUpper(rune(protoDollar[3].id.val[0])) {
 				lexError(protolex, protoDollar[3].id.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", protoDollar[3].id.val))
 			}
-			lbl := &labelNode{identNode: protoDollar[1].id, required: true}
-			protoVAL.grp = &groupNode{groupKeyword: protoDollar[2].id, label: lbl, name: protoDollar[3].id, tag: protoDollar[5].ui, decls: protoDollar[7].msgDecls}
+			lbl := fieldLabel{identNode: protoDollar[1].id, required: true}
+			protoVAL.grp = &groupNode{groupKeyword: protoDollar[2].id, label: lbl, name: protoDollar[3].id, tag: protoDollar[5].i, decls: protoDollar[7].msgDecls}
 			protoVAL.grp.setRange(protoDollar[1].id, protoDollar[8].b)
 		}
-	case 99:
+	case 98:
 		protoDollar = protoS[protopt-8 : protopt+1]
-//line proto.y:524
+//line proto.y:545
 		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
 			if !unicode.IsUpper(rune(protoDollar[3].id.val[0])) {
 				lexError(protolex, protoDollar[3].id.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", protoDollar[3].id.val))
 			}
-			lbl := &labelNode{identNode: protoDollar[1].id}
-			protoVAL.grp = &groupNode{groupKeyword: protoDollar[2].id, label: lbl, name: protoDollar[3].id, tag: protoDollar[5].ui, decls: protoDollar[7].msgDecls}
+			lbl := fieldLabel{identNode: protoDollar[1].id}
+			protoVAL.grp = &groupNode{groupKeyword: protoDollar[2].id, label: lbl, name: protoDollar[3].id, tag: protoDollar[5].i, decls: protoDollar[7].msgDecls}
 			protoVAL.grp.setRange(protoDollar[1].id, protoDollar[8].b)
 		}
-	case 100:
+	case 99:
 		protoDollar = protoS[protopt-8 : protopt+1]
-//line proto.y:533
+//line proto.y:554
 		{
-			checkTag(protolex, protoDollar[5].ui.start(), protoDollar[5].ui.val)
+			checkTag(protolex, protoDollar[5].i.start(), protoDollar[5].i.val)
 			if !unicode.IsUpper(rune(protoDollar[3].id.val[0])) {
 				lexError(protolex, protoDollar[3].id.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", protoDollar[3].id.val))
 			}
-			lbl := &labelNode{identNode: protoDollar[1].id, repeated: true}
-			protoVAL.grp = &groupNode{groupKeyword: protoDollar[2].id, label: lbl, name: protoDollar[3].id, tag: protoDollar[5].ui, decls: protoDollar[7].msgDecls}
+			lbl := fieldLabel{identNode: protoDollar[1].id, repeated: true}
+			protoVAL.grp = &groupNode{groupKeyword: protoDollar[2].id, label: lbl, name: protoDollar[3].id, tag: protoDollar[5].i, decls: protoDollar[7].msgDecls}
 			protoVAL.grp.setRange(protoDollar[1].id, protoDollar[8].b)
 		}
-	case 101:
+	case 100:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:543
+//line proto.y:564
 		{
 			c := 0
 			for _, el := range protoDollar[4].ooDecls {
@@ -1768,256 +1788,215 @@ protodefault:
 			protoVAL.oo = &oneOfNode{name: protoDollar[2].id, decls: protoDollar[4].ooDecls}
 			protoVAL.oo.setRange(protoDollar[1].id, protoDollar[5].b)
 		}
-	case 102:
+	case 101:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:557
+//line proto.y:578
 		{
 			protoVAL.ooDecls = append(protoDollar[1].ooDecls, protoDollar[2].ooDecls...)
 		}
-	case 104:
+	case 103:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:561
+//line proto.y:582
 		{
 			protoVAL.ooDecls = nil
 		}
-	case 105:
+	case 104:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:565
+//line proto.y:586
 		{
 			protoVAL.ooDecls = []*oneOfElement{{option: protoDollar[1].opts[0]}}
 		}
-	case 106:
+	case 105:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:568
+//line proto.y:589
 		{
 			protoVAL.ooDecls = []*oneOfElement{{field: protoDollar[1].fld}}
 		}
-	case 107:
+	case 106:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:571
+//line proto.y:592
 		{
 			protoVAL.ooDecls = []*oneOfElement{{group: protoDollar[1].grp}}
 		}
-	case 108:
+	case 107:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:574
+//line proto.y:595
 		{
 			protoVAL.ooDecls = []*oneOfElement{{empty: protoDollar[1].b}}
 		}
-	case 109:
+	case 108:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:577
+//line proto.y:598
 		{
 		}
-	case 110:
+	case 109:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:579
+//line proto.y:600
 		{
 		}
-	case 111:
+	case 110:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:582
+//line proto.y:603
 		{
-			checkTag(protolex, protoDollar[4].ui.start(), protoDollar[4].ui.val)
-			protoVAL.fld = &fieldNode{fldType: protoDollar[1].id, name: protoDollar[2].id, tag: protoDollar[4].ui}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[5].b)
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			protoVAL.fld = &fieldNode{fldType: protoDollar[1].cid, name: protoDollar[2].id, tag: protoDollar[4].i}
+			protoVAL.fld.setRange(protoDollar[1].cid, protoDollar[5].b)
 		}
-	case 112:
+	case 111:
 		protoDollar = protoS[protopt-6 : protopt+1]
-//line proto.y:587
+//line proto.y:608
 		{
-			checkTag(protolex, protoDollar[4].ui.start(), protoDollar[4].ui.val)
-			protoVAL.fld = &fieldNode{fldType: protoDollar[1].id, name: protoDollar[2].id, tag: protoDollar[4].ui, options: protoDollar[5].cmpctOpts}
-			protoVAL.fld.setRange(protoDollar[1].id, protoDollar[6].b)
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			protoVAL.fld = &fieldNode{fldType: protoDollar[1].cid, name: protoDollar[2].id, tag: protoDollar[4].i, options: protoDollar[5].cmpctOpts}
+			protoVAL.fld.setRange(protoDollar[1].cid, protoDollar[6].b)
 		}
-	case 113:
+	case 112:
 		protoDollar = protoS[protopt-7 : protopt+1]
-//line proto.y:593
+//line proto.y:614
 		{
-			checkTag(protolex, protoDollar[4].ui.start(), protoDollar[4].ui.val)
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
 			if !unicode.IsUpper(rune(protoDollar[2].id.val[0])) {
 				lexError(protolex, protoDollar[2].id.start(), fmt.Sprintf("group %s should have a name that starts with a capital letter", protoDollar[2].id.val))
 			}
-			protoVAL.grp = &groupNode{groupKeyword: protoDollar[1].id, name: protoDollar[2].id, tag: protoDollar[4].ui, decls: protoDollar[6].msgDecls}
+			protoVAL.grp = &groupNode{groupKeyword: protoDollar[1].id, name: protoDollar[2].id, tag: protoDollar[4].i, decls: protoDollar[6].msgDecls}
 			protoVAL.grp.setRange(protoDollar[1].id, protoDollar[7].b)
 		}
-	case 114:
+	case 113:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:602
+//line proto.y:623
 		{
-			checkTag(protolex, protoDollar[4].ui.start(), protoDollar[4].ui.val)
-			protoVAL.mapFld = &mapFieldNode{mapType: protoDollar[1].mapType, name: protoDollar[2].id, tag: protoDollar[4].ui}
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			protoVAL.mapFld = &mapFieldNode{mapType: protoDollar[1].mapType, name: protoDollar[2].id, tag: protoDollar[4].i}
 			protoVAL.mapFld.setRange(protoDollar[1].mapType, protoDollar[5].b)
 		}
-	case 115:
+	case 114:
 		protoDollar = protoS[protopt-6 : protopt+1]
-//line proto.y:607
+//line proto.y:628
 		{
-			checkTag(protolex, protoDollar[4].ui.start(), protoDollar[4].ui.val)
-			protoVAL.mapFld = &mapFieldNode{mapType: protoDollar[1].mapType, name: protoDollar[2].id, tag: protoDollar[4].ui, options: protoDollar[5].cmpctOpts}
+			checkTag(protolex, protoDollar[4].i.start(), protoDollar[4].i.val)
+			protoVAL.mapFld = &mapFieldNode{mapType: protoDollar[1].mapType, name: protoDollar[2].id, tag: protoDollar[4].i, options: protoDollar[5].cmpctOpts}
 			protoVAL.mapFld.setRange(protoDollar[1].mapType, protoDollar[6].b)
 		}
-	case 116:
+	case 115:
 		protoDollar = protoS[protopt-6 : protopt+1]
-//line proto.y:613
+//line proto.y:634
 		{
-			protoVAL.mapType = &mapTypeNode{mapKeyword: protoDollar[1].id, keyType: protoDollar[3].id, valueType: protoDollar[5].id}
+			protoVAL.mapType = &mapTypeNode{mapKeyword: protoDollar[1].id, keyType: protoDollar[3].id, valueType: protoDollar[5].cid}
 			protoVAL.mapType.setRange(protoDollar[1].id, protoDollar[6].b)
 		}
-	case 129:
+	case 128:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:631
+//line proto.y:652
 		{
 			protoVAL.ext = &extensionRangeNode{ranges: protoDollar[2].rngs}
 			protoVAL.ext.setRange(protoDollar[1].id, protoDollar[3].b)
 		}
-	case 130:
+	case 129:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:635
+//line proto.y:656
 		{
 			protoVAL.ext = &extensionRangeNode{ranges: protoDollar[2].rngs, options: protoDollar[3].cmpctOpts}
 			protoVAL.ext.setRange(protoDollar[1].id, protoDollar[4].b)
 		}
-	case 131:
+	case 130:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:640
+//line proto.y:661
 		{
 			protoVAL.rngs = append(protoDollar[1].rngs, protoDollar[3].rngs...)
 		}
-	case 133:
+	case 132:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:645
+//line proto.y:666
 		{
-			if protoDollar[1].ui.val > internal.MaxTag {
-				lexError(protolex, protoDollar[1].ui.start(), fmt.Sprintf("range includes out-of-range tag: %d (should be between 0 and %d)", protoDollar[1].ui.val, internal.MaxTag))
+			if protoDollar[1].i.val > internal.MaxTag {
+				lexError(protolex, protoDollar[1].i.start(), fmt.Sprintf("range includes out-of-range tag: %d (should be between 0 and %d)", protoDollar[1].i.val, internal.MaxTag))
 			}
-			r := &rangeNode{stNode: protoDollar[1].ui, enNode: protoDollar[1].ui, st: int32(protoDollar[1].ui.val), en: int32(protoDollar[1].ui.val)}
-			r.setRange(protoDollar[1].ui, protoDollar[1].ui)
+			r := &rangeNode{stNode: protoDollar[1].i, enNode: protoDollar[1].i, st: int32(protoDollar[1].i.val), en: int32(protoDollar[1].i.val)}
+			r.setRange(protoDollar[1].i, protoDollar[1].i)
 			protoVAL.rngs = []*rangeNode{r}
 		}
-	case 134:
+	case 133:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:653
+//line proto.y:674
 		{
-			if protoDollar[1].ui.val > internal.MaxTag {
-				lexError(protolex, protoDollar[1].ui.start(), fmt.Sprintf("range start is out-of-range tag: %d (should be between 0 and %d)", protoDollar[1].ui.val, internal.MaxTag))
+			if protoDollar[1].i.val > internal.MaxTag {
+				lexError(protolex, protoDollar[1].i.start(), fmt.Sprintf("range start is out-of-range tag: %d (should be between 0 and %d)", protoDollar[1].i.val, internal.MaxTag))
 			}
-			if protoDollar[3].ui.val > internal.MaxTag {
-				lexError(protolex, protoDollar[3].ui.start(), fmt.Sprintf("range end is out-of-range tag: %d (should be between 0 and %d)", protoDollar[3].ui.val, internal.MaxTag))
+			if protoDollar[3].i.val > internal.MaxTag {
+				lexError(protolex, protoDollar[3].i.start(), fmt.Sprintf("range end is out-of-range tag: %d (should be between 0 and %d)", protoDollar[3].i.val, internal.MaxTag))
 			}
-			if protoDollar[1].ui.val > protoDollar[3].ui.val {
-				lexError(protolex, protoDollar[1].ui.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", protoDollar[1].ui.val, protoDollar[3].ui.val))
+			if protoDollar[1].i.val > protoDollar[3].i.val {
+				lexError(protolex, protoDollar[1].i.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", protoDollar[1].i.val, protoDollar[3].i.val))
 			}
-			r := &rangeNode{stNode: protoDollar[1].ui, enNode: protoDollar[3].ui, st: int32(protoDollar[1].ui.val), en: int32(protoDollar[3].ui.val)}
-			r.setRange(protoDollar[1].ui, protoDollar[3].ui)
+			r := &rangeNode{stNode: protoDollar[1].i, enNode: protoDollar[3].i, st: int32(protoDollar[1].i.val), en: int32(protoDollar[3].i.val)}
+			r.setRange(protoDollar[1].i, protoDollar[3].i)
 			protoVAL.rngs = []*rangeNode{r}
 		}
-	case 135:
+	case 134:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:667
+//line proto.y:688
 		{
-			if protoDollar[1].ui.val > internal.MaxTag {
-				lexError(protolex, protoDollar[1].ui.start(), fmt.Sprintf("range start is out-of-range tag: %d (should be between 0 and %d)", protoDollar[1].ui.val, internal.MaxTag))
+			if protoDollar[1].i.val > internal.MaxTag {
+				lexError(protolex, protoDollar[1].i.start(), fmt.Sprintf("range start is out-of-range tag: %d (should be between 0 and %d)", protoDollar[1].i.val, internal.MaxTag))
 			}
-			r := &rangeNode{stNode: protoDollar[1].ui, enNode: protoDollar[3].id, st: int32(protoDollar[1].ui.val), en: internal.MaxTag}
-			r.setRange(protoDollar[1].ui, protoDollar[3].id)
+			r := &rangeNode{stNode: protoDollar[1].i, enNode: protoDollar[3].id, st: int32(protoDollar[1].i.val), en: internal.MaxTag}
+			r.setRange(protoDollar[1].i, protoDollar[3].id)
 			protoVAL.rngs = []*rangeNode{r}
 		}
-	case 136:
+	case 135:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:676
+//line proto.y:697
 		{
 			protoVAL.rngs = append(protoDollar[1].rngs, protoDollar[3].rngs...)
 		}
-	case 138:
+	case 137:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:681
+//line proto.y:702
 		{
-			checkUint64InInt32Range(protolex, protoDollar[1].ui.start(), protoDollar[1].ui.val)
-			r := &rangeNode{stNode: protoDollar[1].ui, enNode: protoDollar[1].ui, st: int32(protoDollar[1].ui.val), en: int32(protoDollar[1].ui.val)}
-			r.setRange(protoDollar[1].ui, protoDollar[1].ui)
+			checkInt64InInt32Range(protolex, protoDollar[1].il.start(), protoDollar[1].il.val)
+			r := &rangeNode{stNode: protoDollar[1].il, enNode: protoDollar[1].il, st: int32(protoDollar[1].il.val), en: int32(protoDollar[1].il.val)}
+			r.setRange(protoDollar[1].il, protoDollar[1].il)
 			protoVAL.rngs = []*rangeNode{r}
 		}
-	case 139:
-		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:687
-		{
-			checkInt64InInt32Range(protolex, protoDollar[1].i.start(), protoDollar[1].i.val)
-			r := &rangeNode{stNode: protoDollar[1].i, enNode: protoDollar[1].i, st: int32(protoDollar[1].i.val), en: int32(protoDollar[1].i.val)}
-			r.setRange(protoDollar[1].i, protoDollar[1].i)
-			protoVAL.rngs = []*rangeNode{r}
-		}
-	case 140:
-		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:693
-		{
-			checkUint64InInt32Range(protolex, protoDollar[1].ui.start(), protoDollar[1].ui.val)
-			checkUint64InInt32Range(protolex, protoDollar[3].ui.start(), protoDollar[3].ui.val)
-			if protoDollar[1].ui.val > protoDollar[3].ui.val {
-				lexError(protolex, protoDollar[1].ui.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", protoDollar[1].ui.val, protoDollar[3].ui.val))
-			}
-			r := &rangeNode{stNode: protoDollar[1].ui, enNode: protoDollar[3].ui, st: int32(protoDollar[1].ui.val), en: int32(protoDollar[3].ui.val)}
-			r.setRange(protoDollar[1].ui, protoDollar[3].ui)
-			protoVAL.rngs = []*rangeNode{r}
-		}
-	case 141:
+	case 138:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:703
+//line proto.y:708
 		{
-			checkInt64InInt32Range(protolex, protoDollar[1].i.start(), protoDollar[1].i.val)
-			checkInt64InInt32Range(protolex, protoDollar[3].i.start(), protoDollar[3].i.val)
-			if protoDollar[1].i.val > protoDollar[3].i.val {
-				lexError(protolex, protoDollar[1].i.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", protoDollar[1].i.val, protoDollar[3].i.val))
+			checkInt64InInt32Range(protolex, protoDollar[1].il.start(), protoDollar[1].il.val)
+			checkInt64InInt32Range(protolex, protoDollar[3].il.start(), protoDollar[3].il.val)
+			if protoDollar[1].il.val > protoDollar[3].il.val {
+				lexError(protolex, protoDollar[1].il.start(), fmt.Sprintf("range, %d to %d, is invalid: start must be <= end", protoDollar[1].il.val, protoDollar[3].il.val))
 			}
-			r := &rangeNode{stNode: protoDollar[1].i, enNode: protoDollar[3].i, st: int32(protoDollar[1].i.val), en: int32(protoDollar[3].i.val)}
-			r.setRange(protoDollar[1].i, protoDollar[3].i)
+			r := &rangeNode{stNode: protoDollar[1].il, enNode: protoDollar[3].il, st: int32(protoDollar[1].il.val), en: int32(protoDollar[3].il.val)}
+			r.setRange(protoDollar[1].il, protoDollar[3].il)
 			protoVAL.rngs = []*rangeNode{r}
 		}
-	case 142:
-		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:713
-		{
-			checkInt64InInt32Range(protolex, protoDollar[1].i.start(), protoDollar[1].i.val)
-			checkUint64InInt32Range(protolex, protoDollar[3].ui.start(), protoDollar[3].ui.val)
-			r := &rangeNode{stNode: protoDollar[1].i, enNode: protoDollar[3].ui, st: int32(protoDollar[1].i.val), en: int32(protoDollar[3].ui.val)}
-			r.setRange(protoDollar[1].i, protoDollar[3].ui)
-			protoVAL.rngs = []*rangeNode{r}
-		}
-	case 143:
-		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:720
-		{
-			checkUint64InInt32Range(protolex, protoDollar[1].ui.start(), protoDollar[1].ui.val)
-			r := &rangeNode{stNode: protoDollar[1].ui, enNode: protoDollar[3].id, st: int32(protoDollar[1].ui.val), en: math.MaxInt32}
-			r.setRange(protoDollar[1].ui, protoDollar[3].id)
-			protoVAL.rngs = []*rangeNode{r}
-		}
-	case 144:
+	case 139:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:726
+//line proto.y:718
 		{
-			checkInt64InInt32Range(protolex, protoDollar[1].i.start(), protoDollar[1].i.val)
-			r := &rangeNode{stNode: protoDollar[1].i, enNode: protoDollar[3].id, st: int32(protoDollar[1].i.val), en: math.MaxInt32}
-			r.setRange(protoDollar[1].i, protoDollar[3].id)
+			checkInt64InInt32Range(protolex, protoDollar[1].il.start(), protoDollar[1].il.val)
+			r := &rangeNode{stNode: protoDollar[1].il, enNode: protoDollar[3].id, st: int32(protoDollar[1].il.val), en: math.MaxInt32}
+			r.setRange(protoDollar[1].il, protoDollar[3].id)
 			protoVAL.rngs = []*rangeNode{r}
 		}
-	case 145:
+	case 140:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:733
+//line proto.y:725
 		{
 			protoVAL.resvd = &reservedNode{ranges: protoDollar[2].rngs}
 			protoVAL.resvd.setRange(protoDollar[1].id, protoDollar[3].b)
 		}
-	case 147:
+	case 142:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:739
+//line proto.y:731
 		{
 			protoVAL.resvd = &reservedNode{ranges: protoDollar[2].rngs}
 			protoVAL.resvd.setRange(protoDollar[1].id, protoDollar[3].b)
 		}
-	case 149:
+	case 144:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:745
+//line proto.y:737
 		{
 			rsvd := map[string]struct{}{}
 			for _, n := range protoDollar[2].names {
@@ -2030,21 +2009,21 @@ protodefault:
 			protoVAL.resvd = &reservedNode{names: protoDollar[2].names}
 			protoVAL.resvd.setRange(protoDollar[1].id, protoDollar[3].b)
 		}
-	case 150:
+	case 145:
 		protoDollar = protoS[protopt-3 : protopt+1]
-//line proto.y:758
+//line proto.y:750
 		{
 			protoVAL.names = append(protoDollar[1].names, protoDollar[3].str)
 		}
-	case 151:
+	case 146:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:761
+//line proto.y:753
 		{
-			protoVAL.names = []*stringLiteralNode{protoDollar[1].str}
+			protoVAL.names = []*compoundStringNode{protoDollar[1].str}
 		}
-	case 152:
+	case 147:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:765
+//line proto.y:757
 		{
 			c := 0
 			for _, el := range protoDollar[4].enDecls {
@@ -2058,182 +2037,166 @@ protodefault:
 			protoVAL.en = &enumNode{name: protoDollar[2].id, decls: protoDollar[4].enDecls}
 			protoVAL.en.setRange(protoDollar[1].id, protoDollar[5].b)
 		}
-	case 153:
+	case 148:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:779
+//line proto.y:771
 		{
 			protoVAL.enDecls = append(protoDollar[1].enDecls, protoDollar[2].enDecls...)
 		}
-	case 155:
+	case 150:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:783
+//line proto.y:775
 		{
 			protoVAL.enDecls = nil
 		}
-	case 156:
+	case 151:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:787
+//line proto.y:779
 		{
 			protoVAL.enDecls = []*enumElement{{option: protoDollar[1].opts[0]}}
 		}
-	case 157:
+	case 152:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:790
+//line proto.y:782
 		{
 			protoVAL.enDecls = []*enumElement{{value: protoDollar[1].env}}
 		}
-	case 158:
+	case 153:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:793
+//line proto.y:785
 		{
 			protoVAL.enDecls = []*enumElement{{reserved: protoDollar[1].resvd}}
 		}
-	case 159:
+	case 154:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:796
+//line proto.y:788
 		{
 			protoVAL.enDecls = []*enumElement{{empty: protoDollar[1].b}}
 		}
-	case 160:
+	case 155:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:799
+//line proto.y:791
 		{
 		}
-	case 161:
+	case 156:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:801
-		{
-		}
-	case 162:
-		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:804
-		{
-			checkUint64InInt32Range(protolex, protoDollar[3].ui.start(), protoDollar[3].ui.val)
-			protoVAL.env = &enumValueNode{name: protoDollar[1].id, numberP: protoDollar[3].ui}
-			protoVAL.env.setRange(protoDollar[1].id, protoDollar[4].b)
-		}
-	case 163:
-		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:809
+//line proto.y:793
 		{
-			checkUint64InInt32Range(protolex, protoDollar[3].ui.start(), protoDollar[3].ui.val)
-			protoVAL.env = &enumValueNode{name: protoDollar[1].id, numberP: protoDollar[3].ui, options: protoDollar[4].cmpctOpts}
-			protoVAL.env.setRange(protoDollar[1].id, protoDollar[5].b)
 		}
-	case 164:
+	case 157:
 		protoDollar = protoS[protopt-4 : protopt+1]
-//line proto.y:814
+//line proto.y:796
 		{
-			checkInt64InInt32Range(protolex, protoDollar[3].i.start(), protoDollar[3].i.val)
-			protoVAL.env = &enumValueNode{name: protoDollar[1].id, numberN: protoDollar[3].i}
+			checkInt64InInt32Range(protolex, protoDollar[3].il.start(), protoDollar[3].il.val)
+			protoVAL.env = &enumValueNode{name: protoDollar[1].id, number: protoDollar[3].il}
 			protoVAL.env.setRange(protoDollar[1].id, protoDollar[4].b)
 		}
-	case 165:
+	case 158:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:819
+//line proto.y:801
 		{
-			checkInt64InInt32Range(protolex, protoDollar[3].i.start(), protoDollar[3].i.val)
-			protoVAL.env = &enumValueNode{name: protoDollar[1].id, numberN: protoDollar[3].i, options: protoDollar[4].cmpctOpts}
+			checkInt64InInt32Range(protolex, protoDollar[3].il.start(), protoDollar[3].il.val)
+			protoVAL.env = &enumValueNode{name: protoDollar[1].id, number: protoDollar[3].il, options: protoDollar[4].cmpctOpts}
 			protoVAL.env.setRange(protoDollar[1].id, protoDollar[5].b)
 		}
-	case 166:
+	case 159:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:825
+//line proto.y:807
 		{
 			protoVAL.msg = &messageNode{name: protoDollar[2].id, decls: protoDollar[4].msgDecls}
 			protoVAL.msg.setRange(protoDollar[1].id, protoDollar[5].b)
 		}
-	case 167:
+	case 160:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:830
+//line proto.y:812
 		{
 			protoVAL.msgDecls = append(protoDollar[1].msgDecls, protoDollar[2].msgDecls...)
 		}
-	case 169:
+	case 162:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:834
+//line proto.y:816
 		{
 			protoVAL.msgDecls = nil
 		}
-	case 170:
+	case 163:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:838
+//line proto.y:820
 		{
 			protoVAL.msgDecls = []*messageElement{{field: protoDollar[1].fld}}
 		}
-	case 171:
+	case 164:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:841
+//line proto.y:823
 		{
 			protoVAL.msgDecls = []*messageElement{{enum: protoDollar[1].en}}
 		}
-	case 172:
+	case 165:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:844
+//line proto.y:826
 		{
 			protoVAL.msgDecls = []*messageElement{{nested: protoDollar[1].msg}}
 		}
-	case 173:
+	case 166:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:847
+//line proto.y:829
 		{
 			protoVAL.msgDecls = []*messageElement{{extend: protoDollar[1].extend}}
 		}
-	case 174:
+	case 167:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:850
+//line proto.y:832
 		{
 			protoVAL.msgDecls = []*messageElement{{extensionRange: protoDollar[1].ext}}
 		}
-	case 175:
+	case 168:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:853
+//line proto.y:835
 		{
 			protoVAL.msgDecls = []*messageElement{{group: protoDollar[1].grp}}
 		}
-	case 176:
+	case 169:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:856
+//line proto.y:838
 		{
 			protoVAL.msgDecls = []*messageElement{{option: protoDollar[1].opts[0]}}
 		}
-	case 177:
+	case 170:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:859
+//line proto.y:841
 		{
 			protoVAL.msgDecls = []*messageElement{{oneOf: protoDollar[1].oo}}
 		}
-	case 178:
+	case 171:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:862
+//line proto.y:844
 		{
 			protoVAL.msgDecls = []*messageElement{{mapField: protoDollar[1].mapFld}}
 		}
-	case 179:
+	case 172:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:865
+//line proto.y:847
 		{
 			protoVAL.msgDecls = []*messageElement{{reserved: protoDollar[1].resvd}}
 		}
-	case 180:
+	case 173:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:868
+//line proto.y:850
 		{
 			protoVAL.msgDecls = []*messageElement{{empty: protoDollar[1].b}}
 		}
-	case 181:
+	case 174:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:871
+//line proto.y:853
 		{
 		}
-	case 182:
+	case 175:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:873
+//line proto.y:855
 		{
 		}
-	case 183:
+	case 176:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:876
+//line proto.y:858
 		{
 			c := 0
 			for _, el := range protoDollar[4].extDecls {
@@ -2244,156 +2207,156 @@ protodefault:
 			if c == 0 {
 				lexError(protolex, protoDollar[1].id.start(), "extend sections must define at least one extension")
 			}
-			protoVAL.extend = &extendNode{extendee: protoDollar[2].id, decls: protoDollar[4].extDecls}
+			protoVAL.extend = &extendNode{extendee: protoDollar[2].cid, decls: protoDollar[4].extDecls}
 			protoVAL.extend.setRange(protoDollar[1].id, protoDollar[5].b)
 		}
-	case 184:
+	case 177:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:890
+//line proto.y:872
 		{
 			protoVAL.extDecls = append(protoDollar[1].extDecls, protoDollar[2].extDecls...)
 		}
-	case 186:
+	case 179:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:894
+//line proto.y:876
 		{
 			protoVAL.extDecls = nil
 		}
-	case 187:
+	case 180:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:898
+//line proto.y:880
 		{
 			protoVAL.extDecls = []*extendElement{{field: protoDollar[1].fld}}
 		}
-	case 188:
+	case 181:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:901
+//line proto.y:883
 		{
 			protoVAL.extDecls = []*extendElement{{group: protoDollar[1].grp}}
 		}
-	case 189:
+	case 182:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:904
+//line proto.y:886
 		{
 			protoVAL.extDecls = []*extendElement{{empty: protoDollar[1].b}}
 		}
-	case 190:
+	case 183:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:907
+//line proto.y:889
 		{
 		}
-	case 191:
+	case 184:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:909
+//line proto.y:891
 		{
 		}
-	case 192:
+	case 185:
 		protoDollar = protoS[protopt-5 : protopt+1]
-//line proto.y:912
+//line proto.y:894
 		{
 			protoVAL.svc = &serviceNode{name: protoDollar[2].id, decls: protoDollar[4].svcDecls}
 			protoVAL.svc.setRange(protoDollar[1].id, protoDollar[5].b)
 		}
-	case 193:
+	case 186:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:917
+//line proto.y:899
 		{
 			protoVAL.svcDecls = append(protoDollar[1].svcDecls, protoDollar[2].svcDecls...)
 		}
-	case 195:
+	case 188:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:921
+//line proto.y:903
 		{
 			protoVAL.svcDecls = nil
 		}
-	case 196:
+	case 189:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:928
+//line proto.y:910
 		{
 			protoVAL.svcDecls = []*serviceElement{{option: protoDollar[1].opts[0]}}
 		}
-	case 197:
+	case 190:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:931
+//line proto.y:913
 		{
 			protoVAL.svcDecls = []*serviceElement{{rpc: protoDollar[1].mtd}}
 		}
-	case 198:
+	case 191:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:934
+//line proto.y:916
 		{
 			protoVAL.svcDecls = []*serviceElement{{empty: protoDollar[1].b}}
 		}
-	case 199:
+	case 192:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:937
+//line proto.y:919
 		{
 		}
-	case 200:
+	case 193:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:939
+//line proto.y:921
 		{
 		}
-	case 201:
+	case 194:
 		protoDollar = protoS[protopt-10 : protopt+1]
-//line proto.y:942
+//line proto.y:924
 		{
 			protoVAL.mtd = &methodNode{name: protoDollar[2].id, input: protoDollar[4].rpcType, output: protoDollar[8].rpcType}
 			protoVAL.mtd.setRange(protoDollar[1].id, protoDollar[10].b)
 		}
-	case 202:
+	case 195:
 		protoDollar = protoS[protopt-12 : protopt+1]
-//line proto.y:946
+//line proto.y:928
 		{
 			protoVAL.mtd = &methodNode{name: protoDollar[2].id, input: protoDollar[4].rpcType, output: protoDollar[8].rpcType, options: protoDollar[11].opts}
 			protoVAL.mtd.setRange(protoDollar[1].id, protoDollar[12].b)
 		}
-	case 203:
+	case 196:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:951
+//line proto.y:933
 		{
-			protoVAL.rpcType = &rpcTypeNode{msgType: protoDollar[2].id, streamKeyword: protoDollar[1].id}
-			protoVAL.rpcType.setRange(protoDollar[1].id, protoDollar[2].id)
+			protoVAL.rpcType = &rpcTypeNode{msgType: protoDollar[2].cid, streamKeyword: protoDollar[1].id}
+			protoVAL.rpcType.setRange(protoDollar[1].id, protoDollar[2].cid)
 		}
-	case 204:
+	case 197:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:955
+//line proto.y:937
 		{
-			protoVAL.rpcType = &rpcTypeNode{msgType: protoDollar[1].id}
-			protoVAL.rpcType.setRange(protoDollar[1].id, protoDollar[1].id)
+			protoVAL.rpcType = &rpcTypeNode{msgType: protoDollar[1].cid}
+			protoVAL.rpcType.setRange(protoDollar[1].cid, protoDollar[1].cid)
 		}
-	case 205:
+	case 198:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:960
+//line proto.y:942
 		{
 			protoVAL.opts = append(protoDollar[1].opts, protoDollar[2].opts...)
 		}
-	case 207:
+	case 200:
 		protoDollar = protoS[protopt-0 : protopt+1]
-//line proto.y:964
+//line proto.y:946
 		{
 			protoVAL.opts = []*optionNode{}
 		}
-	case 208:
+	case 201:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:968
+//line proto.y:950
 		{
 			protoVAL.opts = protoDollar[1].opts
 		}
-	case 209:
+	case 202:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:971
+//line proto.y:953
 		{
 			protoVAL.opts = []*optionNode{}
 		}
-	case 210:
+	case 203:
 		protoDollar = protoS[protopt-2 : protopt+1]
-//line proto.y:974
+//line proto.y:956
 		{
 		}
-	case 211:
+	case 204:
 		protoDollar = protoS[protopt-1 : protopt+1]
-//line proto.y:976
+//line proto.y:958
 		{
 		}
 	}
diff --git a/desc/protoparse/source_code_info.go b/desc/protoparse/source_code_info.go
index 3ae011b..ff37733 100644
--- a/desc/protoparse/source_code_info.go
+++ b/desc/protoparse/source_code_info.go
@@ -80,15 +80,15 @@ func (r *parseResult) generateSourceCodeInfoForOption(sci *sourceCodeInfo, n *op
 	sci.newLoc(n, optPath)
 	var valTag int32
 	switch n.val.(type) {
-	case *identNode:
+	case *compoundIdentNode:
 		valTag = internal.Uninterpreted_identTag
 	case *intLiteralNode:
 		valTag = internal.Uninterpreted_posIntTag
-	case *negativeIntLiteralNode:
+	case *compoundIntNode:
 		valTag = internal.Uninterpreted_negIntTag
-	case *floatLiteralNode:
+	case *compoundFloatNode:
 		valTag = internal.Uninterpreted_doubleTag
-	case *stringLiteralNode:
+	case *compoundStringNode:
 		valTag = internal.Uninterpreted_stringTag
 	case *aggregateLiteralNode:
 		valTag = internal.Uninterpreted_aggregateTag


Test patch:
diff --git a/desc/protoparse/error_reporting_test.go b/desc/protoparse/error_reporting_test.go
index 535f57e..c74d0a3 100644
--- a/desc/protoparse/error_reporting_test.go
+++ b/desc/protoparse/error_reporting_test.go
@@ -54,7 +54,7 @@ func TestErrorReporting(t *testing.T) {
 			},
 			expectedErrs: []string{
 				"test.proto:2:50: syntax value must be 'proto2' or 'proto3'",
-				"test.proto:5:41: syntax error: unexpected \"message\", expecting ';'",
+				"test.proto:5:41: syntax error: unexpected \"message\", expecting ';' or '.'",
 				"test.proto:6:53: syntax error: unexpected '='",
 			},
 		},
diff --git a/desc/protoparse/lexer_test.go b/desc/protoparse/lexer_test.go
index d88ebd1..25d2b24 100644
--- a/desc/protoparse/lexer_test.go
+++ b/desc/protoparse/lexer_test.go
@@ -86,10 +86,20 @@ foo
 		{t: _SERVICE, line: 14, col: 9, span: 7, v: "service", comments: []string{"// another comment\n", "// more and more...\n"}},
 		{t: _RPC, line: 14, col: 17, span: 3, v: "rpc"},
 		{t: _MESSAGE, line: 14, col: 21, span: 7, v: "message"},
-		{t: _TYPENAME, line: 15, col: 9, span: 5, v: ".type"},
-		{t: _TYPENAME, line: 16, col: 9, span: 6, v: ".f.q.n"},
+		{t: '.', line: 15, col: 9, span: 1},
+		{t: _NAME, line: 15, col: 10, span: 4, v: "type"},
+		{t: '.', line: 16, col: 9, span: 1},
+		{t: _NAME, line: 16, col: 10, span: 1, v: "f"},
+		{t: '.', line: 16, col: 11, span: 1},
+		{t: _NAME, line: 16, col: 12, span: 1, v: "q"},
+		{t: '.', line: 16, col: 13, span: 1},
+		{t: _NAME, line: 16, col: 14, span: 1, v: "n"},
 		{t: _NAME, line: 17, col: 9, span: 4, v: "name"},
-		{t: _FQNAME, line: 18, col: 9, span: 5, v: "f.q.n"},
+		{t: _NAME, line: 18, col: 9, span: 1, v: "f"},
+		{t: '.', line: 18, col: 10, span: 1},
+		{t: _NAME, line: 18, col: 11, span: 1, v: "q"},
+		{t: '.', line: 18, col: 12, span: 1},
+		{t: _NAME, line: 18, col: 13, span: 1, v: "n"},
 		{t: _FLOAT_LIT, line: 20, col: 9, span: 3, v: 0.01},
 		{t: _FLOAT_LIT, line: 21, col: 9, span: 6, v: 0.01e12},
 		{t: _FLOAT_LIT, line: 22, col: 9, span: 6, v: 0.01e5},
@@ -146,15 +156,15 @@ foo
 		var n node
 		var val interface{}
 		switch tok {
-		case _SYNTAX, _OPTION, _INT32, _SERVICE, _RPC, _MESSAGE, _TYPENAME, _NAME, _FQNAME:
+		case _SYNTAX, _OPTION, _INT32, _SERVICE, _RPC, _MESSAGE, _NAME:
 			n = sym.id
 			val = sym.id.val
 		case _STRING_LIT:
-			n = sym.str
-			val = sym.str.val
+			n = sym.s
+			val = sym.s.val
 		case _INT_LIT:
-			n = sym.ui
-			val = sym.ui.val
+			n = sym.i
+			val = sym.i.val
 		case _FLOAT_LIT:
 			n = sym.f
 			val = sym.f.val