import CoreGraphics import Foundation let VERTEX_PATTERN = "([^\\(]+?)[\\s]*\\([\\s]*([0-9]+.?[0-9]*)[\\s]*,[\\s]*([0-9]+.?[0-9]*)[\\s]*\\)" let EDGE_PATTERN = "(.+?)[\\s]*->[\\s]*(.+)" struct ParsedMap { let vertices: [Vertex] let edges: [MapEdge] } struct Vertex { let id: Int let label: String let position: CGPoint } struct MapEdge { let id: Int let origin: CGPoint let destination: CGPoint } // Extracts the vertices from the text func parseVertices(_ text: String) -> [String: CGPoint] { var result: [String: CGPoint] = [:] let regex = try! NSRegularExpression(pattern: VERTEX_PATTERN, options: .caseInsensitive) let lines = text.split(whereSeparator: \.isNewline) for line in lines { let range = NSRange(location: 0, length: line.utf16.count) let matches = regex.matches(in: String(line), options: [], range: range) if matches.count > 0 && matches[0].numberOfRanges == 4{ let match = matches[0]; let key = String(line[Range(match.range(at: 1), in: line)!]) let xString = String(line[Range(match.range(at: 2), in: line)!]) let yString = String(line[Range(match.range(at: 3), in: line)!]) let x = CGFloat(truncating: NumberFormatter().number(from:xString) ?? 0.0) let y = CGFloat(truncating: NumberFormatter().number(from:yString) ?? 0.0) let point = CGPoint(x: x, y: y) result[key] = point } } return result } // Extracts the edges from the text func parseEdges(_ text: String, vertices: [String: CGPoint]) -> [MapEdge] { var result: [MapEdge] = [] let regex = try! NSRegularExpression(pattern: EDGE_PATTERN, options: .caseInsensitive) let lines = text.split(whereSeparator: \.isNewline) for (index, line) in lines.enumerated() { let range = NSRange(location: 0, length: line.utf16.count) let matches = regex.matches(in: String(line), options: [], range: range) if matches.count > 0 && matches[0].numberOfRanges == 3 { let match = matches[0]; let vertexA = String(line[Range(match.range(at: 1), in: line)!]) let vertexB = String(line[Range(match.range(at: 2), in: line)!]) if let origin = vertices[vertexA] { if let destination = vertices[vertexB] { result.append(MapEdge(id: index, origin: origin, destination: destination)) } } } } return result } // Converts vetex dictionary to array func mapVertices(_ vertices: [String: CGPoint]) -> [Vertex] { var i = 0 return vertices.map { label, position in i += 1; return Vertex(id: i, label: label, position: position) } } extension Map { func parse() -> ParsedMap { let text = self.content ?? "" let vertices = parseVertices(text) let mappedVertices = mapVertices(vertices) let edges = parseEdges(text, vertices: vertices) print(mappedVertices) print(edges) return ParsedMap(vertices: mappedVertices, edges: edges) } }