refactor(if node): Support multiple conditions

This commit is contained in:
Kyle Fuller
2017-03-03 09:25:16 +00:00
parent 19e4f6e506
commit 233dcfc59a
2 changed files with 110 additions and 45 deletions

View File

@@ -160,30 +160,48 @@ func parseExpression(components: [String], tokenParser: TokenParser) throws -> E
}
/// Represents an if condition and the associated nodes when the condition
/// evaluates
final class IfCondition {
let expression: Expression?
let nodes: [NodeType]
init(expression: Expression?, nodes: [NodeType]) {
self.expression = expression
self.nodes = nodes
}
func render(_ context: Context) throws -> String {
return try context.push {
return try renderNodes(nodes, context)
}
}
}
class IfNode : NodeType {
let expression: Expression
let trueNodes: [NodeType]
let falseNodes: [NodeType]
let conditions: [IfCondition]
class func parse(_ parser: TokenParser, token: Token) throws -> NodeType {
var components = token.components()
components.removeFirst()
var trueNodes = [NodeType]()
var falseNodes = [NodeType]()
trueNodes = try parser.parse(until(["endif", "else"]))
var conditions: [IfCondition] = []
let expression = try parseExpression(components: components, tokenParser: parser)
let nodes = try parser.parse(until(["endif", "else"]))
conditions.append(IfCondition(expression: expression, nodes: nodes))
guard let token = parser.nextToken() else {
throw TemplateSyntaxError("`endif` was not found.")
}
if token.contents == "else" {
falseNodes = try parser.parse(until(["endif"]))
conditions.append(IfCondition(expression: nil, nodes: try parser.parse(until(["endif"]))))
_ = parser.nextToken()
}
let expression = try parseExpression(components: components, tokenParser: parser)
return IfNode(expression: expression, trueNodes: trueNodes, falseNodes: falseNodes)
return IfNode(conditions: conditions)
}
class func parse_ifnot(_ parser: TokenParser, token: Token) throws -> NodeType {
@@ -207,24 +225,29 @@ class IfNode : NodeType {
}
let expression = try parseExpression(components: components, tokenParser: parser)
return IfNode(expression: expression, trueNodes: trueNodes, falseNodes: falseNodes)
return IfNode(conditions: [
IfCondition(expression: expression, nodes: trueNodes),
IfCondition(expression: nil, nodes: falseNodes),
])
}
init(expression: Expression, trueNodes: [NodeType], falseNodes: [NodeType]) {
self.expression = expression
self.trueNodes = trueNodes
self.falseNodes = falseNodes
init(conditions: [IfCondition]) {
self.conditions = conditions
}
func render(_ context: Context) throws -> String {
let truthy = try expression.evaluate(context: context)
for condition in conditions {
if let expression = condition.expression {
let truthy = try expression.evaluate(context: context)
return try context.push {
if truthy {
return try renderNodes(trueNodes, context)
if truthy {
return try condition.render(context)
}
} else {
return try renderNodes(falseNodes, context)
return try condition.render(context)
}
}
return ""
}
}