cue: allow string value as first element in ParsePath

This makes ParsePath more generally applicable.

Change-Id: I6e7eaeed7a3da85036ea39fb7949b6b1a1622652
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9161
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/cue/path.go b/cue/path.go
index 28d0182..538eacb 100644
--- a/cue/path.go
+++ b/cue/path.go
@@ -57,7 +57,13 @@
 
 // ParsePath parses a CUE expression into a Path. Any error resulting from
 // this conversion can be obtained by calling Err on the result.
+//
+// Unlike with normal CUE expressions, the first element of the path may be
+// a string literal.
 func ParsePath(s string) Path {
+	if s == "" {
+		return Path{}
+	}
 	expr, err := parser.ParseExpr("", s)
 	if err != nil {
 		return MakePath(Selector{pathError{errors.Promote(err, "invalid path")}})
@@ -101,6 +107,9 @@
 	case *ast.Ident:
 		return []Selector{identSelector(x)}
 
+	case *ast.BasicLit:
+		return []Selector{basicLitSelector(x)}
+
 	case *ast.IndexExpr:
 		a := toSelectors(x.X)
 		var sel Selector
diff --git a/cue/path_test.go b/cue/path_test.go
index 5da4aa1..6cabd98 100644
--- a/cue/path_test.go
+++ b/cue/path_test.go
@@ -42,6 +42,14 @@
 		out:  "1",
 		str:  "#Foo.a.b",
 	}, {
+		path: ParsePath(`#Foo.a.b`),
+		out:  "1",
+		str:  "#Foo.a.b",
+	}, {
+		path: ParsePath(`"#Foo".c.d`),
+		out:  "2",
+		str:  `"#Foo".c.d`,
+	}, {
 		// fallback Def(Foo) -> Def(#Foo)
 		path: p(Def("Foo"), Str("a"), Str("b")),
 		out:  "1",