Merge pull request #2107 from ewanmellor/swift-fix-deprecated-string-methods

Remove use of deprecated String functions
This commit is contained in:
Terence Parr 2017-11-29 09:52:27 -08:00 committed by GitHub
commit 84e9a46932
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 450 additions and 596 deletions

View File

@ -6,7 +6,7 @@ set -euo pipefail
# here since environment variables doesn't pass # here since environment variables doesn't pass
# across scripts # across scripts
if [ $TRAVIS_OS_NAME == "linux" ]; then if [ $TRAVIS_OS_NAME == "linux" ]; then
export SWIFT_VERSION=swift-4.0 export SWIFT_VERSION=swift-4.0.2
export SWIFT_HOME=$(pwd)/swift/$SWIFT_VERSION-RELEASE-ubuntu14.04/usr/bin/ export SWIFT_HOME=$(pwd)/swift/$SWIFT_VERSION-RELEASE-ubuntu14.04/usr/bin/
export PATH=$SWIFT_HOME:$PATH export PATH=$SWIFT_HOME:$PATH

View File

@ -42,8 +42,8 @@ public class ANTLRInputStream: CharStream {
/// Copy data in string to a local char array /// Copy data in string to a local char array
/// ///
public init(_ input: String) { public init(_ input: String) {
self.data = Array(input.characters) // input.toCharArray(); self.data = Array(input)
self.n = input.length self.n = data.count
} }
/// ///

View File

@ -441,14 +441,13 @@ public class BufferedTokenStream: TokenStream {
/// Collect all hidden tokens (any off-default channel) to the left of /// Collect all hidden tokens (any off-default channel) to the left of
/// the current token up until we see a token on DEFAULT_TOKEN_CHANNEL. /// the current token up until we see a token on DEFAULT_TOKEN_CHANNEL.
/// ///
public func getHiddenTokensToLeft(_ tokenIndex: Int) throws -> Array<Token>? { public func getHiddenTokensToLeft(_ tokenIndex: Int) throws -> [Token]? {
return try getHiddenTokensToLeft(tokenIndex, -1) return try getHiddenTokensToLeft(tokenIndex, -1)
} }
internal func filterForChannel(_ from: Int, _ to: Int, _ channel: Int) -> Array<Token>? { internal func filterForChannel(_ from: Int, _ to: Int, _ channel: Int) -> [Token]? {
var hidden: Array<Token> = Array<Token>() var hidden = [Token]()
for i in from...to { for t in tokens[from...to] {
let t: Token = tokens[i]
if channel == -1 { if channel == -1 {
if t.getChannel() != Lexer.DEFAULT_TOKEN_CHANNEL { if t.getChannel() != Lexer.DEFAULT_TOKEN_CHANNEL {
hidden.append(t) hidden.append(t)
@ -478,8 +477,8 @@ public class BufferedTokenStream: TokenStream {
} }
public func getText(_ interval: Interval) throws -> String { public func getText(_ interval: Interval) throws -> String {
let start: Int = interval.a let start = interval.a
var stop: Int = interval.b var stop = interval.b
if start < 0 || stop < 0 { if start < 0 || stop < 0 {
return "" return ""
} }
@ -488,15 +487,14 @@ public class BufferedTokenStream: TokenStream {
stop = tokens.count - 1 stop = tokens.count - 1
} }
let buf: StringBuilder = StringBuilder() var buf = ""
for i in start...stop { for t in tokens[start...stop] {
let t: Token = tokens[i]
if t.getType() == BufferedTokenStream.EOF { if t.getType() == BufferedTokenStream.EOF {
break break
} }
buf.append(t.getText()!) buf += t.getText()!
} }
return buf.toString() return buf
} }
@ -518,9 +516,9 @@ public class BufferedTokenStream: TokenStream {
/// ///
public func fill() throws { public func fill() throws {
try lazyInit() try lazyInit()
let blockSize: Int = 1000 let blockSize = 1000
while true { while true {
let fetched: Int = try fetch(blockSize) let fetched = try fetch(blockSize)
if fetched < blockSize { if fetched < blockSize {
return return
} }

View File

@ -413,29 +413,27 @@ open class Lexer: Recognizer<LexerATNSimulator>, TokenSource {
} }
open func getErrorDisplay(_ s: String) -> String { open func getErrorDisplay(_ s: String) -> String {
let buf = StringBuilder() var buf = ""
for c in s.characters { for c in s {
buf.append(getErrorDisplay(c)) buf += getErrorDisplay(c)
} }
return buf.toString() return buf
} }
open func getErrorDisplay(_ c: Character) -> String { open func getErrorDisplay(_ c: Character) -> String {
var s = String(c)
if c.integerValue == CommonToken.EOF { if c.integerValue == CommonToken.EOF {
s = "<EOF>" return "<EOF>"
} }
switch s { switch c {
case "\n": case "\n":
s = "\\n" return "\\n"
case "\t": case "\t":
s = "\\t" return "\\t"
case "\r": case "\r":
s = "\\r" return "\\r"
default: default:
break return String(c)
} }
return s
} }
open func getCharErrorDisplay(_ c: Character) -> String { open func getCharErrorDisplay(_ c: Character) -> String {

View File

@ -85,9 +85,8 @@ public class ListTokenSource: TokenSource {
let lastToken = tokens[tokens.count - 1] let lastToken = tokens[tokens.count - 1]
if let tokenText = lastToken.getText() { if let tokenText = lastToken.getText() {
let lastNewLine = tokenText.lastIndexOf("\n") if let lastNewLine = tokenText.lastIndex(of: "\n") {
if lastNewLine >= 0 { return tokenText.distance(from: lastNewLine, to: tokenText.endIndex) - 1
return tokenText.length - lastNewLine - 1
} }
} }
return (lastToken.getCharPositionInLine() + return (lastToken.getCharPositionInLine() +
@ -142,9 +141,8 @@ public class ListTokenSource: TokenSource {
var line = lastToken.getLine() var line = lastToken.getLine()
if let tokenText = lastToken.getText() { if let tokenText = lastToken.getText() {
let length = tokenText.length for c in tokenText {
for j in 0..<length { if c == "\n" {
if String(tokenText[j]) == "\n" {
line += 1 line += 1
} }
} }

View File

@ -429,7 +429,7 @@ open class Parser: Recognizer<ParserATNSimulator> {
if result == nil { if result == nil {
let deserializationOptions = ATNDeserializationOptions() let deserializationOptions = ATNDeserializationOptions()
try! deserializationOptions.setGenerateRuleBypassTransitions(true) try! deserializationOptions.setGenerateRuleBypassTransitions(true)
result = try! ATNDeserializer(deserializationOptions).deserialize(Array(serializedAtn.characters)) result = try! ATNDeserializer(deserializationOptions).deserialize(Array(serializedAtn))
self.bypassAltsAtnCache[serializedAtn] = result! self.bypassAltsAtnCache[serializedAtn] = result!
} }
} }

View File

@ -132,12 +132,12 @@ open class RuleContext: RuleNode {
return "" return ""
} }
let builder = StringBuilder() var builder = ""
for i in 0..<length { for i in 0..<length {
builder.append((getChild(i) as! ParseTree).getText()) builder += (getChild(i) as! ParseTree).getText()
} }
return builder.toString() return builder
} }
open func getRuleIndex() -> Int { open func getRuleIndex() -> Int {
@ -202,31 +202,31 @@ open class RuleContext: RuleNode {
} }
open func toString(_ ruleNames: [String]?, _ stop: RuleContext?) -> String { open func toString(_ ruleNames: [String]?, _ stop: RuleContext?) -> String {
let buf = StringBuilder() var buf = ""
var p: RuleContext? = self var p: RuleContext? = self
buf.append("[") buf += "["
while let pWrap = p, pWrap !== stop { while let pWrap = p, pWrap !== stop {
if let ruleNames = ruleNames { if let ruleNames = ruleNames {
let ruleIndex = pWrap.getRuleIndex() let ruleIndex = pWrap.getRuleIndex()
let ruleIndexInRange = (ruleIndex >= 0 && ruleIndex < ruleNames.count) let ruleIndexInRange = (ruleIndex >= 0 && ruleIndex < ruleNames.count)
let ruleName = (ruleIndexInRange ? ruleNames[ruleIndex] : String(ruleIndex)) let ruleName = (ruleIndexInRange ? ruleNames[ruleIndex] : String(ruleIndex))
buf.append(ruleName) buf += ruleName
} }
else { else {
if !pWrap.isEmpty() { if !pWrap.isEmpty() {
buf.append(pWrap.invokingState) buf += String(pWrap.invokingState)
} }
} }
if pWrap.parent != nil && (ruleNames != nil || !pWrap.parent!.isEmpty()) { if pWrap.parent != nil && (ruleNames != nil || !pWrap.parent!.isEmpty()) {
buf.append(" ") buf += " "
} }
p = pWrap.parent p = pWrap.parent
} }
buf.append("]") buf += "]"
return buf.toString() return buf
} }
open func castdown<T>(_ subType: T.Type) -> T { open func castdown<T>(_ subType: T.Type) -> T {

View File

@ -163,18 +163,14 @@ public class RuntimeMetaData {
/// only the major and minor components of the version string. /// only the major and minor components of the version string.
/// ///
public static func getMajorMinorVersion(_ version: String) -> String { public static func getMajorMinorVersion(_ version: String) -> String {
let firstDot: Int = version.indexOf(".") var result = version
let secondDot: Int = firstDot >= 0 ? version.indexOf(".", startIndex: firstDot + 1) : -1
let firstDash: Int = version.indexOf("-") let dotBits = version.split(separator: ".", maxSplits: 2, omittingEmptySubsequences: false)
var referenceLength: Int = version.length if dotBits.count >= 2 {
if secondDot >= 0 { result = dotBits[0..<2].joined(separator: ".")
referenceLength = min(referenceLength, secondDot)
} }
if firstDash >= 0 { let dashBits = result.split(separator: "-", maxSplits: 1, omittingEmptySubsequences: false)
referenceLength = min(referenceLength, firstDash) return String(dashBits[0])
}
return version[0 ..< referenceLength] // version.substring(0, referenceLength);
} }
} }

View File

@ -84,19 +84,19 @@
import Foundation import Foundation
public class TokenStreamRewriter { public class TokenStreamRewriter {
public let DEFAULT_PROGRAM_NAME: String = "default" public let DEFAULT_PROGRAM_NAME = "default"
public static let PROGRAM_INIT_SIZE: Int = 100 public static let PROGRAM_INIT_SIZE = 100
public static let MIN_TOKEN_INDEX: Int = 0 public static let MIN_TOKEN_INDEX = 0
// Define the rewrite operation hierarchy // Define the rewrite operation hierarchy
public class RewriteOperation: CustomStringConvertible { public class RewriteOperation: CustomStringConvertible {
/// What index into rewrites List are we? /// What index into rewrites List are we?
internal var instructionIndex: Int = 0 internal var instructionIndex = 0
/// Token buffer index. /// Token buffer index.
internal var index: Int internal var index: Int
internal var text: String? internal var text: String?
internal var lastIndex: Int = 0 internal var lastIndex = 0
internal weak var tokens: TokenStream! internal weak var tokens: TokenStream!
init(_ index: Int, _ tokens: TokenStream) { init(_ index: Int, _ tokens: TokenStream) {
self.index = index self.index = index
@ -112,7 +112,7 @@ public class TokenStreamRewriter {
/// Execute the rewrite operation by possibly adding to the buffer. /// Execute the rewrite operation by possibly adding to the buffer.
/// Return the index of the next token to operate on. /// Return the index of the next token to operate on.
/// ///
public func execute(_ buf: StringBuilder) throws -> Int { public func execute(_ buf: inout String) throws -> Int {
return index return index
} }
@ -123,16 +123,13 @@ public class TokenStreamRewriter {
} }
public class InsertBeforeOp: RewriteOperation { public class InsertBeforeOp: RewriteOperation {
public override init(_ index: Int, _ text: String?, _ tokens: TokenStream) { override public func execute(_ buf: inout String) throws -> Int {
super.init(index, text, tokens) if let text = text {
} buf.append(text)
override public func execute(_ buf: StringBuilder) throws -> Int {
if text != nil {
buf.append(text!)
} }
if try tokens.get(index).getType() != CommonToken.EOF { let token = try tokens.get(index)
buf.append(try tokens.get(index).getText()!) if token.getType() != CommonToken.EOF {
buf.append(token.getText()!)
} }
return index + 1 return index + 1
} }
@ -146,7 +143,7 @@ public class TokenStreamRewriter {
/// I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp /// I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp
/// instructions. /// instructions.
/// ///
public class ReplaceOp: RewriteOperation { public class ReplaceOp: RewriteOperation {
@ -156,27 +153,32 @@ public class TokenStreamRewriter {
} }
override override
public func execute(_ buf: StringBuilder) -> Int { public func execute(_ buf: inout String) -> Int {
if text != nil { if let text = text {
buf.append(text!) buf += text
} }
return lastIndex + 1 return lastIndex + 1
} }
override override
public var description: String { public var description: String {
if text == nil { let token = try! tokens.get(index)
return "<DeleteOp@\(try! tokens.get(index))..\(try! tokens.get(lastIndex))>" let lastToken = try! tokens.get(lastIndex)
if let text = text {
return "<ReplaceOp@\(token)..\(lastToken):\"\(text)\">"
} }
return "<ReplaceOp@\(try! tokens.get(index))..\(try! tokens.get(lastIndex)):\"\(text!)\">" return "<DeleteOp@\(token)..\(lastToken)>"
} }
} }
public class RewriteOperationArray{ public class RewriteOperationArray{
private final var rewrites: Array<RewriteOperation?> = Array<RewriteOperation?>() private final var rewrites = [RewriteOperation?]()
public init(){
public init() {
rewrites.reserveCapacity(TokenStreamRewriter.PROGRAM_INIT_SIZE) rewrites.reserveCapacity(TokenStreamRewriter.PROGRAM_INIT_SIZE)
} }
final func append(_ op: RewriteOperation){
final func append(_ op: RewriteOperation) {
op.instructionIndex = rewrites.count op.instructionIndex = rewrites.count
rewrites.append(op) rewrites.append(op)
} }
@ -184,12 +186,15 @@ public class TokenStreamRewriter {
final func rollback(_ instructionIndex: Int) { final func rollback(_ instructionIndex: Int) {
rewrites = Array(rewrites[TokenStreamRewriter.MIN_TOKEN_INDEX ..< instructionIndex]) rewrites = Array(rewrites[TokenStreamRewriter.MIN_TOKEN_INDEX ..< instructionIndex])
} }
final var count: Int{
final var count: Int {
return rewrites.count return rewrites.count
} }
final var isEmpty: Bool{
final var isEmpty: Bool {
return rewrites.isEmpty return rewrites.isEmpty
} }
/// We need to combine operations and report invalid operations (like /// We need to combine operations and report invalid operations (like
/// overlapping replaces that are not completed nested). Inserts to /// overlapping replaces that are not completed nested). Inserts to
/// same index need to be combined etc... Here are the cases: /// same index need to be combined etc... Here are the cases:
@ -239,37 +244,34 @@ public class TokenStreamRewriter {
/// ///
/// Return a map from token index to operation. /// Return a map from token index to operation.
/// ///
final func reduceToSingleOperationPerIndex() throws -> Dictionary<Int, RewriteOperation> { final func reduceToSingleOperationPerIndex() throws -> [Int: RewriteOperation] {
let rewritesCount = rewrites.count let rewritesCount = rewrites.count
// WALK REPLACES // WALK REPLACES
for i in 0..<rewritesCount { for i in 0..<rewritesCount {
guard let rop = rewrites[i] else { guard let rop = rewrites[i] as? ReplaceOp else {
continue
}
if !(rop is ReplaceOp) {
continue continue
} }
// Wipe prior inserts within range // Wipe prior inserts within range
let inserts = getKindOfOps(&rewrites, InsertBeforeOp.self, i) let inserts = getKindOfOps(&rewrites, InsertBeforeOp.self, i)
for j in inserts { for j in inserts {
if let iop = rewrites[j] { if let iop = rewrites[j] {
if iop.index == rop.index { if iop.index == rop.index {
// E.g., insert before 2, delete 2..2; update replace // E.g., insert before 2, delete 2..2; update replace
// text to include insert before, kill insert // text to include insert before, kill insert
rewrites[iop.instructionIndex] = nil rewrites[iop.instructionIndex] = nil
rop.text = catOpText(iop.text, rop.text) rop.text = catOpText(iop.text, rop.text)
}
} else if iop.index > rop.index && iop.index <= rop.lastIndex { else if iop.index > rop.index && iop.index <= rop.lastIndex {
// delete insert as it's a no-op. // delete insert as it's a no-op.
rewrites[iop.instructionIndex] = nil rewrites[iop.instructionIndex] = nil
} }
} }
} }
// Drop any prior replaces contained within // Drop any prior replaces contained within
let prevRopIndexList = getKindOfOps(&rewrites, ReplaceOp.self, i) let prevRopIndexList = getKindOfOps(&rewrites, ReplaceOp.self, i)
for j in prevRopIndexList { for j in prevRopIndexList {
if let prevRop = rewrites[j] { if let prevRop = rewrites[j] {
if prevRop.index >= rop.index && prevRop.lastIndex <= rop.lastIndex { if prevRop.index >= rop.index && prevRop.lastIndex <= rop.lastIndex {
// delete replace as it's a no-op. // delete replace as it's a no-op.
@ -285,7 +287,6 @@ public class TokenStreamRewriter {
rewrites[prevRop.instructionIndex] = nil // kill first delete rewrites[prevRop.instructionIndex] = nil // kill first delete
rop.index = min(prevRop.index, rop.index) rop.index = min(prevRop.index, rop.index)
rop.lastIndex = max(prevRop.lastIndex, rop.lastIndex) rop.lastIndex = max(prevRop.lastIndex, rop.lastIndex)
print("new rop \(rop)")
} else if !disjoint { } else if !disjoint {
throw ANTLRError.illegalArgument(msg: "replace op boundaries of \(rop.description) " + throw ANTLRError.illegalArgument(msg: "replace op boundaries of \(rop.description) " +
"overlap with previous \(prevRop.description)") "overlap with previous \(prevRop.description)")
@ -341,9 +342,9 @@ public class TokenStreamRewriter {
} }
} }
var m: Dictionary<Int, RewriteOperation> = Dictionary<Int, RewriteOperation>() var m = [Int: RewriteOperation]()
for i in 0..<rewritesCount { for i in 0..<rewritesCount {
if let op: RewriteOperation = rewrites[i] { if let op = rewrites[i] {
if m[op.index] != nil { if m[op.index] != nil {
throw ANTLRError.illegalArgument(msg: "should only be one op per index") throw ANTLRError.illegalArgument(msg: "should only be one op per index")
} }
@ -355,17 +356,16 @@ public class TokenStreamRewriter {
} }
final func catOpText(_ a: String?, _ b: String?) -> String { final func catOpText(_ a: String?, _ b: String?) -> String {
let x: String = a ?? "" let x = a ?? ""
let y: String = b ?? "" let y = b ?? ""
return x + y return x + y
} }
/// Get all operations before an index of a particular kind /// Get all operations before an index of a particular kind
final func getKindOfOps<T: RewriteOperation>(_ rewrites: inout [RewriteOperation?], _ kind: T.Type, _ before: Int ) -> [Int] { final func getKindOfOps<T: RewriteOperation>(_ rewrites: inout [RewriteOperation?], _ kind: T.Type, _ before: Int ) -> [Int] {
let length = min(before,rewrites.count) let length = min(before, rewrites.count)
var op = [Int]() var op = [Int]()
op.reserveCapacity(length) op.reserveCapacity(length)
for i in 0..<length { for i in 0..<length {
@ -375,7 +375,6 @@ public class TokenStreamRewriter {
} }
return op return op
} }
} }
/// Our source stream /// Our source stream
@ -385,14 +384,13 @@ public class TokenStreamRewriter {
/// I'm calling these things "programs." /// I'm calling these things "programs."
/// Maps String (name) &rarr; rewrite (List) /// Maps String (name) &rarr; rewrite (List)
/// ///
internal var programs: Dictionary<String, RewriteOperationArray> //Array<RewriteOperation> internal var programs = [String: RewriteOperationArray]()
/// Map String (program name) &rarr; Integer index /// Map String (program name) &rarr; Integer index
internal final var lastRewriteTokenIndexes: Dictionary<String, Int> internal final var lastRewriteTokenIndexes: [String: Int]
public init(_ tokens: TokenStream) { public init(_ tokens: TokenStream) {
self.tokens = tokens self.tokens = tokens
programs = Dictionary<String, RewriteOperationArray>()
programs[DEFAULT_PROGRAM_NAME] = RewriteOperationArray() programs[DEFAULT_PROGRAM_NAME] = RewriteOperationArray()
lastRewriteTokenIndexes = Dictionary<String, Int>() lastRewriteTokenIndexes = Dictionary<String, Int>()
} }
@ -439,7 +437,7 @@ public class TokenStreamRewriter {
public func insertAfter(_ programName: String, _ index: Int, _ text: String) { public func insertAfter(_ programName: String, _ index: Int, _ text: String) {
// to insert after, just insert before next index (even if past end) // to insert after, just insert before next index (even if past end)
let op = InsertAfterOp(index, text, tokens) let op = InsertAfterOp(index, text, tokens)
let rewrites = getProgram(programName) let rewrites = getProgram(programName)
rewrites.append(op) rewrites.append(op)
} }
@ -456,8 +454,8 @@ public class TokenStreamRewriter {
} }
public func insertBefore(_ programName: String, _ index: Int, _ text: String) { public func insertBefore(_ programName: String, _ index: Int, _ text: String) {
let op: RewriteOperation = InsertBeforeOp(index, text, tokens) let op = InsertBeforeOp(index, text, tokens)
let rewrites: RewriteOperationArray = getProgram(programName) let rewrites = getProgram(programName)
rewrites.append(op) rewrites.append(op)
} }
@ -481,10 +479,9 @@ public class TokenStreamRewriter {
if from > to || from < 0 || to < 0 || to >= tokens.size() { if from > to || from < 0 || to < 0 || to >= tokens.size() {
throw ANTLRError.illegalArgument(msg: "replace: range invalid: \(from)..\(to)(size=\(tokens.size()))") throw ANTLRError.illegalArgument(msg: "replace: range invalid: \(from)..\(to)(size=\(tokens.size()))")
} }
let op: RewriteOperation = ReplaceOp(from, to, text, tokens) let op = ReplaceOp(from, to, text, tokens)
let rewritesArray: RewriteOperationArray = getProgram(programName) let rewritesArray = getProgram(programName)
rewritesArray.append(op) rewritesArray.append(op)
} }
public func replace(_ programName: String, _ from: Token, _ to: Token, _ text: String?) throws { public func replace(_ programName: String, _ from: Token, _ to: Token, _ text: String?) throws {
@ -523,30 +520,24 @@ public class TokenStreamRewriter {
} }
internal func getLastRewriteTokenIndex(_ programName: String) -> Int { internal func getLastRewriteTokenIndex(_ programName: String) -> Int {
let I: Int? = lastRewriteTokenIndexes[programName] return lastRewriteTokenIndexes[programName] ?? -1
if I == nil {
return -1
}
return I!
} }
internal func setLastRewriteTokenIndex(_ programName: String, _ i: Int) { internal func setLastRewriteTokenIndex(_ programName: String, _ i: Int) {
lastRewriteTokenIndexes[programName] = i lastRewriteTokenIndexes[programName] = i
} }
internal func getProgram(_ name: String) -> RewriteOperationArray internal func getProgram(_ name: String) -> RewriteOperationArray {
{ if let program = programs[name] {
var program: RewriteOperationArray? = programs[name] return program
if program == nil { }
program = initializeProgram(name) else {
return initializeProgram(name)
} }
return program!
} }
private func initializeProgram(_ name: String) -> RewriteOperationArray private func initializeProgram(_ name: String) -> RewriteOperationArray {
{ let program = RewriteOperationArray()
let program: RewriteOperationArray = RewriteOperationArray()
programs[name] = program programs[name] = program
return program return program
} }
@ -579,8 +570,8 @@ public class TokenStreamRewriter {
} }
public func getText(_ programName: String, _ interval: Interval) throws -> String { public func getText(_ programName: String, _ interval: Interval) throws -> String {
var start: Int = interval.a var start = interval.a
var stop: Int = interval.b var stop = interval.b
// ensure start/end are in range // ensure start/end are in range
if stop > tokens.size() - 1 { if stop > tokens.size() - 1 {
@ -589,32 +580,31 @@ public class TokenStreamRewriter {
if start < 0 { if start < 0 {
start = 0 start = 0
} }
guard let rewrites = programs[programName] , !rewrites.isEmpty else { guard let rewrites = programs[programName], !rewrites.isEmpty else {
return try tokens.getText(interval) // no instructions to execute return try tokens.getText(interval) // no instructions to execute
} }
let buf: StringBuilder = StringBuilder() var buf = ""
// First, optimize instruction stream // First, optimize instruction stream
var indexToOp: Dictionary<Int, RewriteOperation> = try rewrites.reduceToSingleOperationPerIndex() var indexToOp = try rewrites.reduceToSingleOperationPerIndex()
// Walk buffer, executing instructions and emitting tokens // Walk buffer, executing instructions and emitting tokens
var i: Int = start var i = start
while i <= stop && i < tokens.size() { while i <= stop && i < tokens.size() {
let op: RewriteOperation? = indexToOp[i] let op = indexToOp[i]
indexToOp.removeValue(forKey: i) indexToOp.removeValue(forKey: i) // remove so any left have index size-1
//indexToOp.remove(i); // remove so any left have index size-1 let t = try tokens.get(i)
let t: Token = try tokens.get(i) if let op = op {
if op == nil { i = try op.execute(&buf) // execute operation and skip
}
else {
// no operation at that index, just dump token // no operation at that index, just dump token
if t.getType() != CommonToken.EOF { if t.getType() != CommonToken.EOF {
buf.append(t.getText()!) buf.append(t.getText()!)
} }
i += 1 // move to next token i += 1 // move to next token
} else {
i = try op!.execute(buf) // execute operation and skip
} }
} }
// include stuff after end if it's last index in buffer // include stuff after end if it's last index in buffer
@ -623,14 +613,13 @@ public class TokenStreamRewriter {
if stop == tokens.size() - 1 { if stop == tokens.size() - 1 {
// Scan any remaining operations after last token // Scan any remaining operations after last token
// should be included (they will be inserts). // should be included (they will be inserts).
for op: RewriteOperation in indexToOp.values { for op in indexToOp.values {
if op.index >= tokens.size() - 1 { if op.index >= tokens.size() - 1 {
buf.append(op.text!) buf += op.text!
} }
} }
} }
return buf.toString() return buf
} }
} }

View File

@ -284,27 +284,23 @@ public class UnbufferedTokenStream: TokenStream {
public func getText(_ interval: Interval) throws -> String { public func getText(_ interval: Interval) throws -> String {
let bufferStartIndex: Int = getBufferStartIndex() let bufferStartIndex = getBufferStartIndex()
let bufferStopIndex: Int = bufferStartIndex + tokens.count - 1 let bufferStopIndex = bufferStartIndex + tokens.count - 1
let start: Int = interval.a let start = interval.a
let stop: Int = interval.b let stop = interval.b
if start < bufferStartIndex || stop > bufferStopIndex { if start < bufferStartIndex || stop > bufferStopIndex {
throw ANTLRError.unsupportedOperation(msg: "interval \(interval) not in token buffer window: \(bufferStartIndex)..bufferStopIndex)") throw ANTLRError.unsupportedOperation(msg: "interval \(interval) not in token buffer window: \(bufferStartIndex)..bufferStopIndex)")
} }
let a: Int = start - bufferStartIndex let a = start - bufferStartIndex
let b: Int = stop - bufferStartIndex let b = stop - bufferStartIndex
let buf: StringBuilder = StringBuilder() var buf = ""
for i in a...b { for t in tokens[a...b] {
let t: Token = tokens[i] buf += t.getText()!
buf.append(t.getText()!)
} }
return buf
return buf.toString()
} }
internal final func getBufferStartIndex() -> Int { internal final func getBufferStartIndex() -> Int {

View File

@ -85,27 +85,25 @@ public class Vocabulary: Hashable {
/// the display names of tokens. /// the display names of tokens.
/// ///
public static func fromTokenNames(_ tokenNames: [String?]?) -> Vocabulary { public static func fromTokenNames(_ tokenNames: [String?]?) -> Vocabulary {
guard let tokenNames = tokenNames , tokenNames.count > 0 else { guard let tokenNames = tokenNames, tokenNames.count > 0 else {
return EMPTY_VOCABULARY return EMPTY_VOCABULARY
} }
var literalNames: [String?] = tokenNames// Arrays.copyOf(tokenNames, tokenNames.length); var literalNames = tokenNames
var symbolicNames: [String?] = tokenNames var symbolicNames = tokenNames
let length = tokenNames.count let length = tokenNames.count
for i in 0..<length { for i in 0..<length {
guard let tokenName = tokenNames[i] else { guard let tokenName = tokenNames[i] else {
continue continue
} }
if !tokenName.isEmpty { if let firstChar = tokenName.first {
let firstChar: Character = tokenName[0]
if firstChar == "\'" { if firstChar == "\'" {
symbolicNames[i] = nil symbolicNames[i] = nil
continue continue
} else { }
if String(firstChar).uppercased() != String(firstChar) { else if String(firstChar).uppercased() != String(firstChar) {
literalNames[i] = nil literalNames[i] = nil
continue continue
}
} }
} }
@ -141,20 +139,17 @@ public class Vocabulary: Hashable {
public func getDisplayName(_ tokenType: Int) -> String { public func getDisplayName(_ tokenType: Int) -> String {
if tokenType >= 0 && tokenType < displayNames.count { if tokenType >= 0 && tokenType < displayNames.count {
let displayName: String? = displayNames[tokenType] if let displayName = displayNames[tokenType] {
if displayName != nil { return displayName
return displayName!
} }
} }
let literalName: String? = getLiteralName(tokenType) if let literalName = getLiteralName(tokenType) {
if literalName != nil { return literalName
return literalName!
} }
let symbolicName: String? = getSymbolicName(tokenType) if let symbolicName = getSymbolicName(tokenType) {
if symbolicName != nil { return symbolicName
return symbolicName!
} }
return String(tokenType) return String(tokenType)

View File

@ -159,37 +159,27 @@ public class ATNConfig: Hashable, CustomStringConvertible {
} }
public func toString() -> String {
return description
}
public var description: String { public var description: String {
//return "MyClass \(string)" //return "MyClass \(string)"
return toString(nil, true) return toString(nil, true)
} }
public func toString<T>(_ recog: Recognizer<T>?, _ showAlt: Bool) -> String { public func toString<T>(_ recog: Recognizer<T>?, _ showAlt: Bool) -> String {
let buf: StringBuilder = StringBuilder() var buf = "(\(state)"
buf.append("(")
buf.append(state)
if showAlt { if showAlt {
buf.append(",") buf += ",\(alt)"
buf.append(alt)
} }
if let context = context {
if context != nil { buf += ",[\(context)]"
buf.append(",[")
buf.append(context!)
buf.append("]")
} }
if semanticContext != SemanticContext.NONE { if semanticContext != SemanticContext.NONE {
buf.append(",") buf += ",\(semanticContext)"
buf.append(semanticContext)
} }
if getOuterContextDepth() > 0 { let outerDepth = getOuterContextDepth()
buf.append(",up=").append(getOuterContextDepth()) if outerDepth > 0 {
buf += ",up=\(outerDepth)"
} }
buf.append(")") buf += ")"
return buf.toString() return buf
} }
} }

View File

@ -275,27 +275,21 @@ public class ATNConfigSet: Hashable, CustomStringConvertible {
} }
public var description: String { public var description: String {
let buf = StringBuilder() var buf = ""
buf.append(elements().map({ $0.description })) buf += String(describing: elements())
if hasSemanticContext { if hasSemanticContext {
buf.append(",hasSemanticContext=") buf += ",hasSemanticContext=true"
buf.append(hasSemanticContext)
} }
if uniqueAlt != ATN.INVALID_ALT_NUMBER { if uniqueAlt != ATN.INVALID_ALT_NUMBER {
buf.append(",uniqueAlt=") buf += ",uniqueAlt=\(uniqueAlt)"
buf.append(uniqueAlt)
} }
if let conflictingAlts = conflictingAlts { if let conflictingAlts = conflictingAlts {
buf.append(",conflictingAlts=") buf += ",conflictingAlts=\(conflictingAlts)"
buf.append(conflictingAlts.description)
} }
if dipsIntoOuterContext { if dipsIntoOuterContext {
buf.append(",dipsIntoOuterContext") buf += ",dipsIntoOuterContext"
} }
return buf.toString() return buf
}
public func toString() -> String {
return description
} }
/// ///

View File

@ -136,9 +136,6 @@ public class ATNState: Hashable, CustomStringConvertible {
} }
public func toString() -> String {
return description
}
public var description: String { public var description: String {
//return "MyClass \(string)" //return "MyClass \(string)"
return String(stateNumber) return String(stateNumber)

View File

@ -58,28 +58,25 @@ public class ArrayPredictionContext: PredictionContext {
if isEmpty() { if isEmpty() {
return "[]" return "[]"
} }
let buf: StringBuilder = StringBuilder() var buf = "["
buf.append("[") for (i, returnState) in returnStates.enumerated() {
let length = returnStates.count
for i in 0..<length {
if i > 0 { if i > 0 {
buf.append(", ") buf += ", "
} }
if returnStates[i] == PredictionContext.EMPTY_RETURN_STATE { if returnState == PredictionContext.EMPTY_RETURN_STATE {
buf.append("$") buf += "$"
continue continue
} }
buf.append(returnStates[i]) buf += "\(returnState)"
if parents[i] != nil { if let parent = parents[i] {
buf.append(" ") buf += " \(parent)"
buf.append(parents[i].debugDescription) }
} else { else {
buf.append("null") buf += "null"
} }
} }
buf.append("]") buf += "]"
return buf.toString() return buf
} }
internal final func combineCommonParents() { internal final func combineCommonParents() {

View File

@ -225,21 +225,22 @@ public class DecisionInfo: CustomStringConvertible {
public var description: String { public var description: String {
let desc: StringBuilder = StringBuilder() var desc = ""
desc.append("{")
desc.append("decision=\(decision)")
desc.append(", contextSensitivities=\(contextSensitivities.count)")
desc.append(", errors=\(errors.count)")
desc.append(", ambiguities=\(ambiguities.count)")
desc.append(", SLL_lookahead=\(SLL_TotalLook)")
desc.append(", SLL_ATNTransitions=\(SLL_ATNTransitions)")
desc.append(", SLL_DFATransitions=\(SLL_DFATransitions)")
desc.append(", LL_Fallback=\(LL_Fallback)")
desc.append(", LL_lookahead=\(LL_TotalLook)")
desc.append(", LL_ATNTransitions=\(LL_ATNTransitions)")
desc.append("}")
return desc.toString() desc += "{"
desc += "decision=\(decision)"
desc += ", contextSensitivities=\(contextSensitivities.count)"
desc += ", errors=\(errors.count)"
desc += ", ambiguities=\(ambiguities.count)"
desc += ", SLL_lookahead=\(SLL_TotalLook)"
desc += ", SLL_ATNTransitions=\(SLL_ATNTransitions)"
desc += ", SLL_DFATransitions=\(SLL_DFATransitions)"
desc += ", LL_Fallback=\(LL_Fallback)"
desc += ", LL_lookahead=\(LL_TotalLook)"
desc += ", LL_ATNTransitions=\(LL_ATNTransitions)"
desc += "}"
return desc
} }
} }

View File

@ -1907,7 +1907,7 @@ open class ParserATNSimulator: ATNSimulator {
} }
else if let st = t as? SetTransition { else if let st = t as? SetTransition {
let not = st is NotSetTransition let not = st is NotSetTransition
trans = (not ? "~" : "") + "Set " + st.set.toString() trans = (not ? "~" : "") + "Set " + st.set.description
} }
} }
errPrint("\(c.toString(parser, true)):\(trans)") errPrint("\(c.toString(parser, true)):\(trans)")

View File

@ -42,9 +42,4 @@ public final class PrecedencePredicateTransition: AbstractPredicateTransition, C
public var description: String { public var description: String {
return "\(precedence) >= _p" return "\(precedence) >= _p"
} }
public func toString() -> String {
return description
}
} }

View File

@ -14,7 +14,7 @@
/// multiple ATN configurations into a single DFA state. /// multiple ATN configurations into a single DFA state.
/// ///
public final class PredicateTransition: AbstractPredicateTransition { public final class PredicateTransition: AbstractPredicateTransition, CustomStringConvertible {
public let ruleIndex: Int public let ruleIndex: Int
public let predIndex: Int public let predIndex: Int
public let isCtxDependent: Bool public let isCtxDependent: Bool
@ -47,9 +47,7 @@ public final class PredicateTransition: AbstractPredicateTransition {
return SemanticContext.Predicate(ruleIndex, predIndex, isCtxDependent) return SemanticContext.Predicate(ruleIndex, predIndex, isCtxDependent)
} }
public var description: String {
public func toString() -> String {
return "pred_\(ruleIndex):\(predIndex)" return "pred_\(ruleIndex):\(predIndex)"
} }
} }

View File

@ -518,47 +518,40 @@ public class PredictionContext: Hashable, CustomStringConvertible {
if context == nil { if context == nil {
return "" return ""
} }
let buf = StringBuilder() var buf = ""
buf.append("digraph G {\n") buf += "digraph G {\n"
buf.append("rankdir=LR;\n") buf += "rankdir=LR;\n"
var nodes = getAllContextNodes(context!) var nodes = getAllContextNodes(context!)
nodes.sort { $0.id > $1.id } nodes.sort { $0.id > $1.id }
for current in nodes { for current in nodes {
if current is SingletonPredictionContext { if current is SingletonPredictionContext {
let s = String(current.id) buf += " s\(current.id)"
buf.append(" s").append(s)
var returnState = String(current.getReturnState(0)) var returnState = String(current.getReturnState(0))
if current is EmptyPredictionContext { if current is EmptyPredictionContext {
returnState = "$" returnState = "$"
} }
buf.append(" [label=\"") buf += " [label=\"\(returnState)\"];\n"
buf.append(returnState)
buf.append("\"];\n")
continue continue
} }
let arr = current as! ArrayPredictionContext let arr = current as! ArrayPredictionContext
buf.append(" s").append(arr.id) buf += " s\(arr.id) [shape=box, label=\"["
buf.append(" [shape=box, label=\"")
buf.append("[")
var first = true var first = true
let returnStates = arr.returnStates let returnStates = arr.returnStates
for inv in returnStates { for inv in returnStates {
if !first { if !first {
buf.append(", ") buf += ", "
} }
if inv == EMPTY_RETURN_STATE { if inv == EMPTY_RETURN_STATE {
buf.append("$") buf += "$"
} else { } else {
buf.append(inv) buf += String(inv)
} }
first = false first = false
} }
buf.append("]") buf += "]\"];\n"
buf.append("\"];\n")
} }
for current in nodes { for current in nodes {
@ -570,21 +563,17 @@ public class PredictionContext: Hashable, CustomStringConvertible {
guard let currentParent = current.getParent(i) else { guard let currentParent = current.getParent(i) else {
continue continue
} }
let s = String(current.id) buf += " s\(current.id) -> s\(currentParent.id)"
buf.append(" s").append(s)
buf.append("->")
buf.append("s")
buf.append(currentParent.id)
if current.size() > 1 { if current.size() > 1 {
buf.append(" [label=\"parent[\(i)]\"];\n") buf += " [label=\"parent[\(i)]\"];\n"
} else { } else {
buf.append(";\n") buf += ";\n"
} }
} }
} }
buf.append("}\n") buf.append("}\n")
return buf.toString() return buf
} }
// From Sam // From Sam
@ -700,8 +689,7 @@ public class PredictionContext: Hashable, CustomStringConvertible {
var last = true var last = true
var p = self var p = self
var stateNumber = currentState var stateNumber = currentState
let localBuffer = StringBuilder() var localBuffer = "["
localBuffer.append("[")
while !p.isEmpty() && p !== stop { while !p.isEmpty() && p !== stop {
var index = 0 var index = 0
if p.size() > 0 { if p.size() > 0 {
@ -724,9 +712,9 @@ public class PredictionContext: Hashable, CustomStringConvertible {
} }
if let recognizer = recognizer { if let recognizer = recognizer {
if localBuffer.length > 1 { if localBuffer.count > 1 {
// first char is '[', if more than that this isn't the first rule // first char is '[', if more than that this isn't the first rule
localBuffer.append(" ") localBuffer += " "
} }
let atn = recognizer.getATN() let atn = recognizer.getATN()
@ -736,19 +724,19 @@ public class PredictionContext: Hashable, CustomStringConvertible {
} }
else if p.getReturnState(index) != PredictionContext.EMPTY_RETURN_STATE { else if p.getReturnState(index) != PredictionContext.EMPTY_RETURN_STATE {
if !p.isEmpty() { if !p.isEmpty() {
if localBuffer.length > 1 { if localBuffer.count > 1 {
// first char is '[', if more than that this isn't the first rule // first char is '[', if more than that this isn't the first rule
localBuffer.append(" ") localBuffer += " "
} }
localBuffer.append(p.getReturnState(index)) localBuffer += String(p.getReturnState(index))
} }
} }
stateNumber = p.getReturnState(index) stateNumber = p.getReturnState(index)
p = p.getParent(index)! p = p.getParent(index)!
} }
localBuffer.append("]") localBuffer += "]"
result.append(localBuffer.toString()) result.append(localBuffer)
if last { if last {
break break

View File

@ -31,11 +31,6 @@ public final class RangeTransition: Transition, CustomStringConvertible {
return symbol >= from && symbol <= to return symbol >= from && symbol <= to
} }
public func toString() -> String {
return description
}
public var description: String { public var description: String {
return "'" + String(from) + "'..'" + String(to) + "'" return "'" + String(from) + "'..'" + String(to) + "'"

View File

@ -277,10 +277,6 @@ public class SemanticContext: Hashable, CustomStringConvertible {
return result return result
} }
public func toString() -> String {
return description
}
override override
public var description: String { public var description: String {
return opnds.map({ $0.description }).joined(separator: "&&") return opnds.map({ $0.description }).joined(separator: "&&")
@ -386,11 +382,6 @@ public class SemanticContext: Hashable, CustomStringConvertible {
return result return result
} }
public func toString() -> String {
return description
}
override override
public var description: String { public var description: String {
return opnds.map({ $0.description }).joined(separator: "||") return opnds.map({ $0.description }).joined(separator: "||")

View File

@ -49,8 +49,8 @@ public class SingletonPredictionContext: PredictionContext {
override override
public var description: String { public var description: String {
let up: String = parent != nil ? parent!.description : "" let up = parent?.description ?? ""
if up.length == 0 { if up.isEmpty {
if returnState == PredictionContext.EMPTY_RETURN_STATE { if returnState == PredictionContext.EMPTY_RETURN_STATE {
return "$" return "$"
} }

View File

@ -165,18 +165,13 @@ public class DFA: CustomStringConvertible {
return toString(Vocabulary.EMPTY_VOCABULARY) return toString(Vocabulary.EMPTY_VOCABULARY)
} }
public func toString() -> String {
return description
}
public func toString(_ vocabulary: Vocabulary) -> String { public func toString(_ vocabulary: Vocabulary) -> String {
if s0 == nil { if s0 == nil {
return "" return ""
} }
let serializer = DFASerializer(self, vocabulary) let serializer = DFASerializer(self, vocabulary)
return serializer.toString() return serializer.description
} }
public func toLexerString() -> String { public func toLexerString() -> String {
@ -184,7 +179,7 @@ public class DFA: CustomStringConvertible {
return "" return ""
} }
let serializer = LexerDFASerializer(self) let serializer = LexerDFASerializer(self)
return serializer.toString() return serializer.description
} }
} }

View File

@ -22,37 +22,25 @@ public class DFASerializer: CustomStringConvertible {
if dfa.s0 == nil { if dfa.s0 == nil {
return "" return ""
} }
let buf = StringBuilder() var buf = ""
let states = dfa.getStates() let states = dfa.getStates()
for s in states { for s in states {
guard let edges = s.edges else { guard let edges = s.edges else {
continue continue
} }
let n = edges.count for (i, t) in edges.enumerated() {
for i in 0..<n { guard let t = t, t.stateNumber != Int.max else {
if let t = s.edges![i], t.stateNumber != Int.max { continue
buf.append(getStateString(s))
let label = getEdgeLabel(i)
buf.append("-")
buf.append(label)
buf.append("->")
buf.append(getStateString(t))
buf.append("\n")
} }
let edgeLabel = getEdgeLabel(i)
buf += getStateString(s)
buf += "-\(edgeLabel)->"
buf += getStateString(t)
buf += "\n"
} }
} }
let output = buf.toString() return buf
if output.length == 0 {
return ""
}
//return Utils.sortLinesInString(output);
return output
}
public func toString() -> String {
return description
} }
internal func getEdgeLabel(_ i: Int) -> String { internal func getEdgeLabel(_ i: Int) -> String {

View File

@ -136,17 +136,17 @@ public class DFAState: Hashable, CustomStringConvertible {
/// _#stateNumber_ is irrelevant. /// _#stateNumber_ is irrelevant.
/// ///
public var description: String { public var description: String {
let buf = StringBuilder() var buf = "\(stateNumber):\(configs)"
buf.append(stateNumber).append(":").append(configs)
if isAcceptState { if isAcceptState {
buf.append("=>") buf += "=>"
if let predicates = predicates { if let predicates = predicates {
buf.append(predicates.map({ $0.description })) buf += String(describing: predicates)
} else { }
buf.append(prediction) else {
buf += String(prediction)
} }
} }
return buf.toString() return buf
} }
} }

View File

@ -1104,15 +1104,15 @@ public class BitSet: Hashable, CustomStringConvertible {
/// ///
/// Example: /// Example:
/// ///
/// BitSet drPepper = new BitSet(); /// `BitSet drPepper = new BitSet();`
/// Now `drPepper.toString()` returns "`{`}". /// Now `drPepper.description` returns `"{}"`.
/// ///
/// drPepper.set(2); /// `drPepper.set(2);`
/// Now `drPepper.toString()` returns "`{2`}". /// Now `drPepper.description` returns `"{2}"`.
/// ///
/// drPepper.set(4); /// `drPepper.set(4);`
/// drPepper.set(10); /// `drPepper.set(10);`
/// Now `drPepper.toString()` returns "`{2, 4, 10`}". /// Now `drPepper.description` returns `"{2, 4, 10}"`.
/// ///
/// - returns: a string representation of this bit set /// - returns: a string representation of this bit set
/// ///
@ -1121,29 +1121,24 @@ public class BitSet: Hashable, CustomStringConvertible {
//let numBits: Int = (wordsInUse > 128) ? //let numBits: Int = (wordsInUse > 128) ?
// cardinality() : wordsInUse * BitSet.BITS_PER_WORD // cardinality() : wordsInUse * BitSet.BITS_PER_WORD
let b = StringBuilder() var b = "{"
b.append("{")
var i = firstSetBit() var i = firstSetBit()
if i != -1 { if i != -1 {
b.append(i) b += String(i)
i = try! nextSetBit(i + 1) i = try! nextSetBit(i + 1)
while i >= 0 { while i >= 0 {
let endOfRun = try! nextClearBit(i) let endOfRun = try! nextClearBit(i)
repeat { repeat {
b.append(", ").append(i) b += ", \(i)"
i += 1 i += 1
} while i < endOfRun } while i < endOfRun
i = try! nextSetBit(i + 1) i = try! nextSetBit(i + 1)
} }
} }
b.append("}") b += "}"
return b.toString() return b
} }
public func toString() -> String {
return description
}
} }
public func ==(lhs: BitSet, rhs: BitSet) -> Bool { public func ==(lhs: BitSet, rhs: BitSet) -> Bool {

View File

@ -146,6 +146,4 @@ public protocol IntSet {
/// in ascending numerical order. /// in ascending numerical order.
/// ///
func toList() -> [Int] func toList() -> [Int]
func toString() -> String
} }

View File

@ -159,12 +159,6 @@ public class Interval: Hashable {
} }
public func toString() -> String {
return "\(a)..\(b)"
}
public var description: String { public var description: String {
return "\(a)..\(b)" return "\(a)..\(b)"
} }

View File

@ -105,7 +105,6 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible {
if readonly { if readonly {
throw ANTLRError.illegalState(msg: "can't alter readonly IntervalSet") throw ANTLRError.illegalState(msg: "can't alter readonly IntervalSet")
} }
//System.out.println("add "+addition+" to "+intervals.toString());
if addition.b < addition.a { if addition.b < addition.a {
return return
} }
@ -509,109 +508,112 @@ public class IntervalSet: IntSet, Hashable, CustomStringConvertible {
public var description: String { public var description: String {
return toString(false) return toString(false)
} }
public func toString() -> String {
return description
}
public func toString(_ elemAreChar: Bool) -> String { public func toString(_ elemAreChar: Bool) -> String {
let buf = StringBuilder() if intervals.isEmpty {
if self.intervals.isEmpty {
return "{}" return "{}"
} }
if self.size() > 1 {
buf.append("{") let selfSize = size()
var buf = ""
if selfSize > 1 {
buf += "{"
} }
var first = true var first = true
for interval in intervals { for interval in intervals {
if !first { if !first {
buf.append(", ") buf += ", "
} }
first = false first = false
let a = interval.a let a = interval.a
let b = interval.b let b = interval.b
if a == b { if a == b {
if a == CommonToken.EOF { if a == CommonToken.EOF {
buf.append("<EOF>") buf += "<EOF>"
} else {
if elemAreChar {
buf.append("'").append(String(a)).append("'")
} else {
buf.append(a)
}
} }
} else { else if elemAreChar {
if elemAreChar { buf += "'\(a)'"
buf.append("'").append(String(a)).append("'..'").append(String(b)).append("'") }
} else { else {
buf.append(a).append("..").append(b) buf += "\(a)"
} }
} }
else if elemAreChar {
buf += "'\(a)'..'\(b)'"
}
else {
buf += "\(a)..\(b)"
}
} }
if self.size() > 1 {
buf.append("}") if selfSize > 1 {
buf += "}"
} }
return buf.toString()
return buf
} }
public func toString(_ vocabulary: Vocabulary) -> String { public func toString(_ vocabulary: Vocabulary) -> String {
let buf = StringBuilder() if intervals.isEmpty {
if self.intervals.isEmpty {
return "{}" return "{}"
} }
if self.size() > 1 {
buf.append("{") let selfSize = size()
var buf = ""
if selfSize > 1 {
buf += "{"
} }
var first = true var first = true
for interval in intervals { for interval in intervals {
if !first { if !first {
buf.append(", ") buf += ", "
} }
first = false first = false
let a = interval.a let a = interval.a
let b = interval.b let b = interval.b
if a == b { if a == b {
buf.append(elementName(vocabulary, a)) buf += elementName(vocabulary, a)
} else { }
else {
for i in a...b { for i in a...b {
if i > a { if i > a {
buf.append(", ") buf += ", "
} }
buf.append(elementName(vocabulary, i)) buf += elementName(vocabulary, i)
} }
} }
}
if selfSize > 1 {
buf += "}"
} }
if self.size() > 1 {
buf.append("}") return buf
}
return buf.toString()
} }
internal func elementName(_ vocabulary: Vocabulary, _ a: Int) -> String { internal func elementName(_ vocabulary: Vocabulary, _ a: Int) -> String {
if a == CommonToken.EOF { if a == CommonToken.EOF {
return "<EOF>" return "<EOF>"
} else { }
if a == CommonToken.EPSILON { else if a == CommonToken.EPSILON {
return "<EPSILON>" return "<EPSILON>"
} else { }
return vocabulary.getDisplayName(a) else {
} return vocabulary.getDisplayName(a)
} }
} }
public func size() -> Int { public func size() -> Int {
var n = 0 var n = 0
let numIntervals = intervals.count for interval in intervals {
if numIntervals == 1 {
let firstInterval = intervals[0]
return firstInterval.b - firstInterval.a + 1
}
for i in 0..<numIntervals {
let interval = intervals[i]
n += (interval.b - interval.a + 1) n += (interval.b - interval.a + 1)
} }
return n return n

View File

@ -10,27 +10,25 @@ import Foundation
public class Utils { public class Utils {
public static func escapeWhitespace(_ s: String, _ escapeSpaces: Bool) -> String { public static func escapeWhitespace(_ s: String, _ escapeSpaces: Bool) -> String {
let buf: StringBuilder = StringBuilder() var buf = ""
for c: Character in s.characters { for c in s {
if c == " " && escapeSpaces { if c == " " && escapeSpaces {
buf.append("\u{00B7}") buf += "\u{00B7}"
} else { }
if c == "\t" { else if c == "\t" {
buf.append("\\t") buf += "\\t"
} else { }
if c == "\n" { else if c == "\n" {
buf.append("\\n") buf += "\\n"
} else { }
if c == "\r" { else if c == "\r" {
buf.append("\\r") buf += "\\r"
} else { }
buf.append(String(c)) else {
} buf.append(c)
}
}
} }
} }
return buf.toString() return buf
} }

View File

@ -6,62 +6,38 @@
import Foundation import Foundation
//http://stackoverflow.com/questions/28182441/swift-how-to-get-substring-from-start-to-last-index-of-character
//https://github.com/williamFalcon/Bolt_Swift/blob/master/Bolt/BoltLibrary/String/String.swift
extension String { extension String {
func lastIndex(of target: String) -> String.Index? {
var length: Int { if target.isEmpty {
return self.characters.count return nil
}
func indexOf(_ target: String) -> Int {
let range = self.range(of: target)
if let range = range {
return self.characters.distance(from: self.startIndex, to: range.lowerBound)
} else {
return -1
} }
} var result: String.Index? = nil
var substring = self[...]
func indexOf(_ target: String, startIndex: Int) -> Int { while true {
guard let targetRange = substring.range(of: target) else {
let startRange = self.characters.index(self.startIndex, offsetBy: startIndex) return result
let range = self.range(of: target, options: .literal, range: startRange..<self.endIndex)
if let range = range {
return self.characters.distance(from: self.startIndex, to: range.lowerBound)
} else {
return -1
}
}
func lastIndexOf(_ target: String) -> Int {
var index = -1
var stepIndex = self.indexOf(target)
while stepIndex > -1 {
index = stepIndex
if stepIndex + target.length < self.length {
stepIndex = indexOf(target, startIndex: stepIndex + target.length)
} else {
stepIndex = -1
} }
result = targetRange.lowerBound
let nextChar = substring.index(after: targetRange.lowerBound)
substring = self[nextChar...]
} }
return index
}
subscript(integerIndex: Int) -> Character {
let index = characters.index(startIndex, offsetBy: integerIndex)
return self[index]
} }
subscript(integerRange: Range<Int>) -> String { subscript(integerRange: Range<Int>) -> String {
let start = characters.index(startIndex, offsetBy: integerRange.lowerBound) let start = index(startIndex, offsetBy: integerRange.lowerBound)
let end = characters.index(startIndex, offsetBy: integerRange.upperBound) let end = index(startIndex, offsetBy: integerRange.upperBound)
let range = start ..< end let range = start ..< end
return String(self[range]) return String(self[range])
} }
} }
// Implement Substring.hasPrefix, which is not currently in the Linux stdlib.
// https://bugs.swift.org/browse/SR-5627
#if os(Linux)
extension Substring {
func hasPrefix(_ prefix: String) -> Bool {
return String(self).hasPrefix(prefix)
}
}
#endif

View File

@ -1,67 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
//
// StringBuilder.swift
// antlr.swift
//
// Created by janyou on 15/9/4.
//
import Foundation
public class StringBuilder {
private var stringValue: String
public init(string: String = "") {
self.stringValue = string
}
public func toString() -> String {
return stringValue
}
public var length: Int {
return stringValue.length
}
@discardableResult
public func append(_ string: String) -> StringBuilder {
stringValue += string
return self
}
@discardableResult
public func append<T:CustomStringConvertible>(_ value: T) -> StringBuilder {
stringValue += value.description
return self
}
@discardableResult
public func appendLine(_ string: String) -> StringBuilder {
stringValue += string + "\n"
return self
}
@discardableResult
public func appendLine<T:CustomStringConvertible>(_ value: T) -> StringBuilder {
stringValue += value.description + "\n"
return self
}
@discardableResult
public func clear() -> StringBuilder {
stringValue = ""
return self
}
}
public func +=(lhs: StringBuilder, rhs: String) {
lhs.append(rhs)
}
public func +=<T:CustomStringConvertible>(lhs: StringBuilder, rhs: T) {
lhs.append(rhs.description)
}
public func +(lhs: StringBuilder, rhs: StringBuilder) -> StringBuilder {
return StringBuilder(string: lhs.toString() + rhs.toString())
}

View File

@ -64,24 +64,20 @@ public class Trees {
/// parse trees and extract data appropriately. /// parse trees and extract data appropriately.
/// ///
public static func toStringTree(_ t: Tree, _ ruleNames: Array<String>?) -> String { public static func toStringTree(_ t: Tree, _ ruleNames: Array<String>?) -> String {
var s: String = Utils.escapeWhitespace(getNodeText(t, ruleNames), false) let s = Utils.escapeWhitespace(getNodeText(t, ruleNames), false)
if t.getChildCount() == 0 { if t.getChildCount() == 0 {
return s return s
} }
let buf: StringBuilder = StringBuilder() var buf = "(\(s) "
buf.append("(")
s = Utils.escapeWhitespace(getNodeText(t, ruleNames), false)
buf.append(s)
buf.append(" ")
let length = t.getChildCount() let length = t.getChildCount()
for i in 0..<length { for i in 0..<length {
if i > 0 { if i > 0 {
buf.append(" ") buf += " "
} }
buf.append(toStringTree(t.getChild(i)!, ruleNames)) buf += toStringTree(t.getChild(i)!, ruleNames)
} }
buf.append(")") buf += ")"
return buf.toString() return buf
} }
public static func getNodeText(_ t: Tree, _ recog: Parser?) -> String { public static func getNodeText(_ t: Tree, _ recog: Parser?) -> String {

View File

@ -160,9 +160,6 @@ public class ParseTreeMatch: CustomStringConvertible {
return tree return tree
} }
public func toString() -> String {
return description
}
public var description: String { public var description: String {
let info = succeeded() ? "succeeded" : "failed" let info = succeeded() ? "succeeded" : "failed"
return "Match \(info); found \(getLabels().size()) labels" return "Match \(info); found \(getLabels().size()) labels"

View File

@ -311,7 +311,7 @@ public class ParseTreePatternMatcher {
for chunk in chunks { for chunk in chunks {
if let tagChunk = chunk as? TagChunk { if let tagChunk = chunk as? TagChunk {
// add special rule token or conjure up new token from name // add special rule token or conjure up new token from name
let firstStr = String(tagChunk.getTag()[0]) let firstStr = String(tagChunk.getTag().first!)
if firstStr.lowercased() != firstStr { if firstStr.lowercased() != firstStr {
let ttype = parser.getTokenType(tagChunk.getTag()) let ttype = parser.getTokenType(tagChunk.getTag())
if ttype == CommonToken.INVALID_TYPE { if ttype == CommonToken.INVALID_TYPE {
@ -351,29 +351,34 @@ public class ParseTreePatternMatcher {
/// Split `<ID> = <e:expr> ;` into 4 chunks for tokenizing by _#tokenize_. /// Split `<ID> = <e:expr> ;` into 4 chunks for tokenizing by _#tokenize_.
/// ///
public func split(_ pattern: String) throws -> [Chunk] { public func split(_ pattern: String) throws -> [Chunk] {
var p = 0 var p = pattern.startIndex
let n = pattern.length let n = pattern.endIndex
var chunks = [Chunk]() var chunks = [Chunk]()
// find all start and stop indexes first, then collect // find all start and stop indexes first, then collect
var starts = [Int]() var starts = [Range<String.Index>]()
var stops = [Int]() var stops = [Range<String.Index>]()
let escapedStart = escape + start
let escapedStop = escape + stop
while p < n { while p < n {
if p == pattern.indexOf(escape + start, startIndex: p) { let slice = pattern[p...]
p += escape.length + start.length if slice.hasPrefix(escapedStart) {
p = pattern.index(p, offsetBy: escapedStart.count)
} }
else if p == pattern.indexOf(escape + stop, startIndex: p) { else if slice.hasPrefix(escapedStop) {
p += escape.length + stop.length p = pattern.index(p, offsetBy: escapedStop.count)
} }
else if p == pattern.indexOf(start, startIndex: p) { else if slice.hasPrefix(start) {
starts.append(p) let upperBound = pattern.index(p, offsetBy: start.count)
p += start.length starts.append(p ..< upperBound)
p = upperBound
} }
else if p == pattern.indexOf(stop, startIndex: p) { else if slice.hasPrefix(stop) {
stops.append(p) let upperBound = pattern.index(p, offsetBy: stop.count)
p += stop.length stops.append(p ..< upperBound)
p = upperBound
} }
else { else {
p += 1 p = pattern.index(after: p)
} }
} }
@ -387,46 +392,50 @@ public class ParseTreePatternMatcher {
let ntags = starts.count let ntags = starts.count
for i in 0..<ntags { for i in 0..<ntags {
if starts[i] >= stops[i] { if starts[i].lowerBound >= stops[i].lowerBound {
throw ANTLRError.illegalArgument(msg: "tag delimiters out of order in pattern: " + pattern) throw ANTLRError.illegalArgument(msg: "tag delimiters out of order in pattern: " + pattern)
} }
} }
// collect into chunks now // collect into chunks now
if ntags == 0 { if ntags == 0 {
let text = pattern[0 ..< n] let text = String(pattern[..<n])
chunks.append(TextChunk(text)) chunks.append(TextChunk(text))
} }
if ntags > 0 && starts[0] > 0 { if ntags > 0 && starts[0].lowerBound > pattern.startIndex {
// copy text up to first tag into chunks // copy text up to first tag into chunks
let text = pattern[0 ..< starts[0]] let text = pattern[pattern.startIndex ..< starts[0].lowerBound]
chunks.append(TextChunk(text)) chunks.append(TextChunk(String(text)))
} }
for i in 0 ..< ntags { for i in 0 ..< ntags {
// copy inside of <tag> // copy inside of <tag>
let tag = pattern[starts[i] + start.length ..< stops[i]] let tag = pattern[starts[i].upperBound ..< stops[i].lowerBound]
var ruleOrToken = tag let ruleOrToken: String
var label: String? let label: String?
let colon = tag.indexOf(":") let bits = tag.split(separator: ":", maxSplits: 1)
if colon >= 0 { if bits.count == 2 {
label = tag[0 ..< colon] label = String(bits[0])
ruleOrToken = tag[colon + 1 ..< tag.length] ruleOrToken = String(bits[1])
}
else {
label = nil
ruleOrToken = String(tag)
} }
chunks.append(try TagChunk(label, ruleOrToken)) chunks.append(try TagChunk(label, ruleOrToken))
if i + 1 < ntags { if i + 1 < ntags {
// copy from end of <tag> to start of next // copy from end of <tag> to start of next
let text = pattern[stops[i] + stop.length ..< starts[i + 1]] let text = pattern[stops[i].upperBound ..< starts[i + 1].lowerBound]
chunks.append(TextChunk(text)) chunks.append(TextChunk(String(text)))
} }
} }
if ntags > 0 { if ntags > 0 {
let afterLastTag = stops[ntags - 1] + stop.length let afterLastTag = stops[ntags - 1].upperBound
if afterLastTag < n { if afterLastTag < n {
// copy text from end of last tag to end // copy text from end of last tag to end
let text = pattern[afterLastTag ..< n] let text = pattern[afterLastTag ..< n]
chunks.append(TextChunk(text)) chunks.append(TextChunk(String(text)))
} }
} }
@ -435,7 +444,7 @@ public class ParseTreePatternMatcher {
let c = chunks[i] let c = chunks[i]
if let tc = c as? TextChunk { if let tc = c as? TextChunk {
let unescaped = tc.getText().replacingOccurrences(of: escape, with: "") let unescaped = tc.getText().replacingOccurrences(of: escape, with: "")
if unescaped.length < tc.getText().length { if unescaped.count < tc.getText().count {
chunks[i] = TextChunk(unescaped) chunks[i] = TextChunk(unescaped)
} }
} }

View File

@ -0,0 +1,26 @@
/// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
/// Use of this file is governed by the BSD 3-clause license that
/// can be found in the LICENSE.txt file in the project root.
import Foundation
import XCTest
import Antlr4
class RuntimeMetaDataTests: XCTestCase {
func testGetMajorMinorVersion() {
doGetMajorMinorVersionTest("", "")
doGetMajorMinorVersionTest("4", "4")
doGetMajorMinorVersionTest("4.", "4.")
doGetMajorMinorVersionTest("4.7", "4.7")
doGetMajorMinorVersionTest("4.7.1", "4.7")
doGetMajorMinorVersionTest("4-SNAPSHOT", "4")
doGetMajorMinorVersionTest("4.-SNAPSHOT", "4.")
doGetMajorMinorVersionTest("4.7-SNAPSHOT", "4.7")
doGetMajorMinorVersionTest("4.7.1-SNAPSHOT", "4.7")
}
}
private func doGetMajorMinorVersionTest(_ input: String, _ expected: String) {
XCTAssertEqual(RuntimeMetaData.getMajorMinorVersion(input), expected)
}

View File

@ -0,0 +1,31 @@
/// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
/// Use of this file is governed by the BSD 3-clause license that
/// can be found in the LICENSE.txt file in the project root.
import Foundation
import XCTest
@testable import Antlr4
class StringExtensionTests: XCTestCase {
func testLastIndex() {
doLastIndexTest("", "", nil)
doLastIndexTest("a", "", nil)
doLastIndexTest("a", "a", 0)
doLastIndexTest("aba", "a", 2)
doLastIndexTest("aba", "b", 1)
doLastIndexTest("abc", "d", nil)
}
}
private func doLastIndexTest(_ str: String, _ target: String, _ expectedOffset: Int?) {
let expectedIdx: String.Index?
if let expectedOffset = expectedOffset {
expectedIdx = str.index(str.startIndex, offsetBy: expectedOffset)
}
else {
expectedIdx = nil
}
XCTAssertEqual(str.lastIndex(of: target), expectedIdx)
}