zclsyntax: scanner support of string templates
This requires some extra state-keeping because we allow templates to be nested inside templates. This takes us outside of the world of regular languages, but we accept that here because it makes things easier to deal with down the line in the parser. The methodology is to keep track of how many braces are open at a given time and then, when a nested template interpolation begins, record the current brace level. Then, when a closing brace is encountered, if its nesting level is at the top of the stack then we pop off the stack and return to "main" parsing mode. Ragel's existing idea of calling and returning from machines is important here too. As this currently stands this is not actually needed, but once heredocs are in play we will have two possible places to return to at the end of an interpolation sequence, so the state return stack maintained by Ragel will determine whether to return to string mode or heredoc mode.
This commit is contained in:
parent
c50317a2e0
commit
18e45ec05c
File diff suppressed because it is too large
Load Diff
@ -35,7 +35,7 @@ func scanTokens(data []byte, filename string, start zcl.Pos) []Token {
|
||||
Ident = ID_Start ID_Continue*;
|
||||
|
||||
# Symbols that just represent themselves are handled as a single rule.
|
||||
SelfToken = "{" | "}" | "[" | "]" | "(" | ")" | "." | "*" | "/" | "+" | "-" | "=" | "<" | ">" | "!" | "?" | ":" | "\n" | "&" | "|" | "~" | "^" | ";" | "`";
|
||||
SelfToken = "[" | "]" | "(" | ")" | "." | "*" | "/" | "+" | "-" | "=" | "<" | ">" | "!" | "?" | ":" | "\n" | "&" | "|" | "~" | "^" | ";" | "`";
|
||||
|
||||
NotEqual = "!=";
|
||||
GreaterThanEqual = ">=";
|
||||
@ -43,6 +43,10 @@ func scanTokens(data []byte, filename string, start zcl.Pos) []Token {
|
||||
LogicalAnd = "&&";
|
||||
LogicalOr = "||";
|
||||
|
||||
Newline = '\r' ? '\n';
|
||||
|
||||
BeginStringTmpl = '"';
|
||||
|
||||
# Tabs are not valid, but we accept them in the scanner and mark them
|
||||
# as tokens so that we can produce diagnostics advising the user to
|
||||
# use spaces instead.
|
||||
@ -50,6 +54,79 @@ func scanTokens(data []byte, filename string, start zcl.Pos) []Token {
|
||||
|
||||
Spaces = ' '+;
|
||||
|
||||
action beginStringTemplate {
|
||||
token(TokenOQuote);
|
||||
fcall stringTemplate;
|
||||
}
|
||||
|
||||
action endStringTemplate {
|
||||
token(TokenCQuote);
|
||||
fret;
|
||||
}
|
||||
|
||||
action beginTemplateInterp {
|
||||
token(TokenTemplateInterp);
|
||||
braces++;
|
||||
retBraces = append(retBraces, braces);
|
||||
fcall main;
|
||||
}
|
||||
|
||||
action beginTemplateControl {
|
||||
token(TokenTemplateControl);
|
||||
braces++;
|
||||
retBraces = append(retBraces, braces);
|
||||
fcall main;
|
||||
}
|
||||
|
||||
action openBrace {
|
||||
token(TokenOBrace);
|
||||
braces++;
|
||||
}
|
||||
|
||||
action closeBrace {
|
||||
if len(retBraces) > 0 && retBraces[len(retBraces)-1] == braces {
|
||||
token(TokenTemplateSeqEnd);
|
||||
braces--;
|
||||
retBraces = retBraces[0:len(retBraces)-1]
|
||||
fret;
|
||||
} else {
|
||||
token(TokenCBrace);
|
||||
braces--;
|
||||
}
|
||||
}
|
||||
|
||||
action closeTemplateSeqEatWhitespace {
|
||||
token(TokenTemplateSeqEnd);
|
||||
braces--;
|
||||
|
||||
// Only consume from the retBraces stack and return if we are at
|
||||
// a suitable brace nesting level, otherwise things will get
|
||||
// confused. (Not entering this branch indicates a syntax error,
|
||||
// which we will catch in the parser.)
|
||||
if len(retBraces) > 0 && retBraces[len(retBraces)-1] == braces {
|
||||
retBraces = retBraces[0:len(retBraces)-1]
|
||||
fret;
|
||||
}
|
||||
}
|
||||
|
||||
TemplateInterp = "${" ("~")?;
|
||||
TemplateControl = "!{" ("~")?;
|
||||
EndStringTmpl = '"';
|
||||
TemplateStringLiteral = (
|
||||
('$' ^'{') |
|
||||
('!' ^'{') |
|
||||
('\\' AnyUTF8) |
|
||||
(AnyUTF8 - ("$" | "!" | '"'))
|
||||
)+;
|
||||
|
||||
stringTemplate := |*
|
||||
TemplateInterp => beginTemplateInterp;
|
||||
TemplateControl => beginTemplateControl;
|
||||
EndStringTmpl => endStringTemplate;
|
||||
TemplateStringLiteral => { token(TokenStringLit); };
|
||||
BrokenUTF8 => { token(TokenBadUTF8); };
|
||||
*|;
|
||||
|
||||
main := |*
|
||||
Spaces => {};
|
||||
NumberLit => { token(TokenNumberLit) };
|
||||
@ -62,6 +139,13 @@ func scanTokens(data []byte, filename string, start zcl.Pos) []Token {
|
||||
LogicalOr => { token(TokenOr); };
|
||||
SelfToken => { selfToken() };
|
||||
|
||||
"{" => openBrace;
|
||||
"}" => closeBrace;
|
||||
|
||||
"~}" => closeTemplateSeqEatWhitespace;
|
||||
|
||||
BeginStringTmpl => beginStringTemplate;
|
||||
|
||||
Tabs => { token(TokenTabs) };
|
||||
AnyUTF8 => { token(TokenInvalid) };
|
||||
BrokenUTF8 => { token(TokenBadUTF8) };
|
||||
@ -77,6 +161,20 @@ func scanTokens(data []byte, filename string, start zcl.Pos) []Token {
|
||||
te := 0
|
||||
act := 0
|
||||
eof := pe
|
||||
var stack []int
|
||||
var top int
|
||||
|
||||
braces := 0
|
||||
var retBraces []int // stack of brace levels that cause us to use fret
|
||||
|
||||
%%{
|
||||
prepush {
|
||||
stack = append(stack, 0);
|
||||
}
|
||||
postpop {
|
||||
stack = stack[:len(stack)-1];
|
||||
}
|
||||
}%%
|
||||
|
||||
// Make Go compiler happy
|
||||
_ = ts
|
||||
|
@ -213,6 +213,482 @@ func TestScanTokens(t *testing.T) {
|
||||
},
|
||||
},
|
||||
|
||||
// Literal-only Templates (string literals, effectively)
|
||||
{
|
||||
`""`,
|
||||
[]Token{
|
||||
{
|
||||
Type: TokenOQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 0, Line: 1, Column: 1},
|
||||
End: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenCQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: zcl.Pos{Byte: 2, Line: 1, Column: 3},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenEOF,
|
||||
Bytes: []byte{},
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 2, Line: 1, Column: 3},
|
||||
End: zcl.Pos{Byte: 2, Line: 1, Column: 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
`"hello"`,
|
||||
[]Token{
|
||||
{
|
||||
Type: TokenOQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 0, Line: 1, Column: 1},
|
||||
End: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenStringLit,
|
||||
Bytes: []byte(`hello`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenCQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
End: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenEOF,
|
||||
Bytes: []byte{},
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
End: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Templates with interpolations and control sequences
|
||||
{
|
||||
`"${1}"`,
|
||||
[]Token{
|
||||
{
|
||||
Type: TokenOQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 0, Line: 1, Column: 1},
|
||||
End: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateInterp,
|
||||
Bytes: []byte(`${`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: zcl.Pos{Byte: 3, Line: 1, Column: 4},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenNumberLit,
|
||||
Bytes: []byte(`1`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 3, Line: 1, Column: 4},
|
||||
End: zcl.Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateSeqEnd,
|
||||
Bytes: []byte(`}`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 4, Line: 1, Column: 5},
|
||||
End: zcl.Pos{Byte: 5, Line: 1, Column: 6},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenCQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 5, Line: 1, Column: 6},
|
||||
End: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenEOF,
|
||||
Bytes: []byte{},
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
End: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
`"!{a}"`,
|
||||
[]Token{
|
||||
{
|
||||
Type: TokenOQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 0, Line: 1, Column: 1},
|
||||
End: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateControl,
|
||||
Bytes: []byte(`!{`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: zcl.Pos{Byte: 3, Line: 1, Column: 4},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenIdent,
|
||||
Bytes: []byte(`a`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 3, Line: 1, Column: 4},
|
||||
End: zcl.Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateSeqEnd,
|
||||
Bytes: []byte(`}`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 4, Line: 1, Column: 5},
|
||||
End: zcl.Pos{Byte: 5, Line: 1, Column: 6},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenCQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 5, Line: 1, Column: 6},
|
||||
End: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenEOF,
|
||||
Bytes: []byte{},
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
End: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
`"${{}}"`,
|
||||
[]Token{
|
||||
{
|
||||
Type: TokenOQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 0, Line: 1, Column: 1},
|
||||
End: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateInterp,
|
||||
Bytes: []byte(`${`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: zcl.Pos{Byte: 3, Line: 1, Column: 4},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenOBrace,
|
||||
Bytes: []byte(`{`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 3, Line: 1, Column: 4},
|
||||
End: zcl.Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenCBrace,
|
||||
Bytes: []byte(`}`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 4, Line: 1, Column: 5},
|
||||
End: zcl.Pos{Byte: 5, Line: 1, Column: 6},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateSeqEnd,
|
||||
Bytes: []byte(`}`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 5, Line: 1, Column: 6},
|
||||
End: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenCQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
End: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenEOF,
|
||||
Bytes: []byte{},
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
End: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
`"${""}"`,
|
||||
[]Token{
|
||||
{
|
||||
Type: TokenOQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 0, Line: 1, Column: 1},
|
||||
End: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateInterp,
|
||||
Bytes: []byte(`${`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: zcl.Pos{Byte: 3, Line: 1, Column: 4},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenOQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 3, Line: 1, Column: 4},
|
||||
End: zcl.Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenCQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 4, Line: 1, Column: 5},
|
||||
End: zcl.Pos{Byte: 5, Line: 1, Column: 6},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateSeqEnd,
|
||||
Bytes: []byte(`}`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 5, Line: 1, Column: 6},
|
||||
End: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenCQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
End: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenEOF,
|
||||
Bytes: []byte{},
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
End: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
`"${"${a}"}"`,
|
||||
[]Token{
|
||||
{
|
||||
Type: TokenOQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 0, Line: 1, Column: 1},
|
||||
End: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateInterp,
|
||||
Bytes: []byte(`${`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: zcl.Pos{Byte: 3, Line: 1, Column: 4},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenOQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 3, Line: 1, Column: 4},
|
||||
End: zcl.Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateInterp,
|
||||
Bytes: []byte(`${`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 4, Line: 1, Column: 5},
|
||||
End: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenIdent,
|
||||
Bytes: []byte(`a`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
End: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateSeqEnd,
|
||||
Bytes: []byte(`}`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
End: zcl.Pos{Byte: 8, Line: 1, Column: 9},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenCQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 8, Line: 1, Column: 9},
|
||||
End: zcl.Pos{Byte: 9, Line: 1, Column: 10},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateSeqEnd,
|
||||
Bytes: []byte(`}`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 9, Line: 1, Column: 10},
|
||||
End: zcl.Pos{Byte: 10, Line: 1, Column: 11},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenCQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 10, Line: 1, Column: 11},
|
||||
End: zcl.Pos{Byte: 11, Line: 1, Column: 12},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenEOF,
|
||||
Bytes: []byte{},
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 11, Line: 1, Column: 12},
|
||||
End: zcl.Pos{Byte: 11, Line: 1, Column: 12},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
`"${"${a} foo"}"`,
|
||||
[]Token{
|
||||
{
|
||||
Type: TokenOQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 0, Line: 1, Column: 1},
|
||||
End: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateInterp,
|
||||
Bytes: []byte(`${`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: zcl.Pos{Byte: 3, Line: 1, Column: 4},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenOQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 3, Line: 1, Column: 4},
|
||||
End: zcl.Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateInterp,
|
||||
Bytes: []byte(`${`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 4, Line: 1, Column: 5},
|
||||
End: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenIdent,
|
||||
Bytes: []byte(`a`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 6, Line: 1, Column: 7},
|
||||
End: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateSeqEnd,
|
||||
Bytes: []byte(`}`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 7, Line: 1, Column: 8},
|
||||
End: zcl.Pos{Byte: 8, Line: 1, Column: 9},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenStringLit,
|
||||
Bytes: []byte(` foo`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 8, Line: 1, Column: 9},
|
||||
End: zcl.Pos{Byte: 12, Line: 1, Column: 13},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenCQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 12, Line: 1, Column: 13},
|
||||
End: zcl.Pos{Byte: 13, Line: 1, Column: 14},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenTemplateSeqEnd,
|
||||
Bytes: []byte(`}`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 13, Line: 1, Column: 14},
|
||||
End: zcl.Pos{Byte: 14, Line: 1, Column: 15},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenCQuote,
|
||||
Bytes: []byte(`"`),
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 14, Line: 1, Column: 15},
|
||||
End: zcl.Pos{Byte: 15, Line: 1, Column: 16},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: TokenEOF,
|
||||
Bytes: []byte{},
|
||||
Range: zcl.Range{
|
||||
Start: zcl.Pos{Byte: 15, Line: 1, Column: 16},
|
||||
End: zcl.Pos{Byte: 15, Line: 1, Column: 16},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Combinations
|
||||
{
|
||||
` (1 + 2) * 3 `,
|
||||
|
Loading…
Reference in New Issue
Block a user