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