767
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
1 |
// A case of catastrophic backtracking in Swift
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
2 |
//---------------------------------------------
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
3 |
// example provided by Martin Mikusovic
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
4 |
//
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
5 |
// regex: (a*)*b
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
6 |
// strings: aa...a
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
7 |
//
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
8 |
// compile with
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
9 |
//
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
10 |
// swiftc catastrophic.swift
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
11 |
//
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
12 |
// run with for example
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
13 |
//
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
14 |
// time ./catastrophic 20
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
15 |
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
16 |
import Foundation
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
17 |
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
18 |
let args = CommandLine.arguments
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
19 |
if args.count >= 2, let count = Int(args[1]) {
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
20 |
let s = String(repeating: "a", count: count)
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
21 |
calculateTime {
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
22 |
let _ = s ~= "(a*)*b"
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
23 |
}
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
24 |
} else {
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
25 |
print("Please enter a valid number argument.")
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
26 |
}
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
27 |
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
28 |
func calculateTime(block: () -> ()) {
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
29 |
let start = DispatchTime.now()
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
30 |
block()
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
31 |
let end = DispatchTime.now()
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
32 |
let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
33 |
let timeInterval = Double(nanoTime) / 1_000_000_000
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
34 |
print("\(timeInterval) s")
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
35 |
}
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
36 |
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
37 |
extension String {
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
38 |
static func ~=(lhs: String, rhs: String) -> Bool {
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
39 |
guard let regex = try? NSRegularExpression(pattern: rhs) else { return false }
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
40 |
let range = NSRange(location: 0, length: lhs.utf16.count)
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
41 |
return regex.firstMatch(in: lhs, options: [], range: range) != nil
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
42 |
}
|
Christian Urban <christian.urban@kcl.ac.uk>
parents:
diff
changeset
|
43 |
}
|