Commit c6b11a8f by Kyle Brandt Committed by GitHub

Expressions: support ${my var} syntax (#29819)

parent e7447c50
...@@ -288,9 +288,29 @@ func lexFunc(l *lexer) stateFn { ...@@ -288,9 +288,29 @@ func lexFunc(l *lexer) stateFn {
func lexVar(l *lexer) stateFn { func lexVar(l *lexer) stateFn {
hasChar := false hasChar := false
if l.peek() == '{' {
_ = l.next()
for { for {
switch r := l.next(); { switch r := l.next(); {
case unicode.IsLetter(r): case r == '}':
if !hasChar {
return l.errorf("incomplete variable")
}
l.emit(itemVar)
return lexItem
case r == eof:
return l.errorf("unterminated variable missing closing }")
case isVarchar(r) || isSpace(r):
hasChar = true
default:
return l.errorf("unsupported variable character")
}
}
}
for {
switch r := l.next(); {
case isVarchar(r):
hasChar = true hasChar = true
// absorb // absorb
default: default:
...@@ -321,9 +341,6 @@ func isSpace(r rune) bool { ...@@ -321,9 +341,6 @@ func isSpace(r rune) bool {
return unicode.IsSpace(r) return unicode.IsSpace(r)
} }
// isVarchar should maybe be used in place of unicode is letter above,
// but do not want to modify it at this time, so adding lint exception.
// nolint:unused,deadcode
func isVarchar(r rune) bool { func isVarchar(r rune) bool {
return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
} }
......
...@@ -97,6 +97,16 @@ var lexTests = []lexTest{ ...@@ -97,6 +97,16 @@ var lexTests = []lexTest{
{itemNumber, 0, "1.2e-4"}, {itemNumber, 0, "1.2e-4"},
tEOF, tEOF,
}}, }},
{"curly brace var", "${My Var}", []item{
{itemVar, 0, "${My Var}"},
tEOF,
}},
{"curly brace var plus 1", "${My Var} + 1", []item{
{itemVar, 0, "${My Var}"},
tPlus,
{itemNumber, 0, "1"},
tEOF,
}},
{"number plus var", "1 + $A", []item{ {"number plus var", "1 + $A", []item{
{itemNumber, 0, "1"}, {itemNumber, 0, "1"},
tPlus, tPlus,
...@@ -113,6 +123,9 @@ var lexTests = []lexTest{ ...@@ -113,6 +123,9 @@ var lexTests = []lexTest{
{"invalid var", "$", []item{ {"invalid var", "$", []item{
{itemError, 0, "incomplete variable"}, {itemError, 0, "incomplete variable"},
}}, }},
{"invalid curly var", "${adf sd", []item{
{itemError, 0, "unterminated variable missing closing }"},
}},
} }
// collect gathers the emitted items into a slice. // collect gathers the emitted items into a slice.
......
...@@ -88,7 +88,7 @@ func (t NodeType) String() string { ...@@ -88,7 +88,7 @@ func (t NodeType) String() string {
type VarNode struct { type VarNode struct {
NodeType NodeType
Pos Pos
Name string // Without the $ Name string // Without the $ or {}
Text string // Raw Text string // Raw
} }
......
...@@ -300,8 +300,9 @@ func (t *Tree) v() Node { ...@@ -300,8 +300,9 @@ func (t *Tree) v() Node {
func (t *Tree) Var() (v *VarNode) { func (t *Tree) Var() (v *VarNode) {
token := t.next() token := t.next()
varNoPrefix := strings.TrimPrefix(token.val, "$") varNoPrefix := strings.TrimPrefix(token.val, "$")
t.VarNames = append(t.VarNames, varNoPrefix) varNoBraces := strings.TrimSuffix(strings.TrimPrefix(varNoPrefix, "{"), "}")
return newVar(token.pos, varNoPrefix, token.val) t.VarNames = append(t.VarNames, varNoBraces)
return newVar(token.pos, varNoBraces, token.val)
} }
// Func parses a FuncNode. // Func parses a FuncNode.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment