package hclsyntax import ( "testing" "github.com/google/go-cmp/cmp" "github.com/hashicorp/hcl/v2" ) func TestScanTokens_normal(t *testing.T) { tests := []struct { input string want []Token }{ // Empty input { ``, []Token{ { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 0, Line: 1, Column: 1}, }, }, }, }, { ` `, []Token{ { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, }, }, { "\n\n", []Token{ { Type: TokenNewline, Bytes: []byte("\n"), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 2, Column: 1}, }, }, { Type: TokenNewline, Bytes: []byte("\n"), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 2, Column: 1}, End: hcl.Pos{Byte: 2, Line: 3, Column: 1}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 2, Line: 3, Column: 1}, End: hcl.Pos{Byte: 2, Line: 3, Column: 1}, }, }, }, }, // Byte-order mark { "\xef\xbb\xbf", // Leading UTF-8 byte-order mark is ignored... []Token{ { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ // ...but its bytes still count when producing ranges Start: hcl.Pos{Byte: 3, Line: 1, Column: 1}, End: hcl.Pos{Byte: 3, Line: 1, Column: 1}, }, }, }, }, { " \xef\xbb\xbf", // Non-leading BOM is invalid []Token{ { Type: TokenInvalid, Bytes: utf8BOM, Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 4, Line: 1, Column: 3}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 4, Line: 1, Column: 3}, End: hcl.Pos{Byte: 4, Line: 1, Column: 3}, }, }, }, }, { "\xfe\xff", // UTF-16 BOM is invalid []Token{ { Type: TokenBadUTF8, Bytes: []byte{0xfe}, Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenBadUTF8, Bytes: []byte{0xff}, Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 2, Line: 1, Column: 3}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 2, Line: 1, Column: 3}, End: hcl.Pos{Byte: 2, Line: 1, Column: 3}, }, }, }, }, // TokenNumberLit { `1`, []Token{ { Type: TokenNumberLit, Bytes: []byte(`1`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, }, }, { `12`, []Token{ { Type: TokenNumberLit, Bytes: []byte(`12`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 2, Line: 1, Column: 3}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 2, Line: 1, Column: 3}, End: hcl.Pos{Byte: 2, Line: 1, Column: 3}, }, }, }, }, { `12.3`, []Token{ { Type: TokenNumberLit, Bytes: []byte(`12.3`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 4, Line: 1, Column: 5}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 4, Line: 1, Column: 5}, End: hcl.Pos{Byte: 4, Line: 1, Column: 5}, }, }, }, }, { `1e2`, []Token{ { Type: TokenNumberLit, Bytes: []byte(`1e2`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 3, Line: 1, Column: 4}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 3, Line: 1, Column: 4}, End: hcl.Pos{Byte: 3, Line: 1, Column: 4}, }, }, }, }, { `1e+2`, []Token{ { Type: TokenNumberLit, Bytes: []byte(`1e+2`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 4, Line: 1, Column: 5}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 4, Line: 1, Column: 5}, End: hcl.Pos{Byte: 4, Line: 1, Column: 5}, }, }, }, }, // TokenIdent { `hello`, []Token{ { Type: TokenIdent, Bytes: []byte(`hello`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 5, Line: 1, Column: 6}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, }, }, { `_ello`, []Token{ { Type: TokenIdent, Bytes: []byte(`_ello`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 5, Line: 1, Column: 6}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, }, }, { `hel_o`, []Token{ { Type: TokenIdent, Bytes: []byte(`hel_o`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 5, Line: 1, Column: 6}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, }, }, { `hel-o`, []Token{ { Type: TokenIdent, Bytes: []byte(`hel-o`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 5, Line: 1, Column: 6}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, }, }, { `h3ll0`, []Token{ { Type: TokenIdent, Bytes: []byte(`h3ll0`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 5, Line: 1, Column: 6}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, }, }, { `héllo`, // combining acute accent []Token{ { Type: TokenIdent, Bytes: []byte(`héllo`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 7, Line: 1, Column: 6}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 6}, End: hcl.Pos{Byte: 7, Line: 1, Column: 6}, }, }, }, }, // Literal-only Templates (string literals, effectively) { `""`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 2, Line: 1, Column: 3}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 2, Line: 1, Column: 3}, End: hcl.Pos{Byte: 2, Line: 1, Column: 3}, }, }, }, }, { `"hello"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`hello`), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 6, Line: 1, Column: 7}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 6, Line: 1, Column: 7}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 8}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, }, }, { `"hello, \"world\"!"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`hello, \"world\"!`), // The escapes are handled by the parser, not the scanner Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 18, Line: 1, Column: 19}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 18, Line: 1, Column: 19}, End: hcl.Pos{Byte: 19, Line: 1, Column: 20}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 19, Line: 1, Column: 20}, End: hcl.Pos{Byte: 19, Line: 1, Column: 20}, }, }, }, }, { `"hello $$"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`hello `), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, // This one scans a little oddly because of how the scanner // handles the escaping of the dollar sign, but it's still // good enough for the parser since it'll just concatenate // these two string literals together anyway. { Type: TokenQuotedLit, Bytes: []byte(`$`), Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 8}, End: hcl.Pos{Byte: 8, Line: 1, Column: 9}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`$`), Range: hcl.Range{ Start: hcl.Pos{Byte: 8, Line: 1, Column: 9}, End: hcl.Pos{Byte: 9, Line: 1, Column: 10}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 9, Line: 1, Column: 10}, End: hcl.Pos{Byte: 10, Line: 1, Column: 11}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 10, Line: 1, Column: 11}, End: hcl.Pos{Byte: 10, Line: 1, Column: 11}, }, }, }, }, { `"hello %%"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`hello `), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, // This one scans a little oddly because of how the scanner // handles the escaping of the percent sign, but it's still // good enough for the parser since it'll just concatenate // these two string literals together anyway. { Type: TokenQuotedLit, Bytes: []byte(`%`), Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 8}, End: hcl.Pos{Byte: 8, Line: 1, Column: 9}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`%`), Range: hcl.Range{ Start: hcl.Pos{Byte: 8, Line: 1, Column: 9}, End: hcl.Pos{Byte: 9, Line: 1, Column: 10}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 9, Line: 1, Column: 10}, End: hcl.Pos{Byte: 10, Line: 1, Column: 11}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 10, Line: 1, Column: 11}, End: hcl.Pos{Byte: 10, Line: 1, Column: 11}, }, }, }, }, { `"hello $"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`hello `), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`$`), Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 8}, End: hcl.Pos{Byte: 8, Line: 1, Column: 9}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 8, Line: 1, Column: 9}, End: hcl.Pos{Byte: 9, Line: 1, Column: 10}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 9, Line: 1, Column: 10}, End: hcl.Pos{Byte: 9, Line: 1, Column: 10}, }, }, }, }, { `"hello %"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`hello `), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`%`), Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 8}, End: hcl.Pos{Byte: 8, Line: 1, Column: 9}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 8, Line: 1, Column: 9}, End: hcl.Pos{Byte: 9, Line: 1, Column: 10}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 9, Line: 1, Column: 10}, End: hcl.Pos{Byte: 9, Line: 1, Column: 10}, }, }, }, }, { `"hello $${world}"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`hello `), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`$${`), Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 8}, End: hcl.Pos{Byte: 10, Line: 1, Column: 11}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`world}`), Range: hcl.Range{ Start: hcl.Pos{Byte: 10, Line: 1, Column: 11}, End: hcl.Pos{Byte: 16, Line: 1, Column: 17}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 16, Line: 1, Column: 17}, End: hcl.Pos{Byte: 17, Line: 1, Column: 18}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 17, Line: 1, Column: 18}, End: hcl.Pos{Byte: 17, Line: 1, Column: 18}, }, }, }, }, { `"hello %%{world}"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`hello `), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`%%{`), Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 8}, End: hcl.Pos{Byte: 10, Line: 1, Column: 11}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`world}`), Range: hcl.Range{ Start: hcl.Pos{Byte: 10, Line: 1, Column: 11}, End: hcl.Pos{Byte: 16, Line: 1, Column: 17}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 16, Line: 1, Column: 17}, End: hcl.Pos{Byte: 17, Line: 1, Column: 18}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 17, Line: 1, Column: 18}, End: hcl.Pos{Byte: 17, Line: 1, Column: 18}, }, }, }, }, { `"hello %${world}"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`hello `), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, { Type: TokenQuotedLit, Bytes: []byte(`%`), Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 8}, End: hcl.Pos{Byte: 8, Line: 1, Column: 9}, }, }, { Type: TokenTemplateInterp, Bytes: []byte(`${`), Range: hcl.Range{ Start: hcl.Pos{Byte: 8, Line: 1, Column: 9}, End: hcl.Pos{Byte: 10, Line: 1, Column: 11}, }, }, { Type: TokenIdent, Bytes: []byte(`world`), Range: hcl.Range{ Start: hcl.Pos{Byte: 10, Line: 1, Column: 11}, End: hcl.Pos{Byte: 15, Line: 1, Column: 16}, }, }, { Type: TokenTemplateSeqEnd, Bytes: []byte(`}`), Range: hcl.Range{ Start: hcl.Pos{Byte: 15, Line: 1, Column: 16}, End: hcl.Pos{Byte: 16, Line: 1, Column: 17}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 16, Line: 1, Column: 17}, End: hcl.Pos{Byte: 17, Line: 1, Column: 18}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 17, Line: 1, Column: 18}, End: hcl.Pos{Byte: 17, Line: 1, Column: 18}, }, }, }, }, // Templates with interpolations and control sequences { `"${1}"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenTemplateInterp, Bytes: []byte(`${`), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 3, Line: 1, Column: 4}, }, }, { Type: TokenNumberLit, Bytes: []byte(`1`), Range: hcl.Range{ Start: hcl.Pos{Byte: 3, Line: 1, Column: 4}, End: hcl.Pos{Byte: 4, Line: 1, Column: 5}, }, }, { Type: TokenTemplateSeqEnd, Bytes: []byte(`}`), Range: hcl.Range{ Start: hcl.Pos{Byte: 4, Line: 1, Column: 5}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 5, Line: 1, Column: 6}, End: hcl.Pos{Byte: 6, Line: 1, Column: 7}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 6, Line: 1, Column: 7}, End: hcl.Pos{Byte: 6, Line: 1, Column: 7}, }, }, }, }, { `"%{a}"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenTemplateControl, Bytes: []byte(`%{`), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 3, Line: 1, Column: 4}, }, }, { Type: TokenIdent, Bytes: []byte(`a`), Range: hcl.Range{ Start: hcl.Pos{Byte: 3, Line: 1, Column: 4}, End: hcl.Pos{Byte: 4, Line: 1, Column: 5}, }, }, { Type: TokenTemplateSeqEnd, Bytes: []byte(`}`), Range: hcl.Range{ Start: hcl.Pos{Byte: 4, Line: 1, Column: 5}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 5, Line: 1, Column: 6}, End: hcl.Pos{Byte: 6, Line: 1, Column: 7}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 6, Line: 1, Column: 7}, End: hcl.Pos{Byte: 6, Line: 1, Column: 7}, }, }, }, }, { `"${{}}"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenTemplateInterp, Bytes: []byte(`${`), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 3, Line: 1, Column: 4}, }, }, { Type: TokenOBrace, Bytes: []byte(`{`), Range: hcl.Range{ Start: hcl.Pos{Byte: 3, Line: 1, Column: 4}, End: hcl.Pos{Byte: 4, Line: 1, Column: 5}, }, }, { Type: TokenCBrace, Bytes: []byte(`}`), Range: hcl.Range{ Start: hcl.Pos{Byte: 4, Line: 1, Column: 5}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, { Type: TokenTemplateSeqEnd, Bytes: []byte(`}`), Range: hcl.Range{ Start: hcl.Pos{Byte: 5, Line: 1, Column: 6}, End: hcl.Pos{Byte: 6, Line: 1, Column: 7}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 6, Line: 1, Column: 7}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 8}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, }, }, { `"${""}"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenTemplateInterp, Bytes: []byte(`${`), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 3, Line: 1, Column: 4}, }, }, { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 3, Line: 1, Column: 4}, End: hcl.Pos{Byte: 4, Line: 1, Column: 5}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 4, Line: 1, Column: 5}, End: hcl.Pos{Byte: 5, Line: 1, Column: 6}, }, }, { Type: TokenTemplateSeqEnd, Bytes: []byte(`}`), Range: hcl.Range{ Start: hcl.Pos{Byte: 5, Line: 1, Column: 6}, End: hcl.Pos{Byte: 6, Line: 1, Column: 7}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 6, Line: 1, Column: 7}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 8}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, }, }, { `"${"${a}"}"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenTemplateInterp, Bytes: []byte(`${`), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 3, Line: 1, Column: 4}, }, }, { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 3, Line: 1, Column: 4}, End: hcl.Pos{Byte: 4, Line: 1, Column: 5}, }, }, { Type: TokenTemplateInterp, Bytes: []byte(`${`), Range: hcl.Range{ Start: hcl.Pos{Byte: 4, Line: 1, Column: 5}, End: hcl.Pos{Byte: 6, Line: 1, Column: 7}, }, }, { Type: TokenIdent, Bytes: []byte(`a`), Range: hcl.Range{ Start: hcl.Pos{Byte: 6, Line: 1, Column: 7}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, { Type: TokenTemplateSeqEnd, Bytes: []byte(`}`), Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 8}, End: hcl.Pos{Byte: 8, Line: 1, Column: 9}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 8, Line: 1, Column: 9}, End: hcl.Pos{Byte: 9, Line: 1, Column: 10}, }, }, { Type: TokenTemplateSeqEnd, Bytes: []byte(`}`), Range: hcl.Range{ Start: hcl.Pos{Byte: 9, Line: 1, Column: 10}, End: hcl.Pos{Byte: 10, Line: 1, Column: 11}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 10, Line: 1, Column: 11}, End: hcl.Pos{Byte: 11, Line: 1, Column: 12}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 11, Line: 1, Column: 12}, End: hcl.Pos{Byte: 11, Line: 1, Column: 12}, }, }, }, }, { `"${"${a} foo"}"`, []Token{ { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 0, Line: 1, Column: 1}, End: hcl.Pos{Byte: 1, Line: 1, Column: 2}, }, }, { Type: TokenTemplateInterp, Bytes: []byte(`${`), Range: hcl.Range{ Start: hcl.Pos{Byte: 1, Line: 1, Column: 2}, End: hcl.Pos{Byte: 3, Line: 1, Column: 4}, }, }, { Type: TokenOQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 3, Line: 1, Column: 4}, End: hcl.Pos{Byte: 4, Line: 1, Column: 5}, }, }, { Type: TokenTemplateInterp, Bytes: []byte(`${`), Range: hcl.Range{ Start: hcl.Pos{Byte: 4, Line: 1, Column: 5}, End: hcl.Pos{Byte: 6, Line: 1, Column: 7}, }, }, { Type: TokenIdent, Bytes: []byte(`a`), Range: hcl.Range{ Start: hcl.Pos{Byte: 6, Line: 1, Column: 7}, End: hcl.Pos{Byte: 7, Line: 1, Column: 8}, }, }, { Type: TokenTemplateSeqEnd, Bytes: []byte(`}`), Range: hcl.Range{ Start: hcl.Pos{Byte: 7, Line: 1, Column: 8}, End: hcl.Pos{Byte: 8, Line: 1, Column: 9}, }, }, { Type: TokenQuotedLit, Bytes: []byte(` foo`), Range: hcl.Range{ Start: hcl.Pos{Byte: 8, Line: 1, Column: 9}, End: hcl.Pos{Byte: 12, Line: 1, Column: 13}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 12, Line: 1, Column: 13}, End: hcl.Pos{Byte: 13, Line: 1, Column: 14}, }, }, { Type: TokenTemplateSeqEnd, Bytes: []byte(`}`), Range: hcl.Range{ Start: hcl.Pos{Byte: 13, Line: 1, Column: 14}, End: hcl.Pos{Byte: 14, Line: 1, Column: 15}, }, }, { Type: TokenCQuote, Bytes: []byte(`"`), Range: hcl.Range{ Start: hcl.Pos{Byte: 14, Line: 1, Column: 15}, End: hcl.Pos{Byte: 15, Line: 1, Column: 16}, }, }, { Type: TokenEOF, Bytes: []byte{}, Range: hcl.Range{ Start: hcl.Pos{Byte: 15, Line: 1, Column: 16}, End: hcl.Pos{Byte: 15, Line: 1, Column: 16}, }, }, }, }, // Heredoc Templates { `<