internal/ucd: allow non-runes in expansion mode

The first field of UCD files are not always single runes or ranges.
Up till now one had to pass the KeepRanges option to prevent the
first field from being interpreted. Now it will ignore the field
setting a single-rune range with value 0. It also sets keepRanges
to force an error if the user tries to access the field as a Range.

Change-Id: Id3211cc94684cd37c5449c24e45de85d32687298
Reviewed-on: https://go-review.googlesource.com/17292
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/internal/ucd/ucd.go b/internal/ucd/ucd.go
index 04ce069..da2ffa5 100644
--- a/internal/ucd/ucd.go
+++ b/internal/ucd/ucd.go
@@ -156,13 +156,18 @@
 	return false
 }
 
-func (p *Parser) parseRune(b []byte) rune {
+func parseRune(b []byte) (rune, error) {
 	if len(b) > 2 && b[0] == 'U' && b[1] == '+' {
 		b = b[2:]
 	}
 	x, err := strconv.ParseUint(string(b), 16, 32)
+	return rune(x), err
+}
+
+func (p *Parser) parseRune(b []byte) rune {
+	x, err := parseRune(b)
 	p.setError(err)
-	return rune(x)
+	return x
 }
 
 // Rune parses and returns field i as a rune.
@@ -214,7 +219,15 @@
 	if k := bytes.Index(b, []byte("..")); k != -1 {
 		return p.parseRune(b[:k]), p.parseRune(b[k+2:])
 	}
-	x := p.parseRune(b)
+	// The first field may not be a rune, in which case we may ignore any error
+	// and set the range as 0..0.
+	x, err := parseRune(b)
+	if err != nil {
+		// Disable range parsing henceforth. This ensures that an error will be
+		// returned if the user subsequently will try to parse this field as
+		// a Rune.
+		p.keepRanges = true
+	}
 	// Special case for UnicodeData that was retained for backwards compatibility.
 	if i == 0 && len(p.field) > 1 && bytes.HasSuffix(p.field[1], []byte("First>")) {
 		if p.parsedRange {