Skip to content

Instantly share code, notes, and snippets.

@ankitspd
Last active February 3, 2018 23:02
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ankitspd/c3553333426cc2680f5e to your computer and use it in GitHub Desktop.
Save ankitspd/c3553333426cc2680f5e to your computer and use it in GitHub Desktop.
import Foundation
public func getASTString() -> String {
// get the file path for the file "test.json" in the playground bundle
// let filePath = NSBundle.mainBundle().pathForResource("FirstTtest", ofType: "ast")
// get the contentData
let contentData = NSFileManager.defaultManager().contentsAtPath("a.txt")
// get the string
let content = NSString(data: contentData!, encoding: NSUTF8StringEncoding) as? String
return content!
}
extension String {
/**
Remove trailing newline characters. By default chomp removes
all trailing \n (UNIX) or all trailing \r\n (Windows) (it will
not remove mixed occurrences of both separators.
*/
public func chomp(separator: String? = nil) -> String {
func scrub(separator: String) -> String {
var E = endIndex
while self[startIndex..<E].hasSuffix(separator) && E > startIndex {
E = E.predecessor()
}
return self[startIndex..<E]
}
if let separator = separator {
return scrub(separator)
} else if hasSuffix("\r\n") {
return scrub("\r\n")
} else if hasSuffix("\n") {
return scrub("\n")
} else {
return self
}
}
/**
Trims whitespace from both ends of a string, if the resulting
string is empty, returns `nil`.String
Useful because you can short-circuit off the result and thus
handle “falsy” strings in an elegant way:
return userInput.chuzzle() ?? "default value"
*/
public func chuzzle() -> String? {
var cc = characters
loop: while true {
switch cc.first {
case .None:
return nil
case .Some("\n"), .Some("\r"), .Some(" "), .Some("\t"), .Some("\r\n"):
cc = cc.dropFirst()
default:
break loop
}
}
loop: while true {
switch cc.last {
case .None:
return nil
case .Some("\n"), .Some("\r"), .Some(" "), .Some("\t"), .Some("\r\n"):
cc = cc.dropLast()
default:
break loop
}
}
return String(cc)
}
}
let astString = getASTString()
enum Type: String {
case Class = "class_decl"
case Fn = "func_decl"
case Unknown = ""
}
class Node: CustomStringConvertible {
var contents: String = ""
var nodes: [Node] = []
init() {
}
var description: String {
if nodes.count > 0 {
return "\(contents) \(nodes)"
}
return "\(contents)"
}
var type: Type {
if contents.hasPrefix(Type.Class.rawValue) {
return .Class
}
if contents.hasPrefix(Type.Fn.rawValue) {
return .Fn
}
return .Unknown
}
var name: String {
switch type {
case .Class: fallthrough
case .Fn:
var str = ""
var quoteBegan: Bool = false
for char in self.contents.characters {
if char == "\"" {
if quoteBegan { return str[str.startIndex.successor()..<str.endIndex] }
quoteBegan = true
}
if quoteBegan { str += "\(char)" }
}
return str
default:
return ""
}
}
}
var stack = Array<Node>()
var data = ""
var quoteStarted: Bool = false
var sources: [Node] = []
for var index in astString.characters.startIndex..<astString.characters.endIndex {
let char = astString.characters[index]
func peekNext() -> String {
return "\(astString.characters[index.successor()])"
}
if char == "(" && !quoteStarted {
let node = Node()
if data.characters.count > 0, let lastNode = stack.last, let chuzzed = data.chuzzle() {
lastNode.contents = chuzzed
if lastNode.contents == "source_file" { sources += [lastNode] }
}
stack.append(node)
data = ""
} else if char == ")" && !quoteStarted {
if case let poppedNode = stack.removeLast() where stack.count > 0 {
if data.characters.count > 0, let chuzzed = data.chuzzle() {
poppedNode.contents = chuzzed
}
stack.last!.nodes += [poppedNode]
data = ""
}
} else {
var charToAppend = char
data = data + String(char)
if char == "\"" || char == "'" { quoteStarted = !quoteStarted }
}
}
// print(sources)
print(sources.count)
////
for source in sources {
for node in source.nodes where node.type == .Class && node.name.characters.count > 3 {
// guard let _ = node.name.chuzzle() else { continue }
print("----------------")
print(node.name)
print("----------------")
for classNode in node.nodes where classNode.type == .Fn && classNode.name.characters.count > 3 {
print(classNode.name)
}
}
}
@prabodhprakash
Copy link

prabodhprakash commented Nov 26, 2016

Can you please update this for latest Swift version or share an executable that works?

@wwe-johndpope
Copy link

@prabodhprakash

There's a way to spit out swift gramma file if you dig around here
https://github.com/johndpope/ANTLR-Swift-Target

Run time walker here
https://github.com/johndpope/Antlr-Swift-Runtime/tree/master/Test/Test

If you run into issue log to antlr repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment