hcl/scanner: scan heredocs
This commit is contained in:
parent
e5d4045cf0
commit
82ad2beb52
@ -174,6 +174,9 @@ func (s *Scanner) Scan() token.Token {
|
|||||||
ch = s.scanMantissa(ch)
|
ch = s.scanMantissa(ch)
|
||||||
ch = s.scanExponent(ch)
|
ch = s.scanExponent(ch)
|
||||||
}
|
}
|
||||||
|
case '<':
|
||||||
|
tok = token.HEREDOC
|
||||||
|
s.scanHeredoc()
|
||||||
case '[':
|
case '[':
|
||||||
tok = token.LBRACK
|
tok = token.LBRACK
|
||||||
case ']':
|
case ']':
|
||||||
@ -371,6 +374,67 @@ func (s *Scanner) scanExponent(ch rune) rune {
|
|||||||
return ch
|
return ch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scanHeredoc scans a heredoc string.
|
||||||
|
func (s *Scanner) scanHeredoc() {
|
||||||
|
// Scan the second '<' in example: '<<EOF'
|
||||||
|
if s.next() != '<' {
|
||||||
|
s.err("heredoc expected second '<', didn't see it")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the original offset so we can read just the heredoc ident
|
||||||
|
offs := s.srcPos.Offset
|
||||||
|
|
||||||
|
// Scan the identifier
|
||||||
|
ch := s.next()
|
||||||
|
for isLetter(ch) {
|
||||||
|
ch = s.next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we reached an EOF then that is not good
|
||||||
|
if ch == eof {
|
||||||
|
s.err("heredoc not terminated")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we didn't reach a newline then that is also not good
|
||||||
|
if ch != '\n' {
|
||||||
|
s.err("invalid characters in heredoc anchor")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the identifier
|
||||||
|
identBytes := s.src[offs : s.srcPos.Offset-s.lastCharLen]
|
||||||
|
|
||||||
|
// Read the actual string value
|
||||||
|
lineStart := s.srcPos.Offset
|
||||||
|
for {
|
||||||
|
ch := s.next()
|
||||||
|
|
||||||
|
// Special newline handling.
|
||||||
|
if ch == '\n' {
|
||||||
|
// Math is fast, so we first compare the byte counts to
|
||||||
|
// see if we have a chance of seeing the same identifier. If those
|
||||||
|
// match, then we compare the string values directly.
|
||||||
|
lineBytesLen := s.srcPos.Offset - s.lastCharLen - lineStart
|
||||||
|
if lineBytesLen == len(identBytes) &&
|
||||||
|
bytes.Equal(identBytes, s.src[lineStart:s.srcPos.Offset-s.lastCharLen]) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not an anchor match, record the start of a new line
|
||||||
|
lineStart = s.srcPos.Offset
|
||||||
|
}
|
||||||
|
|
||||||
|
if ch == eof {
|
||||||
|
s.err("heredoc not terminated")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// scanString scans a quoted string
|
// scanString scans a quoted string
|
||||||
func (s *Scanner) scanString() {
|
func (s *Scanner) scanString() {
|
||||||
braces := 0
|
braces := 0
|
||||||
|
@ -71,6 +71,9 @@ var tokenLists = map[string][]tokenPair{
|
|||||||
{token.IDENT, "foo६४"},
|
{token.IDENT, "foo६४"},
|
||||||
{token.IDENT, "bar9876"},
|
{token.IDENT, "bar9876"},
|
||||||
},
|
},
|
||||||
|
"heredoc": []tokenPair{
|
||||||
|
{token.HEREDOC, "<<EOF\nhello\nworld\nEOF"},
|
||||||
|
},
|
||||||
"string": []tokenPair{
|
"string": []tokenPair{
|
||||||
{token.STRING, `" "`},
|
{token.STRING, `" "`},
|
||||||
{token.STRING, `"a"`},
|
{token.STRING, `"a"`},
|
||||||
@ -229,6 +232,7 @@ var orderedTokenLists = []string{
|
|||||||
"operator",
|
"operator",
|
||||||
"bool",
|
"bool",
|
||||||
"ident",
|
"ident",
|
||||||
|
"heredoc",
|
||||||
"string",
|
"string",
|
||||||
"number",
|
"number",
|
||||||
"float",
|
"float",
|
||||||
|
@ -37,10 +37,11 @@ const (
|
|||||||
identifier_end
|
identifier_end
|
||||||
|
|
||||||
operator_beg
|
operator_beg
|
||||||
LBRACK // [
|
LBRACK // [
|
||||||
LBRACE // {
|
LBRACE // {
|
||||||
COMMA // ,
|
COMMA // ,
|
||||||
PERIOD // .
|
PERIOD // .
|
||||||
|
HEREDOC // <<
|
||||||
|
|
||||||
RBRACK // ]
|
RBRACK // ]
|
||||||
RBRACE // }
|
RBRACE // }
|
||||||
@ -63,10 +64,11 @@ var tokens = [...]string{
|
|||||||
BOOL: "BOOL",
|
BOOL: "BOOL",
|
||||||
STRING: "STRING",
|
STRING: "STRING",
|
||||||
|
|
||||||
LBRACK: "LBRACK",
|
LBRACK: "LBRACK",
|
||||||
LBRACE: "LBRACE",
|
LBRACE: "LBRACE",
|
||||||
COMMA: "COMMA",
|
COMMA: "COMMA",
|
||||||
PERIOD: "PERIOD",
|
PERIOD: "PERIOD",
|
||||||
|
HEREDOC: "HEREDOC",
|
||||||
|
|
||||||
RBRACK: "RBRACK",
|
RBRACK: "RBRACK",
|
||||||
RBRACE: "RBRACE",
|
RBRACE: "RBRACE",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user