this repo has no description
www.jonmsterling.com/01HC/
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? = nil, 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 /// A mutable version of ``SyntaxTree`` that does not keep track of textual length, for use when constructing trees.
30 public struct Builder {
31 public var kind: SyntaxTreeKind
32 public var metadata: SyntaxTreeMetadata?
33 public var children: [Child]
34
35 var tree: SyntaxTree {
36 SyntaxTree(kind: kind, metadata: metadata, children: children)
37 }
38 }
39}
40
41extension SyntaxTree {
42 public var text: String {
43 children.map(\.text).joined()
44 }
45}
46
47extension SyntaxTree.Child {
48 public var text: String {
49 switch self {
50 case let .token(tok, _): tok.text
51 case let .tree(tree): tree.text
52 }
53 }
54
55 public var tree: SyntaxTree? {
56 switch self {
57 case let .tree(tree): tree
58 default: nil
59 }
60 }
61
62 var token: (Token, TokenMetadata?)? {
63 switch self {
64 case let .token(token, metadata): (token, metadata)
65 default: nil
66 }
67 }
68
69 var utf16Length: Int {
70 switch self {
71 case let .token(token, _): token.utf16Length
72 case let .tree(tree): tree.utf16Length
73 }
74 }
75
76 var children: [Self] {
77 switch self {
78 case .token: []
79 case let .tree(tree): tree.children
80 }
81 }
82}
83
84extension SyntaxTree: CustomStringConvertible {
85 public var description: String {
86 prettyPrint()
87 }
88
89 /// Pretty-print the tree with indentation.
90 func prettyPrint(indent: String = "") -> String {
91 var result = "\(indent)\(kind)"
92 for child in children {
93 switch child {
94 case .token(let token, _):
95 result += "\n\(indent) \(token.kind): \(token.text.replacingOccurrences(of: "\n", with: "\\n"))"
96 case .tree(let subtree):
97 result += "\n" + subtree.prettyPrint(indent: indent + " ")
98 }
99 }
100 return result
101 }
102}