56 lines
2.0 KiB
Go
56 lines
2.0 KiB
Go
package hcl
|
|
|
|
// AbsTraversalForExpr attempts to interpret the given expression as
|
|
// an absolute traversal, or returns error diagnostic(s) if that is
|
|
// not possible for the given expression.
|
|
//
|
|
// A particular Expression implementation can support this function by
|
|
// offering a method called AsTraversal that takes no arguments and
|
|
// returns either a valid absolute traversal or nil to indicate that
|
|
// no traversal is possible.
|
|
//
|
|
// In most cases the calling application is interested in the value
|
|
// that results from an expression, but in rarer cases the application
|
|
// needs to see the the name of the variable and subsequent
|
|
// attributes/indexes itself, for example to allow users to give references
|
|
// to the variables themselves rather than to their values. An implementer
|
|
// of this function should at least support attribute and index steps.
|
|
func AbsTraversalForExpr(expr Expression) (Traversal, Diagnostics) {
|
|
type asTraversal interface {
|
|
AsTraversal() Traversal
|
|
}
|
|
|
|
if asT, supported := expr.(asTraversal); supported {
|
|
if traversal := asT.AsTraversal(); traversal != nil {
|
|
return traversal, nil
|
|
}
|
|
}
|
|
return nil, Diagnostics{
|
|
&Diagnostic{
|
|
Severity: DiagError,
|
|
Summary: "Invalid expression",
|
|
Detail: "A static variable reference is required.",
|
|
Subject: expr.Range().Ptr(),
|
|
},
|
|
}
|
|
}
|
|
|
|
// RelTraversalForExpr is similar to AbsTraversalForExpr but it returns
|
|
// a relative traversal instead. Due to the nature of ZCL expressions, the
|
|
// first element of the returned traversal is always a TraverseAttr, and
|
|
// then it will be followed by zero or more other expressions.
|
|
//
|
|
// Any expression accepted by AbsTraversalForExpr is also accepted by
|
|
// RelTraversalForExpr.
|
|
func RelTraversalForExpr(expr Expression) (Traversal, Diagnostics) {
|
|
traversal, diags := AbsTraversalForExpr(expr)
|
|
if len(traversal) > 0 {
|
|
root := traversal[0].(TraverseRoot)
|
|
traversal[0] = TraverseAttr{
|
|
Name: root.Name,
|
|
SrcRange: root.SrcRange,
|
|
}
|
|
}
|
|
return traversal, diags
|
|
}
|