1import Foundation 2 3public struct Tree<L: Language>: Sendable { 4 public let kind: L.TreeKind 5 public let metadata: L.TreeMetadata? 6 public let children: [Child<L>] 7 public let utf16Length: Int 8 9 public init(kind: L.TreeKind, metadata: L.TreeMetadata?, children: [Child<L>]) { 10 self.kind = kind 11 self.metadata = metadata 12 self.children = children 13 self.utf16Length = children.reduce(0) { length, child in 14 length + child.utf16Length 15 } 16 } 17} 18 19public enum Child<L: Language>: Sendable { 20 case token(Token<L.TokenKind>, metadata: L.TokenMetadata?) 21 case tree(Tree<L>) 22} 23 24extension Tree { 25 public var text: String { 26 children.map(\.text).joined() 27 } 28} 29 30extension Child { 31 var text: String { 32 switch self { 33 case let .token(tok, _): tok.text 34 case let .tree(tree): tree.text 35 } 36 } 37 38 var utf16Length: Int { 39 switch self { 40 case let .token(token, metadata): token.utf16Length 41 case let .tree(tree): tree.utf16Length 42 } 43 } 44 45 var children: [Self] { 46 switch self { 47 case .token: [] 48 case let .tree(tree): tree.children 49 } 50 } 51} 52 53extension Tree: CustomStringConvertible { 54 public var description: String { 55 prettyPrint() 56 } 57 58 /// Pretty-print the tree with indentation. 59 func prettyPrint(indent: String = "") -> String { 60 var result = "\(indent)\(kind)" 61 for child in children { 62 switch child { 63 case .token(let token, _): 64 result += "\n\(indent) \(token.kind): \(token.text.replacingOccurrences(of: "\n", with: "\\n"))" 65 case .tree(let subtree): 66 result += "\n" + subtree.prettyPrint(indent: indent + " ") 67 } 68 } 69 return result 70 } 71}