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