zclsyntax: parsing of the index operator
This can either be a traversal or a first-class node depending on whether the given expression is a literal. This exception is made to allow applications to conditionally populate only part of a potentially-large collection if the config is only requesting one or two distinct indices. In particular, it allows the following to be considered a single traversal from the scope: foo.bar[0].baz
This commit is contained in:
parent
8fc5bd5141
commit
bca573d3d0
@ -387,6 +387,31 @@ func (e *ConditionalExpr) StartRange() zcl.Range {
|
|||||||
return e.Condition.StartRange()
|
return e.Condition.StartRange()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IndexExpr struct {
|
||||||
|
Collection Expression
|
||||||
|
Key Expression
|
||||||
|
|
||||||
|
SrcRange zcl.Range
|
||||||
|
OpenRange zcl.Range
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *IndexExpr) walkChildNodes(w internalWalkFunc) {
|
||||||
|
e.Collection = w(e.Collection).(Expression)
|
||||||
|
e.Key = w(e.Key).(Expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *IndexExpr) Value(ctx *zcl.EvalContext) (cty.Value, zcl.Diagnostics) {
|
||||||
|
panic("IndexExpr.Value not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *IndexExpr) Range() zcl.Range {
|
||||||
|
return e.SrcRange
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *IndexExpr) StartRange() zcl.Range {
|
||||||
|
return e.OpenRange
|
||||||
|
}
|
||||||
|
|
||||||
type TupleConsExpr struct {
|
type TupleConsExpr struct {
|
||||||
Exprs []Expression
|
Exprs []Expression
|
||||||
|
|
||||||
|
@ -19,6 +19,10 @@ func (e *FunctionCallExpr) Variables() []zcl.Traversal {
|
|||||||
return Variables(e)
|
return Variables(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *IndexExpr) Variables() []zcl.Traversal {
|
||||||
|
return Variables(e)
|
||||||
|
}
|
||||||
|
|
||||||
func (e *LiteralValueExpr) Variables() []zcl.Traversal {
|
func (e *LiteralValueExpr) Variables() []zcl.Traversal {
|
||||||
return Variables(e)
|
return Variables(e)
|
||||||
}
|
}
|
||||||
|
@ -461,10 +461,11 @@ Traversal:
|
|||||||
case TokenDot:
|
case TokenDot:
|
||||||
// Attribute access or splat
|
// Attribute access or splat
|
||||||
dot := p.Read()
|
dot := p.Read()
|
||||||
attrTok := p.Read()
|
attrTok := p.Peek()
|
||||||
|
|
||||||
switch attrTok.Type {
|
switch attrTok.Type {
|
||||||
case TokenIdent:
|
case TokenIdent:
|
||||||
|
attrTok = p.Read() // eat token
|
||||||
name := string(attrTok.Bytes)
|
name := string(attrTok.Bytes)
|
||||||
rng := zcl.RangeBetween(dot.Range, attrTok.Range)
|
rng := zcl.RangeBetween(dot.Range, attrTok.Range)
|
||||||
step := zcl.TraverseAttr{
|
step := zcl.TraverseAttr{
|
||||||
@ -491,7 +492,51 @@ Traversal:
|
|||||||
// in order to support autocomplete triggered by typing a
|
// in order to support autocomplete triggered by typing a
|
||||||
// period.
|
// period.
|
||||||
p.setRecovery()
|
p.setRecovery()
|
||||||
break Traversal
|
}
|
||||||
|
|
||||||
|
case TokenOBrack:
|
||||||
|
// Indexing of a collection.
|
||||||
|
// This may or may not be a zcl.Traverser, depending on whether
|
||||||
|
// the key value is something constant.
|
||||||
|
|
||||||
|
open := p.Read()
|
||||||
|
var close Token
|
||||||
|
p.PushIncludeNewlines(false) // arbitrary newlines allowed in brackets
|
||||||
|
keyExpr, keyDiags := p.ParseExpression()
|
||||||
|
diags = append(diags, keyDiags...)
|
||||||
|
if p.recovery && keyDiags.HasErrors() {
|
||||||
|
close = p.recover(TokenCBrack)
|
||||||
|
} else {
|
||||||
|
close = p.Read()
|
||||||
|
if close.Type != TokenCBrack && !p.recovery {
|
||||||
|
diags = append(diags, &zcl.Diagnostic{
|
||||||
|
Severity: zcl.DiagError,
|
||||||
|
Summary: "Missing close bracket on index",
|
||||||
|
Detail: "The index operator must end with a closing bracket (\"]\").",
|
||||||
|
Subject: &close.Range,
|
||||||
|
})
|
||||||
|
close = p.recover(TokenCBrack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.PushIncludeNewlines(true)
|
||||||
|
|
||||||
|
if lit, isLit := keyExpr.(*LiteralValueExpr); isLit {
|
||||||
|
litKey, _ := lit.Value(nil)
|
||||||
|
rng := zcl.RangeBetween(open.Range, close.Range)
|
||||||
|
step := &zcl.TraverseIndex{
|
||||||
|
Key: litKey,
|
||||||
|
SrcRange: rng,
|
||||||
|
}
|
||||||
|
ret = makeRelativeTraversal(ret, step, rng)
|
||||||
|
} else {
|
||||||
|
rng := zcl.RangeBetween(open.Range, close.Range)
|
||||||
|
ret = &IndexExpr{
|
||||||
|
Collection: ret,
|
||||||
|
Key: keyExpr,
|
||||||
|
|
||||||
|
SrcRange: rng,
|
||||||
|
OpenRange: open.Range,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user