// SPDX-FileCopyrightText: 2025 The Project Pterodactyl Developers // // SPDX-License-Identifier: MPL-2.0 import Foundation /// This is an abstraction of grammatical productions. public protocol Grammar: Sendable { /// The kinds of tree that the production produces. static var kinds: [SyntaxTreeKind] { get } /// Indicates whether the current parser state is consistent with the grammatical production starting here. When a given grammatical element is optional, this can be used to avoid backtracking. This is a *precondition* for parsing. static func precondition(_ parser: inout Parser) -> Bool /// Parse the grammatical production, assuming the precondition indicated by ``precondition(_:)``. This function should not be called outside this module (instead, use ``parse(_:recovery:)`` and ``tryParse(_:recovery:)``. static func inside(_ parser: inout Parser, recovery: Set) -> ParseResult } extension Grammar { public static func tryParse(_ parser: inout Parser, recovery: Set) -> Bool { guard !parser.isEndOfFile && precondition(&parser) else { return false } parse(&parser, recovery: recovery) return true } public static func parse(_ parser: inout Parser, recovery: Set) { let mark = parser.builder.open() let result = inside(&parser, recovery: recovery) parser.builder.close(mark: mark, kind: result.kind, metadata: result.metadata) } } public struct ParseResult { public var kind: SyntaxTreeKind public var metadata: SyntaxTreeMetadata? = nil public init(kind: SyntaxTreeKind, metadata: SyntaxTreeMetadata? = nil) { self.kind = kind self.metadata = metadata } }