Skip to content

Commit

Permalink
cue/parser: support string selector labels
Browse files Browse the repository at this point in the history
Allowed by the spec, but previously unimplemented.

Change-Id: I2fb7aad303cdfac8862a0744b80d524cb749f5b3
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7342
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
  • Loading branch information
mpvl committed Oct 3, 2020
1 parent 3914ef8 commit 732b6d5
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 18 deletions.
4 changes: 2 additions & 2 deletions cue/ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -660,8 +660,8 @@ type ParenExpr struct {

// A SelectorExpr node represents an expression followed by a selector.
type SelectorExpr struct {
X Expr // expression
Sel *Ident // field selector
X Expr // expression
Sel Label // field selector

comments
expr
Expand Down
6 changes: 4 additions & 2 deletions cue/format/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -909,11 +909,13 @@ func (f *formatter) selectorExpr(x *ast.SelectorExpr, depth int) bool {
f.expr1(x.X, token.HighestPrec, depth)
f.print(token.PERIOD)
if x.Sel.Pos().IsNewline() {
f.print(indent, formfeed, x.Sel.Pos(), x.Sel)
f.print(indent, formfeed)
f.expr(x.Sel.(ast.Expr))
f.print(unindent)
return true
}
f.print(x.Sel.Pos(), x.Sel)
f.print(noblank)
f.expr(x.Sel.(ast.Expr))
return false
}

Expand Down
10 changes: 10 additions & 0 deletions cue/format/testdata/expressions.golden
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,14 @@ package expressions
]

foo: bar

a: "foo-bar": 3
b: a."foo-bar"
c: a."foo-bar".b
d: a.
"foo-bar"
e: a.
"foo-bar".
b
f: 2
}
10 changes: 10 additions & 0 deletions cue/format/testdata/expressions.input
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,14 @@ package expressions
]

foo : bar

a: "foo-bar": 3
b: a."foo-bar"
c: a. "foo-bar" . b
d: a.
"foo-bar"
e: a.
"foo-bar".
b
f: 2
}
15 changes: 15 additions & 0 deletions cue/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1361,6 +1361,21 @@ L:
X: p.checkExpr(x),
Sel: p.parseIdent(),
}
case token.STRING:
if strings.HasPrefix(p.lit, `"`) && !strings.HasPrefix(p.lit, `""`) {
str := &ast.BasicLit{
ValuePos: p.pos,
Kind: token.STRING,
Value: p.lit,
}
p.next()
x = &ast.SelectorExpr{
X: p.checkExpr(x),
Sel: str,
}
break
}
fallthrough
default:
pos := p.pos
p.errorExpected(pos, "selector")
Expand Down
21 changes: 19 additions & 2 deletions cue/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,23 @@ func TestParse(t *testing.T) {
"one-line embedding",
`{ V1, V2 }`,
`{V1, V2}`,
}, {
"selectors",
`a.b. "str"`,
`a.b."str"`,
}, {
"selectors",
`a.b. "str"`,
`a.b."str"`,
}, {
"faulty bytes selector",
`a.b.'str'`,
"a.b._\nexpected selector, found 'STRING' 'str'",
}, {
"faulty multiline string selector",
`a.b."""
"""`,
"a.b._\nexpected selector, found 'STRING' \"\"\"\n\t\t\t\"\"\"",
}, {
"expression embedding",
`#Def: {
Expand Down Expand Up @@ -697,8 +714,8 @@ func TestImports(t *testing.T) {
// *BadExpr.
func TestIncompleteSelection(t *testing.T) {
for _, src := range []string{
"{ a: fmt. }", // at end of object
"{ a: fmt.\n\"a\": x }", // not at end of struct
"{ a: fmt. }", // at end of object
"{ a: fmt.\n0.0: x }", // not at end of struct
} {
t.Run("", func(t *testing.T) {
f, err := ParseFile("", src)
Expand Down
55 changes: 45 additions & 10 deletions cue/testdata/eval/selectors.txtar
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
-- in.cue --
a: 1
b: a + 1
d: {
x: _
y: b + x
}
e: d & {
x: 5
}

a: 1
b: a + 1
d: {
x: _
y: b + x
}
e: d & {
x: 5
}
f: {
a: "foo-bar": 3
b: a."foo-bar"
}
g: {
a: "foo-bar": c: 3
b: a."foo-bar".c
}
-- out/eval --
(struct){
a: (int){ 1 }
Expand All @@ -24,6 +31,20 @@
x: (int){ 5 }
y: (int){ 7 }
}
f: (struct){
a: (struct){
"foo-bar": (int){ 3 }
}
b: (int){ 3 }
}
g: (struct){
a: (struct){
"foo-bar": (struct){
c: (int){ 3 }
}
}
b: (int){ 3 }
}
}
-- out/compile --
--- in.cue
Expand All @@ -37,4 +58,18 @@
e: (〈0;d〉 & {
x: 5
})
f: {
a: {
"foo-bar": 3
}
b: 〈0;a〉."foo-bar"
}
g: {
a: {
"foo-bar": {
c: 3
}
}
b: 〈0;a〉."foo-bar".c
}
}
2 changes: 1 addition & 1 deletion internal/core/adt/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ func (x *SelectorExpr) Source() ast.Node {

func (x *SelectorExpr) resolve(c *OpContext) *Vertex {
n := c.node(x.X, Partial)
return c.lookup(n, x.Src.Sel.NamePos, x.Sel)
return c.lookup(n, x.Src.Sel.Pos(), x.Sel)
}

// IndexExpr is like a selector, but selects an index.
Expand Down
2 changes: 1 addition & 1 deletion internal/core/export/adt.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func (e *exporter) adt(expr adt.Expr, conjuncts []adt.Conjunct) ast.Expr {
case *adt.SelectorExpr:
return &ast.SelectorExpr{
X: e.expr(x.X),
Sel: e.ident(x.Sel),
Sel: e.stringLabel(x.Sel),
}

case *adt.IndexExpr:
Expand Down

0 comments on commit 732b6d5

Please sign in to comment.