replaced Token with Lexeme protocol on TemplateSyntaxError

This commit is contained in:
Ilya Puchka
2017-10-07 20:54:42 +02:00
parent 6300dbc7bf
commit 69cd8e4d3b
6 changed files with 52 additions and 69 deletions

View File

@@ -17,3 +17,29 @@ public class TemplateDoesNotExist: Error, CustomStringConvertible {
return "Template named `\(templates)` does not exist. No loaders found"
}
}
public struct TemplateSyntaxError : Error, Equatable, CustomStringConvertible {
public let description:String
var lexeme: Lexeme?
public init(_ description:String) {
self.description = description
}
public static func ==(lhs:TemplateSyntaxError, rhs:TemplateSyntaxError) -> Bool {
return lhs.description == rhs.description
}
}
extension Range where Bound == String.Index {
internal static var unknown: Range {
return "".range
}
}
extension String {
var range: Range<String.Index> {
return startIndex..<endIndex
}
}

View File

@@ -53,8 +53,29 @@ struct Lexer {
return tokens
}
func lexemeLine(_ lexeme: Lexeme) -> (content: String, number: Int, offset: String.IndexDistance) {
var lineNumber: Int = 0
var offset = 0
var lineContent = ""
templateString.enumerateLines { (line, stop) in
lineNumber += 1
lineContent = line
if let rangeOfLine = self.templateString.range(of: line), rangeOfLine.contains(lexeme.range.lowerBound) {
offset = self.templateString.distance(from: rangeOfLine.lowerBound, to:
lexeme.range.lowerBound)
stop = true
}
}
return (lineContent, lineNumber, offset)
}
}
protocol Lexeme {
var range: Range<String.Index> { get }
}
class Scanner {
let _content: String //stores original content
@@ -163,20 +184,4 @@ extension String {
return String(self[first..<last])
}
func lineAndPosition(at range: Range<String.Index>) -> (content: String, number: Int, offset: String.IndexDistance) {
var lineNumber: Int = 0
var offset = 0
var lineContent = ""
enumerateLines { (line, stop) in
lineNumber += 1
lineContent = line
if let rangeOfLine = self.range(of: line), rangeOfLine.contains(range.lowerBound) {
offset = self.distance(from: rangeOfLine.lowerBound, to: range.lowerBound)
stop = true
}
}
return (lineContent, lineNumber, offset)
}
}

View File

@@ -1,32 +1,5 @@
import Foundation
public struct TemplateSyntaxError : Error, Equatable, CustomStringConvertible {
public let description:String
public var token: Token?
public init(_ description:String) {
self.description = description
}
public func contextAwareError(templateName: String?, templateContent: String) -> TemplateSyntaxError? {
guard let token = token, token.range != .unknown else { return nil }
let templateName = templateName.map({ "\($0):" }) ?? ""
let (line, lineNumber, offset) = templateContent.lineAndPosition(at: token.range)
let tokenContent = templateContent.substring(with: token.range)
let highlight = "\(String(Array(repeating: " ", count: offset)))^\(String(Array(repeating: "~", count: max(tokenContent.count - 1, 0))))"
let description = "\(templateName)\(lineNumber):\(offset): error: " + self.description + "\n\(line)\n\(highlight)\n"
return TemplateSyntaxError(description)
}
}
public func ==(lhs:TemplateSyntaxError, rhs:TemplateSyntaxError) -> Bool {
return lhs.description == rhs.description
}
public protocol NodeType {
/// Render the node in the given context
func render(_ context:Context) throws -> String

View File

@@ -53,8 +53,8 @@ public class TokenParser {
let node = try parser(self, token)
nodes.append(node)
} catch {
if var syntaxError = error as? TemplateSyntaxError, syntaxError.token == nil {
syntaxError.token = token
if var syntaxError = error as? TemplateSyntaxError, syntaxError.lexeme == nil {
syntaxError.lexeme = token
throw syntaxError
} else {
throw error

View File

@@ -68,17 +68,8 @@ open class Template: ExpressibleByStringLiteral {
func render(_ context: Context) throws -> String {
let context = context
let parser = TokenParser(tokens: tokens, environment: context.environment)
do {
let nodes = try parser.parse()
return try renderNodes(nodes, context)
} catch {
if let syntaxError = error as? TemplateSyntaxError,
let error = syntaxError.contextAwareError(templateName: name, templateContent: templateString) {
throw error
} else {
throw error
}
}
}
/// Render the given template

View File

@@ -40,19 +40,7 @@ extension String {
}
}
extension Range where Bound == String.Index {
internal static var unknown: Range {
return "".range
}
}
extension String {
var range: Range<String.Index> {
return startIndex..<endIndex
}
}
public enum Token : Equatable {
public enum Token : Equatable, Lexeme {
/// A token representing a piece of text.
case text(value: String, at: Range<String.Index>)