1// SPDX-FileCopyrightText: 2025 The Project Pterodactyl Developers 2// 3// SPDX-License-Identifier: MPL-2.0 4 5import Foundation 6 7/// This is an abstraction of grammatical productions. 8public protocol Grammar: Sendable { 9 /// The kinds of tree that the production produces. 10 static var kinds: [SyntaxTreeKind] { get } 11 12 /// 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. 13 static func before(_ parser: inout Parser) -> Bool 14 15 /// Parse the grammatical production, assuming the precondition indicated by ``before(_:)``. This function should not be called outside this module (instead, use ``parse(_:)`` and ``tryParse(_:)``. 16 static func inside(_ parser: inout Parser) -> ParseResult 17} 18 19public struct ParseResult { 20 public var kind: SyntaxTreeKind 21 public var metadata: SyntaxTreeMetadata? = nil 22 23 public init(kind: SyntaxTreeKind, metadata: SyntaxTreeMetadata? = nil) { 24 self.kind = kind 25 self.metadata = metadata 26 } 27} 28 29 30extension Grammar { 31 public static func tryParse(_ parser: inout Parser) -> Bool { 32 guard !parser.isEndOfFile && before(&parser) else { return false } 33 parse(&parser) 34 return true 35 } 36 37 public static func parse(_ parser: inout Parser) { 38 let mark = parser.open() 39 let result = inside(&parser) 40 parser.close(mark: mark, kind: result.kind, metadata: result.metadata) 41 } 42}