diff --git a/config/lang/ast/call.go b/config/lang/ast/call.go index ace1147a6..055701102 100644 --- a/config/lang/ast/call.go +++ b/config/lang/ast/call.go @@ -41,3 +41,7 @@ func (n *Call) Type(s Scope) (Type, error) { return f.ReturnType, nil } + +func (n *Call) GoString() string { + return fmt.Sprintf("*%#v", *n) +} diff --git a/config/lang/lex.go b/config/lang/lex.go index 428631788..0dbe16c9f 100644 --- a/config/lang/lex.go +++ b/config/lang/lex.go @@ -192,12 +192,20 @@ func (x *parserLex) lexModeInterpolation(yylval *parserSymType) int { func (x *parserLex) lexId(yylval *parserSymType) int { var b bytes.Buffer + var last rune for { c := x.next() if c == lexEOF { break } + // We only allow * after a '.' for resource splast: type.name.*.id + // Otherwise, its probably multiplication. + if c == '*' && last != '.' { + x.backup() + break + } + // If this isn't a character we want in an ID, return out. // One day we should make this a regexp. if c != '_' && @@ -214,6 +222,8 @@ func (x *parserLex) lexId(yylval *parserSymType) int { x.Error(err.Error()) return lexEOF } + + last = c } yylval.token = &parserToken{Value: b.String()} diff --git a/config/lang/parse_test.go b/config/lang/parse_test.go index d2671e233..8d705dccb 100644 --- a/config/lang/parse_test.go +++ b/config/lang/parse_test.go @@ -183,6 +183,41 @@ func TestParse(t *testing.T) { }, }, + { + "foo ${var.bar*1} baz", + false, + &ast.Concat{ + Posx: ast.Pos{Column: 1, Line: 1}, + Exprs: []ast.Node{ + &ast.LiteralNode{ + Value: "foo ", + Typex: ast.TypeString, + Posx: ast.Pos{Column: 1, Line: 1}, + }, + &ast.Arithmetic{ + Op: ast.ArithmeticOpMul, + Exprs: []ast.Node{ + &ast.VariableAccess{ + Name: "var.bar", + Posx: ast.Pos{Column: 7, Line: 1}, + }, + &ast.LiteralNode{ + Value: 1, + Typex: ast.TypeInt, + Posx: ast.Pos{Column: 15, Line: 1}, + }, + }, + Posx: ast.Pos{Column: 7, Line: 1}, + }, + &ast.LiteralNode{ + Value: " baz", + Typex: ast.TypeString, + Posx: ast.Pos{Column: 17, Line: 1}, + }, + }, + }, + }, + { "${foo()}", false,