@@ -84,8 +84,8 @@ public class VariableNode : Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class NowNode : Node {
|
public class NowNode : Node {
|
||||||
public class func parse(parser:TokenParser, token:Token) -> Node {
|
public class func parse(parser:TokenParser, token:Token) -> (node:Node?, error:Error?) {
|
||||||
return NowNode()
|
return (NowNode(), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func render(context: Context) -> (String?, Error?) {
|
public func render(context: Context) -> (String?, Error?) {
|
||||||
@@ -99,29 +99,41 @@ public class ForNode : Node {
|
|||||||
let loopVariable:String
|
let loopVariable:String
|
||||||
let nodes:[Node]
|
let nodes:[Node]
|
||||||
|
|
||||||
public class func parse(parser:TokenParser, token:Token) -> Node {
|
public class func parse(parser:TokenParser, token:Token) -> (node:Node?, error:Error?) {
|
||||||
let components = token.components()
|
let components = token.components()
|
||||||
let count = countElements(components)
|
let count = countElements(components)
|
||||||
|
|
||||||
if count == 4 && components[2] == "in" {
|
if count == 4 && components[2] == "in" {
|
||||||
let loopVariable = components[1]
|
let loopVariable = components[1]
|
||||||
let variable = components[3]
|
let variable = components[3]
|
||||||
let nodes = parser.parse(until(["endfor", "empty"]))
|
let (nodes, error) = parser.parse(until(["endfor", "empty"]))
|
||||||
var emptyNodes = [Node]()
|
var emptyNodes = [Node]()
|
||||||
|
|
||||||
|
if let error = error {
|
||||||
|
return (nil, error)
|
||||||
|
}
|
||||||
|
|
||||||
if let token = parser.nextToken() {
|
if let token = parser.nextToken() {
|
||||||
if token.contents == "empty" {
|
if token.contents == "empty" {
|
||||||
emptyNodes = parser.parse(until(["endfor"]))
|
let (nodes, error) = parser.parse(until(["endfor"]))
|
||||||
parser.nextToken()
|
parser.nextToken()
|
||||||
|
|
||||||
|
if let error = error {
|
||||||
|
return (nil, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let nodes = nodes {
|
||||||
|
emptyNodes = nodes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ForNode(variable: variable, loopVariable: loopVariable, nodes: nodes, emptyNodes:emptyNodes)
|
return (ForNode(variable: variable, loopVariable: loopVariable, nodes: nodes!, emptyNodes:emptyNodes), nil)
|
||||||
} else {
|
} else {
|
||||||
// TODO error
|
// TODO error
|
||||||
}
|
}
|
||||||
|
|
||||||
return TextNode(text: "TODO return some error")
|
return (TextNode(text: "TODO return some error"), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(variable:String, loopVariable:String, nodes:[Node], emptyNodes:[Node]) {
|
public init(variable:String, loopVariable:String, nodes:[Node], emptyNodes:[Node]) {
|
||||||
@@ -160,36 +172,59 @@ public class IfNode : Node {
|
|||||||
public let trueNodes:[Node]
|
public let trueNodes:[Node]
|
||||||
public let falseNodes:[Node]
|
public let falseNodes:[Node]
|
||||||
|
|
||||||
public class func parse(parser:TokenParser, token:Token) -> Node {
|
public class func parse(parser:TokenParser, token:Token) -> (node:Node?, error:Error?) {
|
||||||
let variable = token.components()[1]
|
let variable = token.components()[1]
|
||||||
|
|
||||||
let trueNodes = parser.parse(until(["endif", "else"]))
|
let (trueNodes, error) = parser.parse(until(["endif", "else"]))
|
||||||
|
if let error = error {
|
||||||
|
return (nil, error)
|
||||||
|
}
|
||||||
|
|
||||||
var falseNodes = [Node]()
|
var falseNodes = [Node]()
|
||||||
|
|
||||||
if let token = parser.nextToken() {
|
if let token = parser.nextToken() {
|
||||||
if token.contents == "else" {
|
if token.contents == "else" {
|
||||||
falseNodes = parser.parse(until(["endif"]))
|
let (nodes, error) = parser.parse(until(["endif"]))
|
||||||
parser.nextToken()
|
parser.nextToken()
|
||||||
|
|
||||||
|
if let error = error {
|
||||||
|
return (nil, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let nodes = nodes {
|
||||||
|
falseNodes = nodes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return IfNode(variable: variable, trueNodes: trueNodes, falseNodes: falseNodes)
|
return (IfNode(variable: variable, trueNodes: trueNodes!, falseNodes: falseNodes), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
public class func parse_ifnot(parser:TokenParser, token:Token) -> Node {
|
public class func parse_ifnot(parser:TokenParser, token:Token) -> (node:Node?, error:Error?) {
|
||||||
let variable = token.components()[1]
|
let variable = token.components()[1]
|
||||||
|
|
||||||
let falseNodes = parser.parse(until(["endif", "else"]))
|
let (falseNodes, error) = parser.parse(until(["endif", "else"]))
|
||||||
|
if let error = error {
|
||||||
|
return (nil, error)
|
||||||
|
}
|
||||||
var trueNodes = [Node]()
|
var trueNodes = [Node]()
|
||||||
|
|
||||||
if let token = parser.nextToken() {
|
if let token = parser.nextToken() {
|
||||||
if token.contents == "else" {
|
if token.contents == "else" {
|
||||||
trueNodes = parser.parse(until(["endif"]))
|
let (nodes, error) = parser.parse(until(["endif"]))
|
||||||
|
if let error = error {
|
||||||
|
return (nil, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let nodes = nodes {
|
||||||
|
trueNodes = nodes
|
||||||
|
}
|
||||||
|
|
||||||
parser.nextToken()
|
parser.nextToken()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return IfNode(variable: variable, trueNodes: trueNodes, falseNodes: falseNodes)
|
return (IfNode(variable: variable, trueNodes: trueNodes, falseNodes: falseNodes!), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(variable:String, trueNodes:[Node], falseNodes:[Node]) {
|
public init(variable:String, trueNodes:[Node], falseNodes:[Node]) {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public func until(tags:[String])(parser:TokenParser, token:Token) -> Bool {
|
|||||||
|
|
||||||
public class TokenParser {
|
public class TokenParser {
|
||||||
private var tokens:[Token]
|
private var tokens:[Token]
|
||||||
private var tags = Dictionary<String, ((TokenParser, Token) -> (Node))>()
|
private var tags = Dictionary<String, ((TokenParser, Token) -> ((node:Node?, error:Error?)))>()
|
||||||
|
|
||||||
public init(tokens:[Token]) {
|
public init(tokens:[Token]) {
|
||||||
self.tokens = tokens
|
self.tokens = tokens
|
||||||
@@ -32,11 +32,11 @@ public class TokenParser {
|
|||||||
tags["ifnot"] = IfNode.parse_ifnot
|
tags["ifnot"] = IfNode.parse_ifnot
|
||||||
}
|
}
|
||||||
|
|
||||||
public func parse() -> [Node] {
|
public func parse() -> (nodes:[Node]?, error:Error?) {
|
||||||
return parse(nil)
|
return parse(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func parse(parse_until:((parser:TokenParser, token:Token) -> (Bool))?) -> [Node] {
|
public func parse(parse_until:((parser:TokenParser, token:Token) -> (Bool))?) -> (nodes:[Node]?, error:Error?) {
|
||||||
var nodes = [Node]()
|
var nodes = [Node]()
|
||||||
|
|
||||||
while tokens.count > 0 {
|
while tokens.count > 0 {
|
||||||
@@ -53,14 +53,21 @@ public class TokenParser {
|
|||||||
if let parse_until = parse_until {
|
if let parse_until = parse_until {
|
||||||
if parse_until(parser: self, token: token) {
|
if parse_until(parser: self, token: token) {
|
||||||
prependToken(token)
|
prependToken(token)
|
||||||
return nodes
|
return (nodes, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let tag = tag {
|
if let tag = tag {
|
||||||
if let parser = self.tags[tag] {
|
if let parser = self.tags[tag] {
|
||||||
let node = parser(self, token)
|
let (node, error) = parser(self, token)
|
||||||
nodes.append(node)
|
|
||||||
|
if let error = error {
|
||||||
|
return (nil, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let node = node {
|
||||||
|
nodes.append(node)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .Comment(let value):
|
case .Comment(let value):
|
||||||
@@ -68,7 +75,7 @@ public class TokenParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodes
|
return (nodes, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func nextToken() -> Token? {
|
public func nextToken() -> Token? {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class Template {
|
public class Template {
|
||||||
let nodes:[Node]
|
let parser:TokenParser
|
||||||
|
|
||||||
public convenience init(named:String) {
|
public convenience init(named:String) {
|
||||||
self.init(named:named, inBundle:nil)
|
self.init(named:named, inBundle:nil)
|
||||||
@@ -36,11 +36,18 @@ public class Template {
|
|||||||
public init(templateString:String) {
|
public init(templateString:String) {
|
||||||
let lexer = Lexer(templateString: templateString)
|
let lexer = Lexer(templateString: templateString)
|
||||||
let tokens = lexer.tokenize()
|
let tokens = lexer.tokenize()
|
||||||
let parser = TokenParser(tokens: tokens)
|
parser = TokenParser(tokens: tokens)
|
||||||
nodes = parser.parse()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func render(context:Context) -> (string:String?, error:Error?) {
|
public func render(context:Context) -> (string:String?, error:Error?) {
|
||||||
return renderNodes(nodes, context)
|
let (nodes, error) = parser.parse()
|
||||||
|
|
||||||
|
if let error = error {
|
||||||
|
return (nil, error)
|
||||||
|
} else if let nodes = nodes {
|
||||||
|
return renderNodes(nodes, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (nil, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,12 +101,13 @@ class IfNodeTests: NodeTests {
|
|||||||
]
|
]
|
||||||
|
|
||||||
let parser = TokenParser(tokens: tokens)
|
let parser = TokenParser(tokens: tokens)
|
||||||
let nodes = parser.parse()
|
let (nodes, error) = parser.parse()
|
||||||
let node = nodes.first! as IfNode
|
let node = nodes!.first! as IfNode
|
||||||
let trueNode = node.trueNodes.first! as TextNode
|
let trueNode = node.trueNodes.first! as TextNode
|
||||||
let falseNode = node.falseNodes.first! as TextNode
|
let falseNode = node.falseNodes.first! as TextNode
|
||||||
|
|
||||||
XCTAssertEqual(nodes.count, 1)
|
XCTAssertTrue(error == nil)
|
||||||
|
XCTAssertEqual(nodes!.count, 1)
|
||||||
XCTAssertEqual(node.variable.variable, "value")
|
XCTAssertEqual(node.variable.variable, "value")
|
||||||
XCTAssertEqual(node.trueNodes.count, 1)
|
XCTAssertEqual(node.trueNodes.count, 1)
|
||||||
XCTAssertEqual(trueNode.text, "true")
|
XCTAssertEqual(trueNode.text, "true")
|
||||||
@@ -124,12 +125,13 @@ class IfNodeTests: NodeTests {
|
|||||||
]
|
]
|
||||||
|
|
||||||
let parser = TokenParser(tokens: tokens)
|
let parser = TokenParser(tokens: tokens)
|
||||||
let nodes = parser.parse()
|
let (nodes, error) = parser.parse()
|
||||||
let node = nodes.first! as IfNode
|
let node = nodes!.first! as IfNode
|
||||||
let trueNode = node.trueNodes.first! as TextNode
|
let trueNode = node.trueNodes.first! as TextNode
|
||||||
let falseNode = node.falseNodes.first! as TextNode
|
let falseNode = node.falseNodes.first! as TextNode
|
||||||
|
|
||||||
XCTAssertEqual(nodes.count, 1)
|
XCTAssertTrue(error == nil)
|
||||||
|
XCTAssertEqual(nodes!.count, 1)
|
||||||
XCTAssertEqual(node.variable.variable, "value")
|
XCTAssertEqual(node.variable.variable, "value")
|
||||||
XCTAssertEqual(node.trueNodes.count, 1)
|
XCTAssertEqual(node.trueNodes.count, 1)
|
||||||
XCTAssertEqual(trueNode.text, "true")
|
XCTAssertEqual(trueNode.text, "true")
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ class TokenParserTests: XCTestCase {
|
|||||||
Token.Text(value: "Hello World")
|
Token.Text(value: "Hello World")
|
||||||
])
|
])
|
||||||
|
|
||||||
let nodes = parser.parse()
|
let (nodes, error) = parser.parse()
|
||||||
let node = nodes.first as TextNode!
|
let node = nodes!.first as TextNode!
|
||||||
|
|
||||||
XCTAssertEqual(nodes.count, 1)
|
XCTAssertTrue(error == nil)
|
||||||
|
XCTAssertEqual(nodes!.count, 1)
|
||||||
XCTAssertEqual(node.text, "Hello World")
|
XCTAssertEqual(node.text, "Hello World")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,11 +29,12 @@ class TokenParserTests: XCTestCase {
|
|||||||
Token.Variable(value: "name")
|
Token.Variable(value: "name")
|
||||||
])
|
])
|
||||||
|
|
||||||
let nodes = parser.parse()
|
let (nodes, error) = parser.parse()
|
||||||
let node = nodes.first as VariableNode!
|
let node = nodes!.first as VariableNode!
|
||||||
let variable = node.variable
|
let variable = node.variable
|
||||||
|
|
||||||
XCTAssertEqual(nodes.count, 1)
|
XCTAssertTrue(error == nil)
|
||||||
|
XCTAssertEqual(nodes!.count, 1)
|
||||||
XCTAssertEqual(variable, Variable("name"))
|
XCTAssertEqual(variable, Variable("name"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,9 +43,9 @@ class TokenParserTests: XCTestCase {
|
|||||||
Token.Comment(value: "Secret stuff!")
|
Token.Comment(value: "Secret stuff!")
|
||||||
])
|
])
|
||||||
|
|
||||||
let nodes = parser.parse()
|
let (nodes, error) = parser.parse()
|
||||||
|
|
||||||
XCTAssertEqual(nodes.count, 0)
|
XCTAssertEqual(nodes!.count, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testParsingTagToken() {
|
func testParsingTagToken() {
|
||||||
@@ -51,8 +53,9 @@ class TokenParserTests: XCTestCase {
|
|||||||
Token.Block(value: "now"),
|
Token.Block(value: "now"),
|
||||||
])
|
])
|
||||||
|
|
||||||
let nodes = parser.parse()
|
let (nodes, error) = parser.parse()
|
||||||
let node = nodes.first as NowNode!
|
let node = nodes!.first as NowNode!
|
||||||
XCTAssertEqual(nodes.count, 1)
|
XCTAssertTrue(error == nil)
|
||||||
|
XCTAssertEqual(nodes!.count, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user