feat(for loop): Support range literals (#192)

This commit is contained in:
Ilya Puchka
2018-04-05 01:56:58 +01:00
committed by Kyle Fuller
parent 2e6a7215c5
commit fe01beb4bb
8 changed files with 131 additions and 16 deletions

View File

@@ -10,9 +10,15 @@ class ForNode : NodeType {
class func parse(_ parser:TokenParser, token:Token) throws -> NodeType {
let components = token.components()
guard components.count >= 3 && components[2] == "in" &&
(components.count == 4 || (components.count >= 6 && components[4] == "where")) else {
throw TemplateSyntaxError("'for' statements should use the following 'for x in y where condition' `\(token.contents)`.")
func hasToken(_ token: String, at index: Int) -> Bool {
return components.count > (index + 1) && components[index] == token
}
func endsOrHasToken(_ token: String, at index: Int) -> Bool {
return components.count == index || hasToken(token, at: index)
}
guard hasToken("in", at: 2) && endsOrHasToken("where", at: 4) else {
throw TemplateSyntaxError("'for' statements should use the syntax: `for <x> in <y> [where <condition>]")
}
let loopVariables = components[1].characters
@@ -20,8 +26,6 @@ class ForNode : NodeType {
.map(String.init)
.map { $0.trimmingCharacters(in: CharacterSet.whitespaces) }
let variable = components[3]
var emptyNodes = [NodeType]()
let forNodes = try parser.parse(until(["endfor", "empty"]))
@@ -35,14 +39,13 @@ class ForNode : NodeType {
_ = parser.nextToken()
}
let filter = try parser.compileFilter(variable)
let `where`: Expression?
if components.count >= 6 {
`where` = try parseExpression(components: Array(components.suffix(from: 5)), tokenParser: parser)
} else {
`where` = nil
}
return ForNode(resolvable: filter, loopVariables: loopVariables, nodes: forNodes, emptyNodes:emptyNodes, where: `where`)
let resolvable = try parser.compileResolvable(components[3])
let `where` = hasToken("where", at: 4)
? try parseExpression(components: Array(components.suffix(from: 5)), tokenParser: parser)
: nil
return ForNode(resolvable: resolvable, loopVariables: loopVariables, nodes: forNodes, emptyNodes:emptyNodes, where: `where`)
}
init(resolvable: Resolvable, loopVariables: [String], nodes:[NodeType], emptyNodes:[NodeType], where: Expression? = nil) {