// 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 public struct CSTVisitorDriver { public init() {} public func visit( _ elem: any CST.Categories.LanguageElement, visitor: any CSTVisitor, context: T ) -> Result { return switch elem { case let elem as CST.Categories.Expression: visit(expression: elem, visitor: visitor, context: context) case let elem as CST.Categories.Statement: visit(statement: elem, visitor: visitor, context: context) case let elem as CST.Categories.State: visit(state: elem, visitor: visitor, context: context) case let elem as CST.Categories.Declaration: visit(declaration: elem, visitor: visitor, context: context) default: .Error(Error(withMessage: "AST Language Element (\(elem)) Is Not Visitable")) } } func visit( declaration: any CST.Categories.Declaration, visitor: any CSTVisitor, context: T ) -> Result { return switch declaration { case let elem as CST.Control: visitor.visit(node: elem, driver: self, context: context) case let elem as CST.ExternDeclaration: visitor.visit(node: elem, driver: self, context: context) case let elem as CST.FunctionDeclaration: visitor.visit(node: elem, driver: self, context: context) case let elem as CST.StructDeclaration: visitor.visit(node: elem, driver: self, context: context) case let elem as CST.Parser: visitor.visit(node: elem, driver: self, context: context) default: .Error(Error(withMessage: "AST Declaration Element (\(declaration)) Is Not Visitable")) } } func visit( expression: any CST.Categories.Expression, visitor: any CSTVisitor, context: T ) -> Result { return switch expression { case let s as CST.Identifier: visitor.visit(node: s, driver: self, context: context) case let s as CST.KeysetExpression: visitor.visit(node: s, driver: self, context: context) case let s as CST.SelectCaseExpression: visitor.visit(node: s, driver: self, context: context) case let e as CST.SelectExpression: visitor.visit(node: e, driver: self, context: context) case let e as CST.BinaryOperatorExpression: visitor.visit(node: e, driver: self, context: context) case let e as CST.Literal: visitor.visit(node: e, driver: self, context: context) default: .Error(Error(withMessage: "AST Expression Element (\(expression)) Is Not Visitable")) } } func visit( state: any CST.Categories.State, visitor: any CSTVisitor, context: T ) -> Result { return switch state { case let s as CST.ParserStateDirectTransition: visitor.visit(node: s, driver: self, context: context) case let s as CST.ParserStateNoTransition: visitor.visit(node: s, driver: self, context: context) case let s as CST.ParserStateSelectTransition: visitor.visit(node: s, driver: self, context: context) default: .Error(Error(withMessage: "AST State Element (\(state)) Is Not Visitable")) } } func visit( statement: any CST.Categories.Statement, visitor: any CSTVisitor, context: T ) -> Result { return switch statement { case let s as CST.Statements: visitor.visit(node: s, driver: self, context: context) case let s as CST.ExpressionStatement: visitor.visit(node: s, driver: self, context: context) case let s as CST.VariableDeclarationStatement: visitor.visit(node: s, driver: self, context: context) case let s as CST.Parser: visitor.visit(node: s, driver: self, context: context) default: .Error(Error(withMessage: "AST Statement Element (\(statement)) Is Not Visitable")) } } public func start( program: CST.Program, visitor: any CSTVisitor, context: T ) -> Result { var context = context switch visit(statement: program.statements, visitor: visitor, context: context) { case .Ok(let c): context = c case .Error(let e): return .Error(e) } return .Ok(context) } }