this repo has no description www.jonmsterling.com/01HC/
dependent-types proof-assistant swift
at pattern-unification 96 lines 2.5 kB view raw
1// SPDX-FileCopyrightText: 2025 The Project Pterodactyl Developers 2// SPDX-FileCopyrightText: 2026 The Project Pterodactyl Developers 3// 4// SPDX-License-Identifier: MPL-2.0 5 6public class SyntaxTreeBuilder { 7 private enum Event: Equatable { 8 case open 9 case close(kind: SyntaxTreeKind, metadata: SyntaxTreeMetadata?, cancelled: Bool) 10 case advance(token: Token, metadata: TokenMetadata?) 11 } 12 13 private var events: [Event] = [] 14 15 public init() {} 16 17 public struct SubtreeHandle: ~Copyable { 18 let parent: SyntaxTreeBuilder 19 var kind: SyntaxTreeKind 20 var metadata: SyntaxTreeMetadata? 21 private var closed = false 22 var cancelled = false 23 24 init(parent: SyntaxTreeBuilder, kind: SyntaxTreeKind? = nil, metadata: SyntaxTreeMetadata? = nil) { 25 self.parent = parent 26 self.kind = kind ?? .error 27 self.metadata = metadata 28 29 parent.events.append(.open) 30 } 31 32 mutating func cancel() { 33 cancelled = true 34 } 35 36 mutating func close() { 37 precondition(!closed) 38 parent.events.append(.close(kind: kind, metadata: metadata, cancelled: cancelled)) 39 closed = true 40 } 41 42 deinit { 43 precondition(closed) 44 } 45 } 46 47 public func open(kind: SyntaxTreeKind? = nil, metadata: SyntaxTreeMetadata? = nil) -> SubtreeHandle { 48 SubtreeHandle(parent: self, kind: kind, metadata: metadata) 49 } 50 51 public func advance(token: Token, metadata: TokenMetadata?) { 52 events.append(.advance(token: token, metadata: metadata)) 53 } 54 55 public var tree: SyntaxTree { 56 var stack: [SyntaxTree.MutableTree] = [] 57 58 for event in events { 59 switch event { 60 case .open: 61 stack.append(SyntaxTree.MutableTree(kind: .error, metadata: nil, children: [])) 62 63 case .close(let kind, let metadata, let cancelled): 64 guard var node = stack.popLast() else { fatalError("Unbalanced tree") } 65 node.kind = kind 66 node.metadata = metadata 67 guard let parentIndex = stack.indices.last else { return node.tree } 68 if cancelled { 69 stack[parentIndex].children.append(contentsOf: node.children) 70 } else { 71 stack[parentIndex].children.append(.tree(node.tree)) 72 } 73 74 case .advance(let token, let metadata): 75 guard let parentIndex = stack.indices.last else { 76 fatalError("Attempted to insert token at root of parse tree") 77 } 78 stack[parentIndex] 79 .children 80 .append(.token(token, metadata: metadata)) 81 } 82 } 83 84 fatalError("Unbalanced syntax tree") 85 } 86} 87 88 89extension Array { 90 fileprivate mutating func modifyLast(_ modifier: (inout Element) -> Void) { 91 if var last = popLast() { 92 modifier(&last) 93 append(last) 94 } 95 } 96}