diff --git a/Sources/SwiftKotlinFramework/KotlinTokenizer.swift b/Sources/SwiftKotlinFramework/KotlinTokenizer.swift index 088ad74..4880377 100644 --- a/Sources/SwiftKotlinFramework/KotlinTokenizer.swift +++ b/Sources/SwiftKotlinFramework/KotlinTokenizer.swift @@ -553,6 +553,53 @@ public class KotlinTokenizer: SwiftTokenizer { return tokenize(expression.postfixExpression) + expression.newToken(.symbol, "!!") } + open override func tokenize(_ expression: TernaryConditionalOperatorExpression) -> [Token] { + return [ + [expression.newToken(.keyword, "if")], + tokenize(expression.conditionExpression) + .prefix(with: expression.newToken(.startOfScope, "(")) + .suffix(with: expression.newToken(.endOfScope, ")")), + tokenize(expression.trueExpression), + [expression.newToken(.keyword, "else")], + tokenize(expression.falseExpression), + ].joined(token: expression.newToken(.space, " ")) + } + + + open override func tokenize(_ expression: SequenceExpression) -> [Token] { + var elementTokens = expression.elements.map({ tokenize($0, node: expression) }) + + //If there is a ternary, then prefix with if + if let ternaryOperatorIndex = expression.elements.index(where: { $0.isTernaryConditionalOperator }), + ternaryOperatorIndex > 0 { + let assignmentIndex = expression.elements.index(where: { $0.isAssignmentOperator }) ?? -1 + let prefixTokens = [ + expression.newToken(.keyword, "if"), + expression.newToken(.space, " "), + expression.newToken(.startOfScope, "("), + ] + elementTokens[assignmentIndex + 1] = + prefixTokens + + elementTokens[assignmentIndex + 1] + elementTokens[ternaryOperatorIndex - 1] = elementTokens[ternaryOperatorIndex - 1] + .suffix(with: expression.newToken(.endOfScope, ")")) + } + return elementTokens.joined(token: expression.newToken(.space, " ")) + } + + open override func tokenize(_ element: SequenceExpression.Element, node: ASTNode) -> [Token] { + switch element { + case .ternaryConditionalOperator(let expr): + return [ + tokenize(expr), + [node.newToken(.keyword, "else")], + ].joined(token: node.newToken(.space, " ")) + default: + return super.tokenize(element, node: node) + } + } + + // MARK: - Types open override func tokenize(_ type: ArrayType, node: ASTNode) -> [Token] { return diff --git a/Sources/SwiftKotlinFramework/utils/AST+Operations.swift b/Sources/SwiftKotlinFramework/utils/AST+Operations.swift index d0d7e44..6a91fdf 100644 --- a/Sources/SwiftKotlinFramework/utils/AST+Operations.swift +++ b/Sources/SwiftKotlinFramework/utils/AST+Operations.swift @@ -146,4 +146,21 @@ extension EnumDeclaration.Member { } } - +extension SequenceExpression.Element { + var isTernaryConditionalOperator: Bool { + switch self { + case .ternaryConditionalOperator: + return true + default: + return false + } + } + var isAssignmentOperator: Bool { + switch self { + case .assignmentOperator: + return true + default: + return false + } + } +} diff --git a/SwiftKotlin.xcodeproj/xcshareddata/xcschemes/SwiftKotlin-Package.xcscheme b/SwiftKotlin.xcodeproj/xcshareddata/xcschemes/SwiftKotlin-Package.xcscheme index e92824c..4e840ed 100644 --- a/SwiftKotlin.xcodeproj/xcshareddata/xcschemes/SwiftKotlin-Package.xcscheme +++ b/SwiftKotlin.xcodeproj/xcshareddata/xcschemes/SwiftKotlin-Package.xcscheme @@ -15,7 +15,7 @@ @@ -213,7 +213,7 @@ diff --git a/SwiftKotlin.xcodeproj/xcshareddata/xcschemes/SwiftKotlinCommandLine.xcscheme b/SwiftKotlin.xcodeproj/xcshareddata/xcschemes/SwiftKotlinCommandLine.xcscheme index c38d4eb..8d8a7c2 100644 --- a/SwiftKotlin.xcodeproj/xcshareddata/xcschemes/SwiftKotlinCommandLine.xcscheme +++ b/SwiftKotlin.xcodeproj/xcshareddata/xcschemes/SwiftKotlinCommandLine.xcscheme @@ -15,7 +15,7 @@ @@ -34,7 +34,7 @@ @@ -58,7 +58,7 @@ @@ -77,7 +77,7 @@ diff --git a/Tests/SwiftKotlinFrameworkTests/Tests/KotlinTokenizer/control_flow.kt b/Tests/SwiftKotlinFrameworkTests/Tests/KotlinTokenizer/control_flow.kt index 3b4dd28..ae21468 100644 --- a/Tests/SwiftKotlinFrameworkTests/Tests/KotlinTokenizer/control_flow.kt +++ b/Tests/SwiftKotlinFrameworkTests/Tests/KotlinTokenizer/control_flow.kt @@ -76,3 +76,7 @@ when (nb) { } else -> print("three or more digits") } +val value = if (isTrue) "yes" else "no" +val label = if (x > 0) "Positive" else "negative" +button.color = if (item.deleted) red else green +val text = label ?: "default" diff --git a/Tests/SwiftKotlinFrameworkTests/Tests/KotlinTokenizer/control_flow.swift b/Tests/SwiftKotlinFrameworkTests/Tests/KotlinTokenizer/control_flow.swift index ffe71f9..56642f4 100644 --- a/Tests/SwiftKotlinFrameworkTests/Tests/KotlinTokenizer/control_flow.swift +++ b/Tests/SwiftKotlinFrameworkTests/Tests/KotlinTokenizer/control_flow.swift @@ -59,3 +59,11 @@ switch nb { default: print("three or more digits") } + +// Ternary and coalescing operators +let value = isTrue ? "yes" : "no" +let label = x > 0 ? "Positive" : "negative" +button.color = item.deleted ? red : green +let text = label ?? "default" + +