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
7/// This is a “green tree” in the sense of Roslyn.
8public struct SyntaxTree: Codable, Sendable {
9 public let kind: SyntaxTreeKind
10 public let metadata: SyntaxTreeMetadata?
11 public let children: [Child]
12 public let utf16Length: Int
13
14 public enum Child: Codable, Sendable {
15 case token(Token, metadata: TokenMetadata?)
16 case tree(SyntaxTree)
17 }
18
19 public init(kind: SyntaxTreeKind, metadata: SyntaxTreeMetadata? = nil, children: [SyntaxTree.Child]) {
20 self.kind = kind
21 self.metadata = metadata
22 self.children = children
23 self.utf16Length = children.reduce(0) { length, child in
24 length + child.utf16Length
25 }
26 }
27}
28
29extension SyntaxTree {
30 /// A mutable version of ``SyntaxTree`` that does not keep track of textual length, for use when constructing trees.
31 public struct MutableTree {
32 public var kind: SyntaxTreeKind
33 public var metadata: SyntaxTreeMetadata?
34 public var children: [Child]
35
36 var tree: SyntaxTree {
37 SyntaxTree(kind: kind, metadata: metadata, children: children)
38 }
39 }
40}
41
42extension SyntaxTree {
43 public var text: String {
44 children.map(\.text).joined()
45 }
46}
47
48extension SyntaxTree.Child {
49 public var text: String {
50 switch self {
51 case let .token(tok, _): tok.text
52 case let .tree(tree): tree.text
53 }
54 }
55
56 public var tree: SyntaxTree? {
57 switch self {
58 case let .tree(tree): tree
59 default: nil
60 }
61 }
62
63 var token: (Token, TokenMetadata?)? {
64 switch self {
65 case let .token(token, metadata): (token, metadata)
66 default: nil
67 }
68 }
69
70 var utf16Length: Int {
71 switch self {
72 case let .token(token, _): token.utf16Length
73 case let .tree(tree): tree.utf16Length
74 }
75 }
76
77 var children: [Self] {
78 switch self {
79 case .token: []
80 case let .tree(tree): tree.children
81 }
82 }
83}
84
85extension SyntaxTree: CustomStringConvertible {
86 public var description: String {
87 prettyPrint()
88 }
89
90 /// Pretty-print the tree with indentation.
91 func prettyPrint(indent: String = "") -> String {
92 var result = "\(indent)\(kind)"
93 for child in children {
94 switch child {
95 case .token(let token, _):
96 result += "\n\(indent) \(token.kind): \(token.text.replacingOccurrences(of: "\n", with: "\\n"))"
97 case .tree(let subtree):
98 result += "\n" + subtree.prettyPrint(indent: indent + " ")
99 }
100 }
101 return result
102 }
103}