1
0
mirror of https://github.com/danog/liquid.git synced 2024-12-11 16:50:38 +01:00
liquid/parser/scanner.go
2017-07-16 14:15:11 -04:00

55 lines
1.4 KiB
Go

package parser
import (
"regexp"
"strings"
)
var tokenMatcher = regexp.MustCompile(`{{-?\s*(.+?)\s*-?}}|{%-?\s*(\w+)(?:\s+((?:[^%]|%[^}])+?))?\s*-?%}`)
// Scan breaks a string into a sequence of Tokens.
func Scan(data string, loc SourceLoc) (tokens []Token) {
// TODO error on unterminated {{ and {%
// TODO probably an error when a tag contains a {{ or {%, at least outside of a string
p, pe := 0, len(data)
for _, m := range tokenMatcher.FindAllStringSubmatchIndex(data, -1) {
ts, te := m[0], m[1]
if p < ts {
tokens = append(tokens, Token{Type: TextTokenType, SourceLoc: loc, Source: data[p:ts]})
loc.LineNo += strings.Count(data[p:ts], "\n")
}
source := data[ts:te]
switch data[ts+1] {
case '{':
tok := Token{
Type: ObjTokenType,
SourceLoc: loc,
Source: source,
Args: data[m[2]:m[3]],
TrimLeft: source[2] == '-',
TrimRight: source[len(source)-3] == '-',
}
tokens = append(tokens, tok)
case '%':
tok := Token{
Type: TagTokenType,
SourceLoc: loc,
Source: source,
Name: data[m[4]:m[5]],
TrimLeft: source[2] == '-',
TrimRight: source[len(source)-3] == '-',
}
if m[6] > 0 {
tok.Args = data[m[6]:m[7]]
}
tokens = append(tokens, tok)
}
loc.LineNo += strings.Count(source, "\n")
p = te
}
if p < pe {
tokens = append(tokens, Token{Type: TextTokenType, SourceLoc: loc, Source: data[p:]})
}
return tokens
}