Udra.swift 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. //
  2. // PArser.swift
  3. // IBAnimatable
  4. //
  5. // Created by phimage on 06/05/2019.
  6. // Copyright © 2019 IBAnimatable. All rights reserved.
  7. //
  8. import Foundation
  9. /// User defined runtime attributes parsing.
  10. class Udra { //swiftlint:disable:this type_body_length
  11. // MARK: - Token
  12. /// User defined runtime attributes Tokens.
  13. enum Token {
  14. case identifier(String, CountableRange<Int>)
  15. case number(Double, CountableRange<Int>)
  16. case comma(CountableRange<Int>)
  17. case parenthesisOpen(CountableRange<Int>)
  18. case parenthesisClose(CountableRange<Int>)
  19. case bracketOpen(CountableRange<Int>)
  20. case bracketClose(CountableRange<Int>)
  21. case `operator`(Operator, CountableRange<Int>)
  22. case undefined(String, CountableRange<Int>)
  23. }
  24. enum Operator: String {
  25. case plus = "+"
  26. var precedence: Int {
  27. switch self {
  28. case .plus:
  29. return 10
  30. }
  31. }
  32. }
  33. // MARK: - Lexer
  34. /// User defined runtime attributes Lexer.
  35. class Lexer {
  36. typealias TokenBuilder = (String, CountableRange<Int>) -> Token? //swiftlint:disable:this nesting
  37. static let tokenStringList: [String: TokenBuilder] = [
  38. "[ \t\n]": { _, _ in nil }, // trim
  39. "[a-zA-Z][a-zA-Z0-9]*": ({ .identifier($0, $1) }),
  40. "\\-?[0-9.]+": ({ .number(Double($0)!, $1) }),
  41. "\\(": ({ .parenthesisOpen($1) }),
  42. "\\)": ({ .parenthesisClose($1) }),
  43. "\\[": ({ .bracketOpen($1) }),
  44. "\\]": ({ .bracketClose($1) }),
  45. "\\+": ({ .operator(Operator(rawValue: $0)!, $1) }),
  46. ",": ({ .comma($1) })
  47. ]
  48. typealias TokenRegularExpression = (NSRegularExpression, TokenBuilder) //swiftlint:disable:this nesting
  49. static let tokenList: [TokenRegularExpression] = tokenStringList.map {
  50. (try! NSRegularExpression(pattern: "^\($0.0)", options: []), $0.1) //swiftlint:disable:this force_try
  51. }
  52. /// Split input string to tokens
  53. static func tokenize(_ input: String) -> [Token] {
  54. var tokens = [Token]()
  55. var content = input
  56. while !content.isEmpty {
  57. var found = false
  58. for (regex, builder) in tokenList {
  59. if let (matched, range) = regex.matched(content) {
  60. if let token = builder(matched, range) {
  61. tokens.append(token)
  62. }
  63. // next content
  64. content = String(content[content.index(content.startIndex, offsetBy: matched.count)...])
  65. found = true
  66. break
  67. }
  68. }
  69. if !found {
  70. let index = content.index(content.startIndex, offsetBy: 1)
  71. let intIndex = content.distance(from: content.startIndex, to: index)
  72. tokens.append(.undefined(String(content[..<index]), intIndex..<intIndex + 1))
  73. content = String(content[index...])
  74. }
  75. }
  76. return tokens
  77. }
  78. }
  79. // MARK: - Nodes
  80. class Node: CustomStringConvertible, Equatable {
  81. var range: CountableRange<Int> = 0..<0
  82. let name: String
  83. init(name: String) {
  84. self.name = name
  85. }
  86. var description: String {
  87. return "\(type(of: self))(name: \"\(name)\")"
  88. }
  89. static func == (lhs: Node, rhs: Node) -> Bool {
  90. return lhs.description == rhs.description
  91. }
  92. }
  93. class VariableNode: Node {}
  94. class NumberNode: Node {
  95. let value: Double
  96. init(value: Double) {
  97. self.value = value
  98. super.init(name: "\(value)")
  99. }
  100. override var description: String {
  101. return "\(type(of: self))(value: \(value))"
  102. }
  103. static func + (lhs: NumberNode, rhs: NumberNode) -> NumberNode {
  104. return NumberNode(value: lhs.value + rhs.value)
  105. }
  106. }
  107. class ArrayNode: Node {
  108. let elements: [Node]
  109. init(elements: [Node]) {
  110. self.elements = elements
  111. super.init(name: "array")
  112. }
  113. override var description: String {
  114. return "\(elements))"
  115. }
  116. }
  117. class BinaryOperatorNode: Node {
  118. let `operator`: Operator
  119. let lhs: Node
  120. let rhs: Node
  121. init(operator: Operator, lhs: Node, rhs: Node) {
  122. self.operator = `operator`
  123. self.lhs = lhs
  124. self.rhs = rhs
  125. super.init(name: `operator`.rawValue)
  126. }
  127. override var description: String {
  128. return "\(type(of: self))(name: \"\(name)\", lhs: \(lhs), rhs: \(rhs))"
  129. }
  130. func evaluate() -> Any? {
  131. return self.operator.evaluate(lhs: lhs, rhs: rhs)
  132. }
  133. }
  134. class CallNode: Node {
  135. let arguments: [Node]
  136. init(name: String, arguments: [Node]) {
  137. self.arguments = arguments
  138. super.init(name: name)
  139. }
  140. override var description: String {
  141. return "\(type(of: self))(name: \"\(name)\", arguments: \(arguments))"
  142. }
  143. }
  144. // MARK: - Parser
  145. enum ParseError: Error {
  146. case unexpectToken
  147. case expectCharacter(Character)
  148. case expectExpression(Token)
  149. case expectExpressionList
  150. case undefinedOperator(String)
  151. }
  152. /// User defined runtimes attribues parser.
  153. class Parser {
  154. let tokens: [Token]
  155. var currentIndex = 0
  156. init(tokens: [Token]) {
  157. self.tokens = tokens
  158. }
  159. // MARK: current token
  160. func currentToken() -> Token {
  161. if currentIndex >= tokens.count {
  162. return .undefined("", 0..<0)
  163. }
  164. return tokens[currentIndex]
  165. }
  166. @discardableResult
  167. func popCurrentToken() -> Token {
  168. defer { currentIndex += 1 }
  169. return tokens[currentIndex]
  170. }
  171. // MARK: parse
  172. func parse() throws -> [Node] {
  173. currentIndex = 0
  174. var nodes = [Node]()
  175. while currentIndex < tokens.count {
  176. let expr = try parseExpression()
  177. nodes.append(expr)
  178. }
  179. return nodes
  180. }
  181. func parseExpression() throws -> Node {
  182. let node = try parsePrimary()
  183. return try parseBinaryOperator(node: node)
  184. }
  185. func parsePrimary() throws -> Node {
  186. let currentToken = self.currentToken()
  187. switch currentToken {
  188. case .identifier:
  189. return try parseIdentifier()
  190. case .number:
  191. return try parseNumber()
  192. case .parenthesisOpen:
  193. return try parseParenthesis()
  194. case .bracketOpen:
  195. return try parseIdentifier()
  196. default:
  197. throw ParseError.expectExpression(currentToken)
  198. }
  199. }
  200. func parseNumber() throws -> Node {
  201. guard case let .number(value, _) = popCurrentToken() else {
  202. throw ParseError.unexpectToken
  203. }
  204. return NumberNode(value: value)
  205. }
  206. func parseParenthesis() throws -> Node {
  207. guard case .parenthesisOpen = popCurrentToken() else {
  208. throw ParseError.expectCharacter("(")
  209. }
  210. let exp = try parseExpression()
  211. guard case .parenthesisClose = popCurrentToken() else {
  212. throw ParseError.expectCharacter(")")
  213. }
  214. return exp
  215. }
  216. func parseBracket() throws -> Node {
  217. guard case .bracketOpen = currentToken() else {
  218. throw ParseError.expectCharacter("[")
  219. }
  220. let exp = try parseExpression()
  221. guard case .bracketClose = popCurrentToken() else {
  222. throw ParseError.expectCharacter("]")
  223. }
  224. return exp
  225. }
  226. func parseIdentifier() throws -> Node {
  227. let firstToken = popCurrentToken()
  228. switch firstToken {
  229. case .identifier(let name, _):
  230. guard case .parenthesisOpen = currentToken() else {
  231. return VariableNode(name: name)
  232. }
  233. popCurrentToken()
  234. var arguments = [Node]()
  235. if case .parenthesisClose = currentToken() {
  236. } else {
  237. while true {
  238. let argument = try parseExpression()
  239. arguments.append(argument)
  240. if case .parenthesisClose = currentToken() {
  241. break
  242. }
  243. guard case .comma = popCurrentToken() else {
  244. throw ParseError.expectCharacter(",")
  245. }
  246. }
  247. }
  248. popCurrentToken()
  249. return CallNode(name: name, arguments: arguments)
  250. case .bracketOpen:
  251. var elements = [Node]()
  252. if case .bracketClose = currentToken() {
  253. } else {
  254. while true {
  255. let node = try parseExpression()
  256. elements.append(node)
  257. if case .bracketClose = currentToken() {
  258. break
  259. }
  260. guard case .comma = popCurrentToken() else {
  261. throw ParseError.expectExpressionList
  262. }
  263. }
  264. }
  265. popCurrentToken()
  266. return ArrayNode(elements: elements)
  267. default:
  268. throw ParseError.unexpectToken
  269. }
  270. }
  271. func currentTokenPrecedence() throws -> Int {
  272. guard currentIndex < tokens.count else {
  273. return -1
  274. }
  275. if case let .undefined(op, _) = currentToken() {
  276. throw ParseError.undefinedOperator(op)
  277. }
  278. guard case let .operator(op, _) = currentToken() else {
  279. return -1
  280. }
  281. return op.precedence
  282. }
  283. func parseBinaryOperator(node: Node, exprPrecedence: Int = 0) throws -> Node {
  284. var lhs = node
  285. while true {
  286. let tokenPrecedence = try currentTokenPrecedence()
  287. if tokenPrecedence < exprPrecedence {
  288. return lhs
  289. }
  290. guard case let .operator(op, _) = popCurrentToken() else {
  291. throw ParseError.unexpectToken
  292. }
  293. var rhs = try parsePrimary()
  294. let nextPrecedence = try currentTokenPrecedence()
  295. if tokenPrecedence < nextPrecedence {
  296. rhs = try parseBinaryOperator(node: rhs, exprPrecedence: tokenPrecedence + 1)
  297. }
  298. lhs = BinaryOperatorNode(operator: op, lhs: lhs, rhs: rhs)
  299. }
  300. }
  301. }
  302. }
  303. // MARK: node extensions
  304. extension Udra {
  305. typealias ParentNode = UdraParentNode
  306. }
  307. protocol UdraParentNode {
  308. var children: [Udra.Node] { get }
  309. }
  310. extension Udra.CallNode: UdraParentNode {
  311. var children: [Udra.Node] {
  312. return arguments
  313. }
  314. }
  315. extension Udra.ArrayNode: UdraParentNode {
  316. var children: [Udra.Node] {
  317. return elements
  318. }
  319. }
  320. extension Udra.BinaryOperatorNode: UdraParentNode {
  321. var children: [Udra.Node] {
  322. return [lhs, rhs]
  323. }
  324. }
  325. extension Udra.Operator {
  326. func evaluate(lhs: Udra.Node, rhs: Udra.Node) -> Any? {
  327. if let lhs = lhs as? Udra.NumberNode, let rhs = rhs as? Udra.NumberNode {
  328. switch self {
  329. case .plus:
  330. return lhs + rhs
  331. }
  332. }
  333. return nil
  334. }
  335. }