cue/scanner: allow $ as a letter in identifies

This brings CUE identifiers in line with JavaScript,
and more importantly, JSON style.

It is common in JSON to have identifiers with a $.
With the restriction that string labels can no longer
be referenced, and with the elimination of quoted
identifiers, this has become a bit awkward.

Also, unlike Go, CUE cannot enforce a certain
capitalization style as this is often enforced by the
given APIs. Allowing `$` in addition to `_` gives users
a bit more flexibility in using identifiers that stand out
from other conventions used within an API.

Change-Id: If6253d1e353729aad07ccd665ccd04018ab2ccce
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/3982
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/cue/ast/ident.go b/cue/ast/ident.go
index 8760c7b..22e3762 100644
--- a/cue/ast/ident.go
+++ b/cue/ast/ident.go
@@ -35,7 +35,7 @@
 // IsValidIdent reports whether str is a valid identifier.
 func IsValidIdent(ident string) bool {
 	for i, r := range ident {
-		if isLetter(r) || r == '_' {
+		if isLetter(r) || r == '_' || r == '$' {
 			continue
 		}
 		if i > 0 && isDigit(r) {
@@ -65,7 +65,7 @@
 	// }
 
 	for _, r := range ident {
-		if isLetter(r) || isDigit(r) || r == '_' {
+		if isLetter(r) || isDigit(r) || r == '_' || r == '$' {
 			continue
 		}
 		if r == '-' {
diff --git a/cue/scanner/scanner.go b/cue/scanner/scanner.go
index 07817f9..29cb0cf 100644
--- a/cue/scanner/scanner.go
+++ b/cue/scanner/scanner.go
@@ -282,7 +282,7 @@
 
 func (s *Scanner) scanIdentifier() string {
 	offs := s.offset
-	for isLetter(s.ch) || isDigit(s.ch) || s.ch == '_' {
+	for isLetter(s.ch) || isDigit(s.ch) || s.ch == '_' || s.ch == '$' {
 		s.next()
 	}
 	return string(s.src[offs:s.offset])
@@ -798,7 +798,7 @@
 	// 	lit = string(rune(ch))
 	// 	s.next()
 	// 	fallthrough
-	case isLetter(ch):
+	case isLetter(ch), ch == '$':
 		lit = s.scanIdentifier()
 		if len(lit) > 1 {
 			// keywords are longer than one letter - avoid lookup otherwise
diff --git a/cue/scanner/scanner_test.go b/cue/scanner/scanner_test.go
index bcbca81..11a377b 100644
--- a/cue/scanner/scanner_test.go
+++ b/cue/scanner/scanner_test.go
@@ -74,6 +74,7 @@
 	{token.BOTTOM, "_|_", literal},
 
 	{token.IDENT, "foobar", literal},
+	{token.IDENT, "$foobar", literal},
 	{token.IDENT, "`foobar`", literal},
 	{token.IDENT, "a۰۱۸", literal},
 	{token.IDENT, "foo६४", literal},
diff --git a/doc/ref/spec.md b/doc/ref/spec.md
index 22fc29c..2fe4864 100644
--- a/doc/ref/spec.md
+++ b/doc/ref/spec.md
@@ -177,8 +177,9 @@
 ### Identifiers
 
 Identifiers name entities such as fields and aliases.
-An identifier is a sequence of one or more letters (which includes `_`) and digits.
-It may not be `_`.
+An identifier is a sequence of one or more letters (which includes `_` and `$`)
+and digits.
+It may not be `_` or `$`.
 The first character in an identifier must be a letter.
 
 <!--