From da3b49d9ed890b5c53d40bb88b441912a9538f00 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sat, 25 Oct 2014 13:03:58 +0100 Subject: [PATCH] Complete lexer implementation --- Stencil/Lexer.swift | 44 ++++++++++++++++++++++++++++++++++- StencilTests/LexerTests.swift | 26 +++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/Stencil/Lexer.swift b/Stencil/Lexer.swift index 76819cd..133daaa 100644 --- a/Stencil/Lexer.swift +++ b/Stencil/Lexer.swift @@ -10,12 +10,54 @@ import Foundation public struct Lexer { public let templateString:String + let regex = NSRegularExpression(pattern: "(\\{\\{.*\\}\\}|\\{%.*%\\}|\\{#.*#\\})", options: nil, error: nil) public init(templateString:String) { self.templateString = templateString } + func createToken(string:String) -> Token { + func strip() -> String { + return string[string.startIndex.successor().successor().. [Token] { - return [Token.Text(value: templateString)] + // Unfortunately NSRegularExpression doesn't have a split. + // So here's a really terrible implementation + + var tokens = [Token]() + + let range = NSMakeRange(0, countElements(templateString)) + var lastIndex = 0 + let nsTemplateString = templateString as NSString + regex.enumerateMatchesInString(templateString, options: nil, range: range) { (result, flags, b) in + if result.range.location != lastIndex { + let previousMatch = nsTemplateString.substringWithRange(NSMakeRange(lastIndex, result.range.location)) + tokens.append(self.createToken(previousMatch)) + } + + let match = nsTemplateString.substringWithRange(result.range) + tokens.append(self.createToken(match)) + + lastIndex = result.range.location + result.range.length + } + + if lastIndex < countElements(templateString) { + let substring = (templateString as NSString).substringFromIndex(lastIndex) + tokens.append(Token.Text(value: substring)) + } + + return tokens } } diff --git a/StencilTests/LexerTests.swift b/StencilTests/LexerTests.swift index 3394445..dc13be7 100644 --- a/StencilTests/LexerTests.swift +++ b/StencilTests/LexerTests.swift @@ -20,4 +20,30 @@ class LexerTests: XCTestCase { XCTAssertEqual(tokens.first!, Token.Text(value: "Hello World")) } + func testTokenizeComment() { + let lexer = Lexer(templateString:"{# Comment #}") + let tokens = lexer.tokenize() + + XCTAssertEqual(tokens.count, 1) + XCTAssertEqual(tokens.first!, Token.Comment(value: "Comment")) + } + + func testTokenizeVariable() { + let lexer = Lexer(templateString:"{{ Variable }}") + let tokens = lexer.tokenize() + + XCTAssertEqual(tokens.count, 1) + XCTAssertEqual(tokens.first!, Token.Variable(value: "Variable")) + } + + func testTokenizeMixture() { + let lexer = Lexer(templateString:"My name is {{ name }}.") + let tokens = lexer.tokenize() + + XCTAssertEqual(tokens.count, 3) + XCTAssertEqual(tokens[0], Token.Text(value: "My name is ")) + XCTAssertEqual(tokens[1], Token.Variable(value: "name")) + XCTAssertEqual(tokens[2], Token.Text(value: ".")) + } + }