at main 1.6 kB view raw
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 precondition(_ parser: inout Parser) -> Bool 14 15 /// 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:)``. 16 static func inside(_ parser: inout Parser, recovery: Set<TokenKind>) -> ParseResult 17} 18 19extension Grammar { 20 public static func tryParse(_ parser: inout Parser, recovery: Set<TokenKind>) -> Bool { 21 guard !parser.isEndOfFile && precondition(&parser) else { return false } 22 parse(&parser, recovery: recovery) 23 return true 24 } 25 26 public static func parse(_ parser: inout Parser, recovery: Set<TokenKind>) { 27 let mark = parser.builder.open() 28 let result = inside(&parser, recovery: recovery) 29 parser.builder.close(mark: mark, kind: result.kind, metadata: result.metadata) 30 } 31} 32 33public struct ParseResult { 34 public var kind: SyntaxTreeKind 35 public var metadata: SyntaxTreeMetadata? = nil 36 37 public init(kind: SyntaxTreeKind, metadata: SyntaxTreeMetadata? = nil) { 38 self.kind = kind 39 self.metadata = metadata 40 } 41} 42