// 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 extension P4Value: CST.Categories.Expression {} public struct CST { public struct Categories { public protocol Expression {} public protocol Statement {} public protocol State {} public protocol Declaration: Categories.Statement {} } struct Expression {} public struct Statements { public let statements: [Categories.Statement] public init(_ s: [Categories.Statement]) { self.statements = s } } public struct VariableDeclarationStatement: Categories.Statement { public var initializer: Categories.Expression? public var identifier: CST.Identifier public var tipe: CST.Tipe public init( identifier: Identifier, withType tipe: CST.Tipe, withInitializer initializer: Categories.Expression? ) { self.identifier = identifier self.initializer = initializer self.tipe = tipe } } public struct ConditionalStatement: Categories.Statement { public var condition: Categories.Expression public var thenn: Categories.Statement public var elss: Categories.Statement? public init(condition: Categories.Expression, withThen thenn: Categories.Statement) { self.condition = condition self.thenn = thenn self.elss = .none } public init( condition: Categories.Expression, withThen thenn: Categories.Statement, andElse elss: Categories.Statement ) { self.condition = condition self.thenn = thenn self.elss = elss } } public struct BlockStatement: Categories.Statement { public var statements: Statements public init(_ statements: Statements) { self.statements = statements } } public struct ReturnStatement: Categories.Statement { public let value: Categories.Expression public init(_ value: Categories.Expression) { self.value = value } } public struct ApplyStatement: Categories.Statement { public let body: CST.BlockStatement? public init() { self.body = .none } public init(_ body: CST.BlockStatement) { self.body = body } } public struct Action: CustomStringConvertible { public var description: String { return "Action: " + "\(self.name) with parameters \(self.params) and body \(String(describing: self.body))" } public var body: CST.BlockStatement? public var params: CST.ParameterList public var name: CST.Identifier public init( named name: CST.Identifier = CST.Identifier(Common.Identifier(name: "")), withParameters parameters: ParameterList = ParameterList([]), withBody body: CST.BlockStatement? = .none ) { self.name = name self.params = parameters self.body = body } } public struct Actions: CustomStringConvertible { public let actions: [CST.Action] public init(withActions actions: [CST.Action]) { self.actions = actions } public var description: String { return "Actions: " + actions.map { action in return "\(action)" }.joined(separator: ";") } } public enum TableKeyMatchType { case Exact } public struct TableKeyEntry: CustomStringConvertible { public let key: CST.KeysetExpression public let match_type: CST.TableKeyMatchType public init(_ key: CST.KeysetExpression, _ match: CST.TableKeyMatchType) { self.key = key self.match_type = match } public var description: String { return "Table Key Entry: " + "\(self.key): \(self.match_type)" } } public struct TableKeys: CustomStringConvertible { public let keys: [CST.TableKeyEntry] public init(withEntries entries: [CST.TableKeyEntry]) { self.keys = entries } public init() { self.keys = [] } public var description: String { return "Table Keys: " + self.keys.map { key in return "\(key)" }.joined(separator: ";") } } public struct TableActionsProperty: CustomStringConvertible { public let actions: [CST.Identifier] public init(_ actions: [CST.Identifier] = []) { self.actions = actions } public var description: String { return "Table Actions: " + self.actions.map { action in return "\(action)" }.joined(separator: ";") } } public struct TablePropertyList: CustomStringConvertible { public let actions: CST.TableActionsProperty public let keys: CST.TableKeys public init(withActions actions: CST.TableActionsProperty, withKeys keys: CST.TableKeys) { self.actions = actions self.keys = keys } public var description: String { return "Table Property List: \(self.actions) \(self.keys)" } } public struct Table: CustomStringConvertible { public let properties: CST.TablePropertyList let name: CST.Identifier public let entries: [(P4Value, CST.Identifier)] public init( withName name: CST.Identifier, withPropertyList property_list: CST.TablePropertyList, withEntries entries: [(P4Value, CST.Identifier)] = [] ) { self.name = name self.properties = property_list self.entries = entries } public var description: String { return "Table named: \(self.name) \(self.properties)" } /// When the control is evaluated, the value of the x in the table is /// compared to the entries and the match is assocated with an action /// that is invoked when the match occurs! public func update(addEntry entry: (P4Value, CST.Identifier)) -> Table { return Table( withName: self.name, withPropertyList: self.properties, withEntries: self.entries + [entry]) } } public struct Declaration {} public struct Control: CustomStringConvertible, Categories.Declaration { public var description: String { return "Control named \(self._name) \(self.parameters) \(self.actions) \(self.table)" } public let actions: CST.Actions public let table: CST.Table let _parameters: CST.ParameterList let _name: CST.Identifier let apply: CST.ApplyStatement public var parameters: CST.ParameterList { _parameters } public var name: CST.Identifier { _name } public init( named: CST.Identifier, withParameters parameters: CST.ParameterList, withTable table: CST.Table, withActions actions: CST.Actions, withApply apply: CST.ApplyStatement ) { self._name = named self._parameters = parameters self.actions = actions self.table = table self.apply = apply } public func updateTable(addEntry entry: (P4Value, CST.Identifier)) -> Control { let table = self.table.update(addEntry: entry) return Control( named: self.name, withParameters: self.parameters, withTable: table, withActions: self.actions, withApply: self.apply) } public func def() -> P4DataValue? { return .none } } public struct ExternDeclaration: Categories.Declaration { public let declaration: CST.Categories.Declaration public init(_ declaration: CST.Categories.Declaration) { self.declaration = declaration } } public struct FunctionDeclaration: Categories.Declaration { public var description: String { return "Function named \(self.name) that returns \(self.tipe) with parameters \(self.params)" } public var body: CST.BlockStatement? public var params: CST.ParameterList public var name: CST.Identifier public var tipe: CST.Tipe public init( named name: CST.Identifier, ofType type: CST.Tipe, withParameters parameters: CST.ParameterList, withBody body: CST.BlockStatement? ) { self.name = name self.tipe = type self.params = parameters self.body = body } } public struct StructDeclaration: Categories.Declaration { public let fields: [CST.VariableDeclarationStatement] public let identifier: CST.Identifier public init(_ id: CST.Identifier, _ fields: [CST.VariableDeclarationStatement]) { self.identifier = id self.fields = fields } } public struct Instantiation: Categories.Statement { public let name: CST.Identifier public var tipe: CST.Identifier public let arguments: CST.ArgumentList public init( named name: CST.Identifier, withType tipe: CST.Identifier, withArguments arguments: CST.ArgumentList ) { self.name = name self.arguments = arguments self.tipe = tipe } } public struct ExpressionStatement: Categories.Statement { public let expression: Categories.Expression public init(_ expr: Categories.Expression) { self.expression = expr } } public struct Identifier: Categories.Expression { public let id: Common.Identifier public init(_ id: Common.Identifier) { self.id = id } } public struct Literal: Categories.Expression { public let literal: P4Value public init(_ literal: P4Value) { self.literal = literal } } public enum KeysetExpression: Categories.Expression { case Default case Value(Categories.Expression) } public struct SelectCaseExpression: Categories.Expression { public let key: CST.KeysetExpression public let next_state_identifier: CST.Identifier public init(withKey key: CST.KeysetExpression, withNextState next_state_id: CST.Identifier) { self.key = key self.next_state_identifier = next_state_id } } public struct SelectExpression: Categories.Expression { public let selector: Categories.Expression public let case_expressions: [CST.SelectCaseExpression] public init( withSelector selector: Categories.Expression, withSelectCaseExpressions sces: [CST.SelectCaseExpression] ) { self.selector = selector self.case_expressions = sces } public func append_checked_sce(sce: CST.SelectCaseExpression) -> CST.SelectExpression { var new_cses = self.case_expressions new_cses.append(sce) return SelectExpression( withSelector: self.selector, withSelectCaseExpressions: new_cses) } } public enum BinaryOperatorExpressionType { case Add case Subtract case Multiply case Divide case Lt case Lte case Gt case Gte case Eq case And case Or } public struct BinaryOperatorExpression: Categories.Expression { public let left: Categories.Expression public let right: Categories.Expression public let type: BinaryOperatorExpressionType public init( withType tipe: BinaryOperatorExpressionType, withLhs lhs: Categories.Expression, withRhs rhs: Categories.Expression ) { self.type = tipe self.left = lhs self.right = rhs } } public struct ArrayAccessExpression: Categories.Expression { public let indexor: Categories.Expression public let name: Categories.Expression public init( withName name: Categories.Expression, withIndexor indexor: Categories.Expression ) { self.name = name self.indexor = indexor } } public struct FieldAccessExpression: Categories.Expression { public let field: Identifier public let strct: Categories.Expression public init(withStruct strct: Categories.Expression, withField field: Identifier) { self.strct = strct self.field = field } } public struct FunctionCall: Categories.Expression { public let callee: Identifier public let arguments: ArgumentList public init(_ callee: Identifier, withArguments arguments: ArgumentList) { self.callee = callee self.arguments = arguments } } public struct LocalElements {} public struct LocalElement {} public struct ParserAssignmentStatement: Categories.Statement { public let lvalue: Categories.Expression public let value: Categories.Expression public init( withLValue lvalue: Categories.Expression, withValue value: Categories.Expression ) { self.lvalue = lvalue self.value = value } } /// A P4 Parser State public class ParserState { let name: Identifier public let statements: CST.Statements? public var description: String { return "Parser State named \(self.name)" } public func getName() -> Identifier { return self.name } public func getStatements() -> CST.Statements? { return self.statements } /// Construct a ParserState public init(_ name: Identifier, _ statements: CST.Statements? = .none) { self.name = name self.statements = statements } } /// TransitionStatement /// /// Only defined to define Compilable extension. public struct TransitionStatement {} public class ParserStateDirectTransition: ParserState, Categories.State { public let next_state_identifier: Identifier? public init( name: Identifier, withNextStateIdentifier next_state_id: Identifier, withStatements stmts: CST.Statements? = .none ) { self.next_state_identifier = next_state_id super.init(name, stmts) } } public class ParserStateNoTransition: ParserState, Categories.State { /// Construct a ParserState public init( name: Identifier, withStatements stmts: CST.Statements? = .none ) { super.init(name, stmts) } } public class ParserStateSelectTransition: ParserState, Categories.State { public let te: SelectExpression public init( name: Identifier, withTransitionExpression te: SelectExpression, withStatements stmts: CST.Statements? = .none ) { self.te = te super.init(name, stmts) } } public struct ParserStates { public var states: [Categories.State] = Array() public func count() -> Int { return states.count } public init(_ states: [Categories.State] = Array()) { self.states = states } public func append(state: Categories.State) -> ParserStates { var new_states = self.states new_states.append(state) return ParserStates(new_states) } } /// A P4 Parser /// /// Note: A Parser is a type public struct Parser: Categories.Declaration { public var states: ParserStates public var name: Identifier public var parameters: ParameterList public init(withName name: Identifier) { self.states = ParserStates() self.parameters = ParameterList() self.name = name } public init(withName name: Identifier, withParameters parameters: ParameterList) { self.states = ParserStates() self.parameters = parameters self.name = name } public var description: String { return "Parser \(self.name) with parameters: \(parameters) and states: \(self.states)" } } public struct Types {} public struct Tipe { public let tipe: P4QualifiedType public init(_ tipe: P4QualifiedType) { self.tipe = tipe } } public struct Parameter: CustomStringConvertible { public var name: CST.Identifier public var type: CST.Tipe public init( identifier: Identifier, withType type: CST.Tipe ) { self.name = identifier self.type = type } public var description: String { return "Parameter: \(self.name) with type \(self.type)" } } public struct ParameterList: CustomStringConvertible { public var parameters: [CST.Parameter] public init() { self.parameters = Array() } public init(_ parameters: [CST.Parameter]) { self.parameters = parameters } public func addParameter(_ parameter: CST.Parameter) -> CST.ParameterList { return CST.ParameterList(self.parameters + [parameter]) } public var description: String { let parameters = self.parameters.map { parameter in parameter.description }.joined(separator: ";") return "Parameter list: \(parameters)" } } public struct ArgumentList { public let arguments: [CST.Argument] public init(_ arguments: [CST.Argument] = []) { self.arguments = arguments } public func addArgument(_ argument: CST.Argument) -> CST.ArgumentList { return ArgumentList(self.arguments + [argument]) } } public struct Argument { public let index: Int public let argument: Categories.Expression public init(_ argument: Categories.Expression, atIndex index: Int) { self.argument = argument self.index = index } } public struct Program { public var statements: Statements public init(_ stmts: Statements = Statements([])) { self.statements = stmts } } public struct Statement {} } public struct CSTCompilerContext { public let lexical_context_name: CST.Identifier? public let lexical_context_statements: CST.Statements? public let extern_context: Bool public init( _ name: CST.Identifier? = .none, _ stmts: CST.Statements? = .none, _ extern: Bool = false ) { self.lexical_context_name = name self.lexical_context_statements = stmts self.extern_context = extern } public func update(withContextName cn: CST.Identifier?) -> CSTCompilerContext { return CSTCompilerContext(cn, self.lexical_context_statements, self.extern_context) } public func update(withContextStatements stmts: CST.Statements?) -> CSTCompilerContext { return CSTCompilerContext(self.lexical_context_name, stmts, self.extern_context) } public func update(withExtern extern: Bool) -> CSTCompilerContext { return CSTCompilerContext(self.lexical_context_name, self.lexical_context_statements, extern) } }