1//SPDX-FileCopyrightText:2025TheProjectPterodactylDevelopers 2//SPDX-FileCopyrightText:2026TheProjectPterodactylDevelopers 3// 4//SPDX-License-Identifier:MPL-2.0 5 6publicstructSyntaxTreeBuilder{ 7privateenumEvent:Equatable{ 8caseopen 9caseclose(kind:SyntaxTreeKind,metadata:SyntaxTreeMetadata?)10caseadvance(token:Token,metadata:TokenMetadata?)11}1213privatevarevents:[Event]=[]1415publicinit(){}1617publicstructCheckpoint{18fileprivateletposition:Int19}2021publicvarcheckpoint:Checkpoint{22Checkpoint(position:events.count)23}2425publicmutatingfuncopenAtCheckpoint(_checkpoint:Checkpoint){26events.insert(.open,at:checkpoint.position)27}2829publicmutatingfuncopen(){30events.append(.open)31}3233publicmutatingfuncclose(kind:SyntaxTreeKind,metadata:SyntaxTreeMetadata?=nil){34events.append(.close(kind:kind,metadata:metadata))35}3637publicmutatingfuncadvance(token:Token,metadata:TokenMetadata?){38events.append(.advance(token:token,metadata:metadata))39}4041publicvartree:SyntaxTree{42varstack:[SyntaxTree.MutableTree]=[]4344foreventinevents{45switchevent{46case.open:47stack.append(SyntaxTree.MutableTree(kind:.error,metadata:nil,children:[]))4849case.close(letkind,letmetadata):50guardvarnode=stack.popLast()else{fatalError("More close events than open events")}51node.kind=kind52node.metadata=metadata53guardletparentIndex=stack.indices.lastelse{returnnode.tree}54stack[parentIndex].children.append(.tree(node.tree))5556case.advance(lettoken,letmetadata):57guardletparentIndex=stack.indices.lastelse{58fatalError("Attempted to insert token at root of parse tree")59}60stack[parentIndex]61.children62.append(.token(token,metadata:metadata))63}64}6566if!stack.isEmpty{67fatalError("More open events than close events")68}6970returnSyntaxTree(kind:.error,children:[])71}72}