Commit 5c4a028f by Daniel Dahan

removed string MotionTransition parser

parent 959610e1
......@@ -35,14 +35,8 @@
96AEB69F1EE4610F009A3BE0 /* MotionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB6791EE4610F009A3BE0 /* MotionContext.swift */; };
96AEB6A01EE4610F009A3BE0 /* MotionIndependentController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB67A1EE4610F009A3BE0 /* MotionIndependentController.swift */; };
96AEB6A11EE4610F009A3BE0 /* MotionTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB67B1EE4610F009A3BE0 /* MotionTransition.swift */; };
96AEB6A21EE4610F009A3BE0 /* MotionTransition+MotionStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB67C1EE4610F009A3BE0 /* MotionTransition+MotionStringConvertible.swift */; };
96AEB6A31EE4610F009A3BE0 /* MotionPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB67D1EE4610F009A3BE0 /* MotionPlugin.swift */; };
96AEB6A41EE4610F009A3BE0 /* MotionStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB67E1EE4610F009A3BE0 /* MotionStringConvertible.swift */; };
96AEB6A51EE4610F009A3BE0 /* MotionTransitionState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB67F1EE4610F009A3BE0 /* MotionTransitionState.swift */; };
96AEB6A71EE4610F009A3BE0 /* Lexer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB6821EE4610F009A3BE0 /* Lexer.swift */; };
96AEB6A81EE4610F009A3BE0 /* Nodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB6831EE4610F009A3BE0 /* Nodes.swift */; };
96AEB6A91EE4610F009A3BE0 /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB6841EE4610F009A3BE0 /* Parser.swift */; };
96AEB6AA1EE4610F009A3BE0 /* Regex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB6851EE4610F009A3BE0 /* Regex.swift */; };
96AEB6AC1EE4610F009A3BE0 /* CascadePreprocessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB6881EE4610F009A3BE0 /* CascadePreprocessor.swift */; };
96AEB6AD1EE4610F009A3BE0 /* DurationPreprocessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB6891EE4610F009A3BE0 /* DurationPreprocessor.swift */; };
96AEB6AE1EE4610F009A3BE0 /* IgnoreSubviewModifiersPreprocessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96AEB68A1EE4610F009A3BE0 /* IgnoreSubviewModifiersPreprocessor.swift */; };
......@@ -79,14 +73,8 @@
96AEB6791EE4610F009A3BE0 /* MotionContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionContext.swift; sourceTree = "<group>"; };
96AEB67A1EE4610F009A3BE0 /* MotionIndependentController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionIndependentController.swift; sourceTree = "<group>"; };
96AEB67B1EE4610F009A3BE0 /* MotionTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionTransition.swift; sourceTree = "<group>"; };
96AEB67C1EE4610F009A3BE0 /* MotionTransition+MotionStringConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MotionTransition+MotionStringConvertible.swift"; sourceTree = "<group>"; };
96AEB67D1EE4610F009A3BE0 /* MotionPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionPlugin.swift; sourceTree = "<group>"; };
96AEB67E1EE4610F009A3BE0 /* MotionStringConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionStringConvertible.swift; sourceTree = "<group>"; };
96AEB67F1EE4610F009A3BE0 /* MotionTransitionState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MotionTransitionState.swift; sourceTree = "<group>"; };
96AEB6821EE4610F009A3BE0 /* Lexer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lexer.swift; sourceTree = "<group>"; };
96AEB6831EE4610F009A3BE0 /* Nodes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Nodes.swift; sourceTree = "<group>"; };
96AEB6841EE4610F009A3BE0 /* Parser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Parser.swift; sourceTree = "<group>"; };
96AEB6851EE4610F009A3BE0 /* Regex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Regex.swift; sourceTree = "<group>"; };
96AEB6881EE4610F009A3BE0 /* CascadePreprocessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CascadePreprocessor.swift; sourceTree = "<group>"; };
96AEB6891EE4610F009A3BE0 /* DurationPreprocessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DurationPreprocessor.swift; sourceTree = "<group>"; };
96AEB68A1EE4610F009A3BE0 /* IgnoreSubviewModifiersPreprocessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IgnoreSubviewModifiersPreprocessor.swift; sourceTree = "<group>"; };
......@@ -148,17 +136,6 @@
path = Extensions;
sourceTree = "<group>";
};
96AEB6811EE4610F009A3BE0 /* Parser */ = {
isa = PBXGroup;
children = (
96AEB6821EE4610F009A3BE0 /* Lexer.swift */,
96AEB6831EE4610F009A3BE0 /* Nodes.swift */,
96AEB6841EE4610F009A3BE0 /* Parser.swift */,
96AEB6851EE4610F009A3BE0 /* Regex.swift */,
);
path = Parser;
sourceTree = "<group>";
};
96AEB6861EE4610F009A3BE0 /* Preprocessors */ = {
isa = PBXGroup;
children = (
......@@ -206,12 +183,9 @@
96AEB67B1EE4610F009A3BE0 /* MotionTransition.swift */,
96E49A3F1EEA08F8006D5A93 /* MotionTransitionObserver.swift */,
96AEB67D1EE4610F009A3BE0 /* MotionPlugin.swift */,
96AEB67E1EE4610F009A3BE0 /* MotionStringConvertible.swift */,
96AEB67C1EE4610F009A3BE0 /* MotionTransition+MotionStringConvertible.swift */,
96AEB6641EE4610F009A3BE0 /* Animator */,
96AEB6691EE4610F009A3BE0 /* Debug Plugin */,
96AEB66D1EE4610F009A3BE0 /* Extensions */,
96AEB6811EE4610F009A3BE0 /* Parser */,
96AEB6861EE4610F009A3BE0 /* Preprocessors */,
);
path = Sources;
......@@ -306,7 +280,6 @@
96AEB69D1EE4610F009A3BE0 /* Motion.swift in Sources */,
963150D61EE51C7A002B0D42 /* MotionAnimation.swift in Sources */,
968989DE1EE6633E003B8F3D /* MotionAnimator.swift in Sources */,
96AEB6A21EE4610F009A3BE0 /* MotionTransition+MotionStringConvertible.swift in Sources */,
968989B91EE5B34B003B8F3D /* MotionHasInsertOrder.swift in Sources */,
96AEB6A51EE4610F009A3BE0 /* MotionTransitionState.swift in Sources */,
96AEB6961EE4610F009A3BE0 /* Motion+CAMediaTimingFunction.swift in Sources */,
......@@ -317,16 +290,11 @@
96E49A401EEA08F8006D5A93 /* MotionTransitionObserver.swift in Sources */,
96AEB6A01EE4610F009A3BE0 /* MotionIndependentController.swift in Sources */,
966A7F091EEC422000A2DAAC /* MotionSnapshotType.swift in Sources */,
96AEB6AA1EE4610F009A3BE0 /* Regex.swift in Sources */,
96AEB6901EE4610F009A3BE0 /* MotionViewPropertyViewContext.swift in Sources */,
96AEB6991EE4610F009A3BE0 /* Motion+UIKit.swift in Sources */,
96AEB69B1EE4610F009A3BE0 /* Motion+UIViewController.swift in Sources */,
96AEB6A41EE4610F009A3BE0 /* MotionStringConvertible.swift in Sources */,
96AEB6A81EE4610F009A3BE0 /* Nodes.swift in Sources */,
968989DC1EE65F2B003B8F3D /* MotionPreprocessor.swift in Sources */,
96AEB6A91EE4610F009A3BE0 /* Parser.swift in Sources */,
96AEB69F1EE4610F009A3BE0 /* MotionContext.swift in Sources */,
96AEB6A71EE4610F009A3BE0 /* Lexer.swift in Sources */,
96AEB6AE1EE4610F009A3BE0 /* IgnoreSubviewModifiersPreprocessor.swift in Sources */,
96AEB68D1EE4610F009A3BE0 /* MotionAnimatorViewContext.swift in Sources */,
96AEB6B01EE4610F009A3BE0 /* SourcePreprocessor.swift in Sources */,
......
......@@ -41,65 +41,3 @@ internal extension Array {
return nil
}
}
internal extension Array where Element: ExprNode {
/**
Retrieves the element at the given index if it exists
as a CGFloat.
- Parameter _ index: An Int.
- Returns: An optional CGFloat value.
*/
func getCGFloat(_ index: Int) -> CGFloat? {
guard let s = get(index) as? NumberNode else {
return nil
}
return CGFloat(s.value)
}
/**
Retrieves the element at the given index if it exists
as a Double.
- Parameter _ index: An Int.
- Returns: An optional Double value.
*/
func getDouble(_ index: Int) -> Double? {
guard let s = get(index) as? NumberNode else {
return nil
}
return Double(s.value)
}
/**
Retrieves the element at the given index if it exists
as a Float.
- Parameter _ index: An Int.
- Returns: An optional Float value.
*/
func getFloat(_ index: Int) -> Float? {
guard let s = get(index) as? NumberNode else {
return nil
}
return s.value
}
/**
Retrieves the element at the given index if it exists
as a Bool.
- Parameter _ index: An Int.
- Returns: An optional Bool value.
*/
func getBool(_ index: Int) -> Bool? {
guard let s = get(index) as? VariableNode else {
return nil
}
guard let f = Bool(s.name) else {
return nil
}
return f
}
}
......@@ -115,17 +115,6 @@ public extension UIView {
}
}
/// Used for Storyboards, allows a string to be converted into MotionTransitions.
@IBInspectable
public var motionTransitionsString: String? {
get {
fatalError("Reverse lookup is not supported")
}
set(value) {
motionTransitions = value?.parse()
}
}
/// Computes the rotate of the view.
var motionRotationAngle: CGFloat {
get {
......
......@@ -84,16 +84,6 @@ extension UIViewController {
}
}
@IBInspectable
public var motionModalTransitionTypeString: String? {
get {
return associatedInstance.modalTransitionType.label
}
set(value) {
associatedInstance.modalTransitionType = value?.parseOne() ?? .auto
}
}
/// used for .overFullScreen presentation
internal var motionStoredSnapshot: UIView? {
get {
......@@ -178,17 +168,6 @@ extension UINavigationController {
associatedInstance.navigationTransitionType = value
}
}
/// A String representation for the motionNavigationTransitionType.
@IBInspectable
public var motionNavigationTransitionTypeString: String? {
get {
return associatedInstance.navigationTransitionType.label
}
set(value) {
associatedInstance.navigationTransitionType = value?.parseOne() ?? .auto
}
}
}
extension UITabBarController {
......@@ -201,16 +180,6 @@ extension UITabBarController {
associatedInstance.tabBarTransitionType = value
}
}
/// A String representation for the motionTabBarTransitionTypeString.
@IBInspectable
public var motionTabBarTransitionTypeString: String? {
get {
return associatedInstance.tabBarTransitionType.label }
set(value) {
associatedInstance.tabBarTransitionType = value?.parseOne() ?? .auto
}
}
}
extension UIViewController {
......
/*
* The MIT License (MIT)
*
* Copyright (C) 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Original Inspiration & Author
* Copyright (c) 2016 Luke Zhao <me@lkzhao.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import UIKit
public protocol MotionStringConvertible {
/**
Retrieves an instance of Self from a give ExprNode.
- Parameter node: An ExprNode.
- Returns: An optional Self.
*/
static func from(node: ExprNode) -> Self?
}
extension String {
/**
Parses a string that implements the MotionStringConvertible protocol.
- Returns: An optional Array of Elements of type T.
*/
func parse<T: MotionStringConvertible>() -> [T]? {
let lexer = Lexer(input: self)
let parser = Parser(tokens: lexer.tokenize())
do {
let nodes = try parser.parse()
var results = [T]()
for v in nodes {
if let modifier = T.from(node: v) {
results.append(modifier)
} else {
print("\(v.name) doesn't exist in \(T.self)")
}
}
return results
} catch let error {
print("failed to parse \"\(self)\", error: \(error)")
}
return nil
}
/**
Retrieves a single instance of a token.
- Returns: An optional Element ot type T.
*/
func parseOne<T: MotionStringConvertible>() -> T? {
return parse()?.last
}
}
/*
* The MIT License (MIT)
*
* Copyright (C) 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Original Inspiration & Author
* Copyright (c) 2016 Luke Zhao <me@lkzhao.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import UIKit
extension MotionTransition: MotionStringConvertible {
/**
Used to construct MotionTransitions from motionTransitionsString.
- Parameter node: An ExprNode.
- Returns: An optional MotionTransition.
*/
public static func from(node: ExprNode) -> MotionTransition? {
let name: String = node.name
let parameters: [ExprNode] = (node as? CallNode)?.arguments ?? []
switch name {
case "fade":
return .fade
case "opacity":
return MotionTransition.fade(to: parameters.getFloat(0) ?? 1)
case "position":
return .position(to: CGPoint(x: parameters.getCGFloat(0) ?? 0, y: parameters.getCGFloat(1) ?? 0))
case "size":
return .size(CGSize(width: parameters.getCGFloat(0) ?? 0, height: parameters.getCGFloat(1) ?? 0))
case "scale":
return 1 == parameters.count ? .scale(to: parameters.getCGFloat(0) ?? 1) : .scale(x: parameters.getCGFloat(0) ?? 1,
y: parameters.getCGFloat(1) ?? 1,
z: parameters.getCGFloat(2) ?? 1)
case "rotate":
return 1 == parameters.count ? .rotate(parameters.getCGFloat(0) ?? 0) : .rotate(x: parameters.getCGFloat(0) ?? 0,
y: parameters.getCGFloat(1) ?? 0,
z: parameters.getCGFloat(2) ?? 0)
case "translate":
return .translate(x: parameters.getCGFloat(0) ?? 0,
y: parameters.getCGFloat(1) ?? 0,
z: parameters.getCGFloat(2) ?? 0)
case "overlay":
return .overlay(color: UIColor(red: parameters.getCGFloat(0) ?? 1,
green: parameters.getCGFloat(1) ?? 1,
blue: parameters.getCGFloat(2) ?? 1,
alpha: 1),
opacity: parameters.getCGFloat(3) ?? 1)
case "duration":
if let v = parameters.getDouble(0) {
return .duration(v)
}
case "preferredDurationMatchesLongest":
return .preferredDurationMatchesLongest
case "delay":
if let v = parameters.getDouble(0) {
return .delay(v)
}
case "spring":
if #available(iOS 9, *) {
return .spring(stiffness: parameters.getCGFloat(0) ?? 250, damping: parameters.getCGFloat(1) ?? 30)
}
case "timingFunction":
if let c1 = parameters.getFloat(0),
let c2 = parameters.getFloat(1),
let c3 = parameters.getFloat(2),
let c4 = parameters.getFloat(3) {
return .timingFunction(CAMediaTimingFunction(controlPoints: c1, c2, c3, c4))
} else if let name = parameters.get(0)?.name,
let timingFunction = CAMediaTimingFunction.from(mediaTimingFunctionType: name) {
return .timingFunction(timingFunction)
}
case "arc":
return .arc(intensity: parameters.getCGFloat(0) ?? 1)
case "cascade":
var cascadeDirection = CascadeDirection.topToBottom
if let directionString = parameters.get(1)?.name,
let direction = CascadeDirection(directionString) {
cascadeDirection = direction
}
return .cascade(delta: parameters.getDouble(0) ?? 0.02, direction: cascadeDirection, animationDelayUntilMatchedViews:parameters.getBool(2) ?? false)
case "source":
if let v = parameters.get(0)?.name {
return .motionIdentifier(v)
}
case "useGlobalCoordinateSpace":
return .useGlobalCoordinateSpace
case "useSameParentCoordinateSpace":
return .useSameParentCoordinateSpace
case "ignoreSubviewTransitions":
return .ignoreSubviewTransitions(recursive:parameters.getBool(0) ?? false)
case "zPosition":
if let zPosition = parameters.getCGFloat(0) {
return .zPosition(zPosition)
}
case "useOptimizedSnapshot":
return .useOptimizedSnapshot
case "useNormalSnapshot":
return .useNormalSnapshot
case "useLayerRenderSnapshot":
return .useLayerRenderSnapshot
case "useNoSnapshot":
return .useNoSnapshot
case "forceAnimate":
return .forceAnimate
default: break
}
return nil
}
}
//
// Lexer.swift
// Kaleidoscope
//
// Created by Matthew Cheok on 15/11/15.
// Copyright © 2015 Matthew Cheok. All rights reserved.
//
import Foundation
public enum Token {
case identifier(String, CountableRange<Int>)
case number(Float, CountableRange<Int>)
case parensOpen(CountableRange<Int>)
case parensClose(CountableRange<Int>)
case comma(CountableRange<Int>)
case other(String, CountableRange<Int>)
}
typealias TokenGenerator = (String, CountableRange<Int>) -> Token?
let tokenList: [(String, TokenGenerator)] = [
("[ \t\n]", { _ in nil }),
("[a-zA-Z][a-zA-Z0-9]*", { .identifier($0, $1) }),
("\\-?[0-9.]+", { .number(Float($0)!, $1) }),
("\\(", { .parensOpen($1) }),
("\\)", { .parensClose($1) }),
(",", { .comma($1) })
]
public class Lexer {
let input: String
public init(input: String) {
self.input = input
}
public func tokenize() -> [Token] {
var tokens = [Token]()
var content = input
while !content.characters.isEmpty {
var matched = false
for (pattern, generator) in tokenList {
if let (m, r) = content.match(regex: pattern) {
if let t = generator(m, r) {
tokens.append(t)
}
content = content.substring(from: content.index(content.startIndex, offsetBy: m.characters.count))
matched = true
break
}
}
if !matched {
let index = content.index(content.startIndex, offsetBy: 1)
let intIndex = content.distance(from: content.startIndex, to: index)
tokens.append(.other(content.substring(to: index), intIndex..<intIndex+1))
content = content.substring(from: index)
}
}
return tokens
}
}
//
// Nodes.swift
// Kaleidoscope
//
// Created by Matthew Cheok on 15/11/15.
// Copyright © 2015 Matthew Cheok. All rights reserved.
//
import Foundation
public class ExprNode: CustomStringConvertible, Equatable {
public var range: CountableRange<Int> = 0..<0
public let name: String
public var description: String {
return "ExprNode(name: \"\(name)\")"
}
public init(name: String) {
self.name = name
}
}
public func == (lhs: ExprNode, rhs: ExprNode) -> Bool {
return lhs.description == rhs.description
}
public class NumberNode: ExprNode {
public let value: Float
public override var description: String {
return "NumberNode(value: \(value))"
}
public init(value: Float) {
self.value = value
super.init(name: "\(value)")
}
}
public class VariableNode: ExprNode {
public override var description: String {
return "VariableNode(name: \"\(name)\")"
}
}
public class BinaryOpNode: ExprNode {
public let lhs: ExprNode
public let rhs: ExprNode
public override var description: String {
return "BinaryOpNode(name: \"\(name)\", lhs: \(lhs), rhs: \(rhs))"
}
public init(name: String, lhs: ExprNode, rhs: ExprNode) {
self.lhs = lhs
self.rhs = rhs
super.init(name: "\(name)")
}
}
public class CallNode: ExprNode {
public let arguments: [ExprNode]
public override var description: String {
return "CallNode(name: \"\(name)\", arguments: \(arguments))"
}
public init(name: String, arguments: [ExprNode]) {
self.arguments = arguments
super.init(name: "\(name)")
}
}
public class PrototypeNode: ExprNode {
public let argumentNames: [String]
public override var description: String {
return "PrototypeNode(name: \"\(name)\", argumentNames: \(argumentNames))"
}
public init(name: String, argumentNames: [String]) {
self.argumentNames = argumentNames
super.init(name: "\(name)")
}
}
public class FunctionNode: ExprNode {
public let prototype: PrototypeNode
public let body: ExprNode
public override var description: String {
return "FunctionNode(prototype: \(prototype), body: \(body))"
}
public init(prototype: PrototypeNode, body: ExprNode) {
self.prototype = prototype
self.body = body
super.init(name: "\(prototype.name)")
}
}
//
// Parser.swift
// Kaleidoscope
//
// Created by Matthew Cheok on 15/11/15.
// Copyright © 2015 Matthew Cheok. All rights reserved.
//
import Foundation
public enum ParseError: Error {
case unexpectToken
case undefinedOperator(String)
case expectCharacter(Character)
case expectExpression
case expectArgumentList
case expectFunctionName
}
public class Parser {
let tokens: [Token]
var index = 0
public init(tokens: [Token]) {
self.tokens = tokens
}
func peekCurrentToken() -> Token {
if index >= tokens.count {
return .other("", 0..<0)
}
return tokens[index]
}
@discardableResult func popCurrentToken() -> Token {
defer { index += 1 }
return tokens[index]
}
func parseNumber() throws -> ExprNode {
guard case let .number(value, _) = popCurrentToken() else {
throw ParseError.unexpectToken
}
return NumberNode(value: value)
}
func parseExpression() throws -> ExprNode {
let node = try parsePrimary()
return try parseBinaryOp(node: node)
}
func parseParens() throws -> ExprNode {
guard case .parensOpen = popCurrentToken() else {
throw ParseError.expectCharacter("(")
}
let exp = try parseExpression()
guard case .parensClose = popCurrentToken() else {
throw ParseError.expectCharacter(")")
}
return exp
}
func parseIdentifier() throws -> ExprNode {
guard case let .identifier(name, _) = popCurrentToken() else {
throw ParseError.unexpectToken
}
guard case .parensOpen = peekCurrentToken() else {
return VariableNode(name: name)
}
popCurrentToken()
var arguments = [ExprNode]()
if case .parensClose = peekCurrentToken() {
} else {
while true {
let argument = try parseExpression()
arguments.append(argument)
if case .parensClose = peekCurrentToken() {
break
}
guard case .comma = popCurrentToken() else {
throw ParseError.expectArgumentList
}
}
}
popCurrentToken()
return CallNode(name: name, arguments: arguments)
}
func parsePrimary() throws -> ExprNode {
switch peekCurrentToken() {
case .identifier:
return try parseIdentifier()
case .number:
return try parseNumber()
case .parensOpen:
return try parseParens()
default:
throw ParseError.expectExpression
}
}
let operatorPrecedence: [String: Int] = [
"+": 20,
"-": 20,
"*": 40,
"/": 40
]
func getCurrentTokenPrecedence() throws -> Int {
guard index < tokens.count else {
return -1
}
guard case let .other(op, _) = peekCurrentToken() else {
return -1
}
guard let precedence = operatorPrecedence[op] else {
throw ParseError.undefinedOperator(op)
}
return precedence
}
func parseBinaryOp(node: ExprNode, exprPrecedence: Int = 0) throws -> ExprNode {
var lhs = node
while true {
let tokenPrecedence = try getCurrentTokenPrecedence()
if tokenPrecedence < exprPrecedence {
return lhs
}
guard case let .other(op, _) = popCurrentToken() else {
throw ParseError.unexpectToken
}
var rhs = try parsePrimary()
let nextPrecedence = try getCurrentTokenPrecedence()
if tokenPrecedence < nextPrecedence {
rhs = try parseBinaryOp(node: rhs, exprPrecedence: tokenPrecedence+1)
}
lhs = BinaryOpNode(name: op, lhs: lhs, rhs: rhs)
}
}
public func parse() throws -> [ExprNode] {
index = 0
var nodes = [ExprNode]()
while index < tokens.count {
let expr = try parsePrimary()
nodes.append(expr)
}
return nodes
}
}
//
// Regex.swift
// Kaleidoscope
//
// Created by Matthew Cheok on 15/11/15.
// Copyright © 2015 Matthew Cheok. All rights reserved.
//
import Foundation
var expressions = [String: NSRegularExpression]()
public extension String {
public func match(regex: String) -> (String, CountableRange<Int>)? {
let expression: NSRegularExpression
if let exists = expressions[regex] {
expression = exists
} else {
do {
expression = try NSRegularExpression(pattern: "^\(regex)", options: [])
expressions[regex] = expression
} catch {
return nil
}
}
let range = expression.rangeOfFirstMatch(in: self, options: [], range: NSRange(0 ..< self.utf16.count))
if range.location != NSNotFound {
return ((self as NSString).substring(with: range), range.location ..< range.location + range.length )
}
return nil
}
}
//
// CascadeEffect.swift
/*
* The MIT License (MIT)
*
......
//
// DurationPreprocessor.swift
// Motion
//
// Created by Luke on 3/16/17.
// Copyright © 2017 Luke Zhao. All rights reserved.
//
/*
* The MIT License (MIT)
*
* Copyright (C) 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Original Inspiration & Author
* Copyright (c) 2016 Luke Zhao <me@lkzhao.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import UIKit
......
......@@ -29,30 +29,25 @@
import UIKit
public enum MotionTransitionType {
public enum Direction: MotionStringConvertible {
case left, right, up, down
public static func from(node: ExprNode) -> Direction? {
switch node.name {
case "left": return .left
case "right": return .right
case "up": return .up
case "down": return .down
default: return nil
}
public enum Direction {
case left
case right
case up
case down
}
}
case auto
case push(direction: Direction)
case pull(direction: Direction)
case cover(direction: Direction)
case uncover(direction: Direction)
case slide(direction: Direction)
case zoomSlide(direction: Direction)
case pageIn(direction: Direction)
case pageOut(direction: Direction)
case fade
case zoom
case zoomOut
case auto
case push(direction: Direction)
case pull(direction: Direction)
case cover(direction: Direction)
case uncover(direction: Direction)
case slide(direction: Direction)
case zoomSlide(direction: Direction)
case pageIn(direction: Direction)
case pageOut(direction: Direction)
case fade
case zoom
case zoomOut
indirect case selectBy(presenting: MotionTransitionType, dismissing: MotionTransitionType)
......@@ -152,63 +147,6 @@ public enum MotionTransitionType {
}
}
extension MotionTransitionType: MotionStringConvertible {
public static func from(node: ExprNode) -> MotionTransitionType? {
let name: String = node.name
let parameters: [ExprNode] = (node as? CallNode)?.arguments ?? []
switch name {
case "auto":
return .auto
case "push":
if let node = parameters.get(0), let direction = Direction.from(node: node) {
return .push(direction: direction)
}
case "pull":
if let node = parameters.get(0), let direction = Direction.from(node: node) {
return .pull(direction: direction)
}
case "cover":
if let node = parameters.get(0), let direction = Direction.from(node: node) {
return .cover(direction: direction)
}
case "uncover":
if let node = parameters.get(0), let direction = Direction.from(node: node) {
return .uncover(direction: direction)
}
case "slide":
if let node = parameters.get(0), let direction = Direction.from(node: node) {
return .slide(direction: direction)
}
case "zoomSlide":
if let node = parameters.get(0), let direction = Direction.from(node: node) {
return .zoomSlide(direction: direction)
}
case "pageIn":
if let node = parameters.get(0), let direction = Direction.from(node: node) {
return .pageIn(direction: direction)
}
case "pageOut":
if let node = parameters.get(0), let direction = Direction.from(node: node) {
return .pageOut(direction: direction)
}
case "fade": return .fade
case "zoom": return .zoom
case "zoomOut": return .zoomOut
case "selectBy":
if let presentingNode = parameters.get(0),
let presenting = MotionTransitionType.from(node: presentingNode),
let dismissingNode = parameters.get(1),
let dismissing = MotionTransitionType.from(node: dismissingNode) {
return .selectBy(presenting: presenting, dismissing: dismissing)
}
case "none": return .none
default: break
}
return nil
}
}
class TransitionPreprocessor: MotionPreprocessor {
/// A reference to a MotionContext.
weak var context: MotionContext!
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment