// p4rse, Copyright 2026, Will Hawkins // // This file is part of p4rse. // // This file is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . import Common import SwiftTreeSitter import TreeSitterExtensions import TreeSitterP4 extension CST.LocalElements: Parsable { public typealias C = CST.Statement public static func Parse( node: Node, withContext context: CSTCompilerContext ) -> Result { let localElementsParsers: [String: ParsableStatement.Type] = [ "variableDeclaration": CST.VariableDeclarationStatement.self ] guard let parser = localElementsParsers[node.nodeType ?? ""] else { return Result.Error( ErrorWithLocation( sourceLocation: node.toSourceLocation(), withError: "Unparseable statement type (\(node.nodeType ?? "Unknown Statement Type"))")) } switch parser.ParseStatement(node: node, withContext: context) { case Result.Ok(let parsed): return Result.Ok(parsed) case Result.Error(let e): return Result.Error(Error(withMessage: "Failed to parse local element: \(e)")) } } } extension CST.ParserState: Parsable { public typealias C = CST.AnState public static func Parse( node: Node, withContext context: CSTCompilerContext ) -> Result { var walker = Walker(node: node) var current_node: Node? = .none guard let node_type = node.nodeType, node_type == "parserState" else { return Result.Error( ErrorWithLocation( sourceLocation: node.toSourceLocation(), withError: "Did not find a parser state declaration")) } #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( ErrorWithLocation( sourceLocation: node.toSourceLocation(), withError: "Missing elements in parser state declaration"))) if current_node!.nodeType == "annotations" { return Result.Error( ErrorWithLocation( sourceLocation: current_node!.toSourceLocation(), withError: "Annotations in parser state are not yet handled.")) // Would increment here. } // Skip the keyword state walker.next() #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( ErrorWithLocation( sourceLocation: node.toSourceLocation(), withError: "Missing elements in parser state declaration"))) let maybe_state_identifier = CST.Identifier.ParseExpression( node: current_node!, withContext: context) guard case Result.Ok(let state_identifier) = maybe_state_identifier else { return Result.Error(maybe_state_identifier.error()!) } walker.next() // Skip the '{' walker.next() #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( ErrorWithLocation( sourceLocation: node.toSourceLocation(), withError: "Missing body of state declaration") )) var errors: (any Errorable)? = .none var parsed_s: CST.Statements? = .none if current_node!.nodeType == "parserStatements" { switch CST.Statements.Parse( node: current_node!, withContext: context) { case .Ok(let state_statements): parsed_s = state_statements case .Error(let error): errors = if let errors = errors { errors.append(error: error) } else { error } } walker.next() } if let errors = errors { return .Error(errors) } #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( ErrorWithLocation( sourceLocation: node.toSourceLocation(), withError: "Missing transition statement of state declaration"))) let updated_context = context.update(withContextName: (state_identifier as! CST.Identifier)) .update(withContextStatements: parsed_s) return CST.TransitionStatement.Parse(node: current_node!, withContext: updated_context) } }