diff --git a/Sources/Common/Scope.swift b/Sources/Common/Scope.swift
index 7a7d290..ac0e2df 100644
--- a/Sources/Common/Scope.swift
+++ b/Sources/Common/Scope.swift
@@ -15,7 +15,13 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-public struct Scope: CustomStringConvertible {
+public struct Scope: CustomStringConvertible, Sequence {
+ public typealias Element = T
+ public typealias Iterator = Dictionary.Values.Iterator
+ public func makeIterator() -> Iterator {
+ self.symbols.values.makeIterator()
+ }
+
var symbols: [Identifier: T] = Dictionary()
public init() {}
@@ -45,7 +51,7 @@ public struct Scope: CustomStringConvertible {
}
}
-public struct Scopes: CustomStringConvertible {
+public struct Scopes: CustomStringConvertible, Sequence {
var scopes: [Scope] = Array()
public init() {}
@@ -117,6 +123,12 @@ public struct Scopes: CustomStringConvertible {
return .Error(Error(withMessage: "Cannot find \(identifier) in lexical scope."))
}
+ public typealias Element = T
+ public typealias Iterator = Dictionary.Values.Iterator
+ public func makeIterator() -> Iterator {
+ scopes.last?.makeIterator() ?? Scope().makeIterator()
+ }
+
public var count: Int {
scopes.count
}
diff --git a/Sources/P4Compiler/Parser.swift b/Sources/P4Compiler/Parser.swift
index 2617ec8..9c55be7 100644
--- a/Sources/P4Compiler/Parser.swift
+++ b/Sources/P4Compiler/Parser.swift
@@ -144,8 +144,8 @@ public struct Parser {
public struct TransitionStatement {
static func Compile(
- node: Node, inTree tree: MutableTree, withScope scopes: LexicalScopes
- ) -> Result<(ParserTransitionStatement, LexicalScopes)> {
+ node: Node, inTree tree: MutableTree, forState state_identifier: Common.Identifier, withStatements stmts: [EvaluatableStatement], withScope scopes: LexicalScopes
+ ) -> Result<(ParserState, LexicalScopes)> {
#RequireNodeType(
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
@@ -171,7 +171,7 @@ public struct Parser {
node: next_node, inTree: tree, withScopes: scopes)
if case .Ok(let next_state) = maybe_parsed_next_state {
return .Ok(
- (ParserTransitionStatement(withNextState: next_state), scopes))
+ (ParserStateDirectTransition(name: state_identifier, withStatements: stmts, withNextState: next_state), scopes))
} else {
return .Error(
Error(
@@ -187,7 +187,7 @@ public struct Parser {
{
case .Ok(let tse):
.Ok(
- (ParserTransitionStatement(withTransitionExpression: tse! as! SelectExpression), scopes))
+ (ParserStateSelectTransition(name: state_identifier, withStatements: stmts, withTransitioniExpression: tse as! SelectExpression), scopes))
case .Error(let e): .Error(e)
}
}
@@ -287,18 +287,8 @@ public struct Parser {
ErrorOnNode(node: node, withError: "Missing transition statement of state declaration"))
}
currentChild = node.child(at: currentChildIdx)
- switch TransitionStatement.Compile(
- node: currentChild!, inTree: tree, withScope: current_scopes)
- {
- case .Ok(let (transition_statement, new_scopes)):
- return Result.Ok(
- (
- ParserState(
- name: state_identifier, withStatements: parsed_s,
- withTransition: transition_statement), new_scopes
- ))
- case .Error(let e): return .Error(e)
- }
+ return TransitionStatement.Compile(
+ node: currentChild!, inTree: tree, forState: state_identifier, withStatements: parsed_s, withScope: current_scopes)
}
}
@@ -326,14 +316,13 @@ public struct Parser {
var error: Error? = .none
- var parser_scopes = scopes
-
// TODO: Assert that there is only one.
captures[0].node.enumerateChildren { parser_state in
- switch Parser.State.Compile(node: parser_state, inTree: tree, withLexicalScopes: scopes) {
- case Result.Ok(let (state, new_parser_scopes)):
+ switch Parser.State.Compile(
+ node: parser_state, inTree: tree, withLexicalScopes: scopes.enter())
+ {
+ case Result.Ok(let (state, _)):
parser.states = parser.states.append(state: state)
- parser_scopes = new_parser_scopes
case Result.Error(let e): error = e
}
}
@@ -342,6 +331,6 @@ public struct Parser {
return .Error(error)
}
- return Result.Ok((parser, parser_scopes))
+ return Result.Ok((parser, scopes))
}
-}
+}
\ No newline at end of file
diff --git a/Sources/P4Compiler/Program.swift b/Sources/P4Compiler/Program.swift
index daee625..df21b7a 100644
--- a/Sources/P4Compiler/Program.swift
+++ b/Sources/P4Compiler/Program.swift
@@ -62,12 +62,13 @@ public struct Program {
node: parser_declaration.nodes[1], inTree: tree, withLexicalScopes: program_scope)
{
case Result.Ok((let parser, let new_program_scope)):
- program.types.append(parser)
- program_scope = new_program_scope
+ program_scope = new_program_scope.declare(identifier: parser.name, withValue: parser)
case Result.Error(let error): return Result.Error(error)
}
}
+ // Any of the types that are in the top-level scope should go into the program!
+ program.types = Array(program_scope)
return Result.Ok(program)
}
}
diff --git a/Sources/P4Lang/Expressions.swift b/Sources/P4Lang/Expressions.swift
index e69de29..c6b82ab 100644
--- a/Sources/P4Lang/Expressions.swift
+++ b/Sources/P4Lang/Expressions.swift
@@ -0,0 +1,59 @@
+// 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 KeysetExpression {
+ public let key: EvaluatableExpression
+ public let next_state_identifier: Identifier
+ public let next_state: ParserState?
+
+ public init(withKey key: EvaluatableExpression, withNextState next_state_id: Identifier) {
+ self.key = key
+ self.next_state_identifier = next_state_id
+ self.next_state = .none
+ }
+ public init(
+ withKey key: EvaluatableExpression, withNextState next_state_id: Identifier,
+ withNextState next_state: ParserState
+ ) {
+ self.key = key
+ self.next_state_identifier = next_state_id
+ self.next_state = next_state
+ }
+
+}
+
+public struct SelectExpression {
+ public let selector: EvaluatableExpression
+ public let keyset_expressions: [KeysetExpression]
+
+ public init(
+ withSelector selector: EvaluatableExpression, withKeysetExpressions kses: [KeysetExpression]
+ ) {
+ self.selector = selector
+ self.keyset_expressions = kses
+ }
+
+ public func append_checked_kse(kse: KeysetExpression) -> SelectExpression {
+ var new_kse = self.keyset_expressions
+ new_kse.append(kse)
+ return SelectExpression(
+ withSelector: self.selector, withKeysetExpressions: new_kse)
+ }
+}
+
diff --git a/Sources/P4Lang/Instantiation.swift b/Sources/P4Lang/Instantiation.swift
deleted file mode 100644
index 7a0899d..0000000
--- a/Sources/P4Lang/Instantiation.swift
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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 Instantiation {
-
-}
diff --git a/Sources/P4Lang/Parser.swift b/Sources/P4Lang/Parser.swift
index f1f0b3d..ebb664c 100644
--- a/Sources/P4Lang/Parser.swift
+++ b/Sources/P4Lang/Parser.swift
@@ -35,152 +35,100 @@ public struct ParserAssignmentStatement {
}
}
-public struct KeysetExpression {
- public let key: EvaluatableExpression
- public let next_state_identifier: Identifier
- public let next_state: ParserState?
+/// A P4 Parser State
+///
+/// Note: A P4 Parser State is both a type and a value.
+public class ParserState: P4Type, P4Value, Equatable, CustomStringConvertible{
+ public static func == (lhs: ParserState, rhs: ParserState) -> Bool {
+ return lhs.state == rhs.state
+ }
- public init(withKey key: EvaluatableExpression, withNextState next_state_id: Identifier) {
- self.key = key
- self.next_state_identifier = next_state_id
- self.next_state = .none
- }
- public init(
- withKey key: EvaluatableExpression, withNextState next_state_id: Identifier,
- withNextState next_state: ParserState
- ) {
- self.key = key
- self.next_state_identifier = next_state_id
- self.next_state = next_state
- }
+ public func eq(rhs: any Common.P4Type) -> Bool {
+ return switch rhs {
+ case is ParserState: true
+ default: false
+ }
+ }
-}
+ public func type() -> any Common.P4Type {
+ return self
+ }
-public struct SelectExpression {
- public let selector: EvaluatableExpression
- public let keyset_expressions: [KeysetExpression]
-
- public init(
- withSelector selector: EvaluatableExpression, withKeysetExpressions kses: [KeysetExpression]
- ) {
- self.selector = selector
- self.keyset_expressions = kses
- }
-
- public func append_checked_kse(kse: KeysetExpression) -> SelectExpression {
- var new_kse = self.keyset_expressions
- new_kse.append(kse)
- return SelectExpression(
- withSelector: self.selector, withKeysetExpressions: new_kse)
- }
-}
-
-public struct ParserTransitionStatement {
- public let next_state: Identifier?
- public let transition_expression: SelectExpression?
-
- public init() {
- self.next_state = .none
- self.transition_expression = .none
- }
-
- public init(withTransitionExpression transition_expression: SelectExpression) {
- self.next_state = .none
- self.transition_expression = transition_expression
- }
-
- public init(withNextState next_state: Identifier) {
- self.next_state = next_state
- self.transition_expression = .none
- }
-}
-
-public class ParserState: Equatable, CustomStringConvertible, Comparable {
+ public func eq(rhs: any Common.P4Value) -> Bool {
+ return switch rhs {
+ case let other as ParserState: self.state == other.state
+ default: false
+ }
+ }
public private(set) var state: Identifier
public private(set) var statements: [EvaluatableStatement]
- public private(set) var transition: ParserTransitionStatement?
- public private(set) var next_state: ParserState?
-
- public static func < (lhs: ParserState, rhs: ParserState) -> Bool {
- // If lhs transitions to rhs, then return true. Otherwise, return false.
-
- // TODO!!
- return false
- }
public var description: String {
return "Name: \(state)"
}
- public static func == (lhs: ParserState, rhs: ParserState) -> Bool {
- return lhs.state == rhs.state
- }
-
/// Construct a ParserState
public init(
- name: Identifier, withStatements stmts: [EvaluatableStatement]?,
- withTransition transitionStatement: ParserTransitionStatement
+ name: Identifier, withStatements stmts: [EvaluatableStatement],
) {
state = name
- transition = transitionStatement
- statements = stmts ?? Array()
- }
-
- public func semantic_check(states: ParserStates) -> Bool {
- guard let transition = transition else {
- return self == accept || self == reject
- }
-
- if let next_state = transition.next_state,
- let next_state = states.find(withIdentifier: next_state)
- {
- self.next_state = next_state
- return true
- }
-
- return false
+ statements = stmts
}
/// (private) constructor (no transition)
///
/// accept and reject are the only final states and they are constructed internally.
- init(name: Identifier) {
+ private init(name: Identifier) {
state = name
- transition = .none
statements = Array()
}
+}
- public func direct_transition() -> Bool {
- return
- if let transition = self.transition,
- transition.next_state != nil
- {
- true
- } else {
- false
- }
+
+public class ParserStateDirectTransition: ParserState {
+
+ private let next_state: Identifier
+
+ public init(name: Identifier, withStatements stmts: [EvaluatableStatement], withNextState next_state: Identifier) {
+ self.next_state = next_state
+ super.init(name: name, withStatements: stmts)
+ }
+
+ public override var description: String {
+ return "State (Name: \(super.state) (direct transition))"
+ }
+
+ public func get_next_state() -> Identifier {
+ return self.next_state
}
}
-/// A P4 parser state type
-public struct P4ParserState: P4Type {
- public static func create() -> any P4Type {
- return P4ParserState()
+public class ParserStateNoTransition: ParserState {
+ public override init(name: Identifier, withStatements stmts: [any EvaluatableStatement]) {
+ super.init(name: name, withStatements: stmts)
}
- public var description: String {
- return "Parser State"
- }
- public func eq(rhs: any P4Type) -> Bool {
- return switch rhs {
- case is P4ParserState: true
- default: false
- }
+ public override var description: String {
+ return "State (Name: \(super.state) (no transition))"
}
}
-nonisolated(unsafe) public let accept: ParserState = ParserState(name: Identifier(name: "accept"))
-nonisolated(unsafe) public let reject: ParserState = ParserState(name: Identifier(name: "reject"))
+public class ParserStateSelectTransition: ParserState {
+
+ public let selectExpression: SelectExpression
+
+ public override var description: String {
+ return "State (Name: \(super.state) (select transition))"
+ }
+
+ public init(name: Identifier, withStatements stmts: [any EvaluatableStatement], withTransitioniExpression te: SelectExpression) {
+ self.selectExpression = te
+ super.init(name: name, withStatements: stmts)
+ }
+}
+
+nonisolated(unsafe) public let accept = ParserStateNoTransition(name: Identifier(name: "accept"), withStatements: [])
+nonisolated(unsafe) public let reject = ParserStateNoTransition(name: Identifier(name: "reject"), withStatements: [])
public struct ParserStates {
public var states: [ParserState] = Array()
@@ -198,22 +146,6 @@ public struct ParserStates {
return .none
}
- public func semantic_check() -> Result<()> {
- // Check whether all the states referred to in the transition statements are
- // valid.
- let errors = states.filter { state in
- return !state.semantic_check(states: self)
- }.map { state in
- return Result<()>.Error(Error(withMessage: "State \(state) has invalid transition"))
- }
-
- if !errors.isEmpty {
- return errors[0]
- }
-
- return .Ok(())
- }
-
public init() {
self.states = Array()
}
@@ -229,7 +161,21 @@ public struct ParserStates {
}
}
-public struct Parser: P4Type {
+/// A P4 Parser
+///
+/// Note: A Parser is both a type _and_ a value.
+public struct Parser: P4Type, P4Value {
+ public func type() -> any Common.P4Type {
+ return self
+ }
+
+ public func eq(rhs: any Common.P4Type) -> Bool {
+ return switch rhs {
+ case is Parser: true
+ default: false
+ }
+ }
+
public var states: ParserStates
public var name: Identifier
@@ -239,10 +185,6 @@ public struct Parser: P4Type {
self.name = name
}
- public static func create() -> any P4Type {
- return Parser(withName: Identifier(name: ""))
- }
-
public func findStartState() -> ParserState? {
for state in states.states {
if state.state == Identifier(name: "start") {
@@ -252,19 +194,14 @@ public struct Parser: P4Type {
return .none
}
- public func semantic_check() -> Result<()> {
- return self.states.semantic_check()
+ public func eq(rhs: any P4Value) -> Bool {
+ return switch rhs {
+ case let other as Parser: self.name == other.name
+ default: false
+ }
}
public var description: String {
return "Parser"
}
-
- public func eq(rhs: P4Type) -> Bool {
- return if let parser_rhs = rhs as? Parser {
- self.name == parser_rhs.name
- } else {
- false
- }
- }
}
diff --git a/Sources/P4Runtime/Expressions.swift b/Sources/P4Runtime/Expressions.swift
index d2835ad..06afca1 100644
--- a/Sources/P4Runtime/Expressions.swift
+++ b/Sources/P4Runtime/Expressions.swift
@@ -24,7 +24,8 @@ extension KeysetExpression: EvaluatableExpression {
}
public func type() -> any Common.P4Type {
- return P4ParserState.create()
+ // TODO
+ return reject
}
}
@@ -45,8 +46,9 @@ extension SelectExpression: EvaluatableExpression {
}
}
+ // TODO
public func type() -> any Common.P4Type {
- return P4ParserState.create()
+ return reject
}
}
diff --git a/Sources/P4Runtime/Parser.swift b/Sources/P4Runtime/Parser.swift
index 56a6523..39ddadd 100644
--- a/Sources/P4Runtime/Parser.swift
+++ b/Sources/P4Runtime/Parser.swift
@@ -32,39 +32,20 @@ extension ParserAssignmentStatement: EvaluatableStatement {
}
}
-public struct ParserStateDirectTransition: ParserStateInstance {
-
- public func type() -> any Common.P4Type {
- return P4ParserState.create()
- }
-
- public func eq(rhs: any Common.P4Value) -> Bool {
- switch rhs {
- case let state as ParserStateInstance: return currrent_state == state.state()
- default: return false
- }
- }
-
- public var description: String {
- return "Instance of \(currrent_state)"
- }
-
- public let currrent_state: ParserState
- public let next_state_identifier: Identifier
-
+extension ParserStateDirectTransition: EvaluatableParserState {
public func execute(
program: Common.ProgramExecution
- ) -> (any ParserStateInstance, Common.ProgramExecution) {
+ ) -> (any EvaluatableParserState, Common.ProgramExecution) {
var program = program.enter_scope()
- for statement in currrent_state.statements {
+ for statement in statements {
program = statement.evaluate(execution: program)
}
- let res = program.scopes.lookup(identifier: next_state_identifier)
+ let res = program.scopes.lookup(identifier: get_next_state())
if case .Ok(let value) = res {
- if value.type().eq(rhs: P4ParserState.create()) {
- return (value as! ParserStateInstance, program.exit_scope())
+ if value.type().eq(rhs: self) {
+ return (value as! EvaluatableParserState, program.exit_scope())
}
}
@@ -78,33 +59,15 @@ public struct ParserStateDirectTransition: ParserStateInstance {
}
public func state() -> P4Lang.ParserState {
- return currrent_state
+ return self
}
-
}
-public struct ParserStateNoTransition: ParserStateInstance {
-
- public func type() -> any Common.P4Type {
- return P4ParserState.create()
- }
-
- public func eq(rhs: any Common.P4Value) -> Bool {
- switch rhs {
- case let state as ParserStateInstance: return currrent_state == state.state()
- default: return false
- }
- }
-
- public var description: String {
- return "Instance of \(currrent_state)"
- }
-
- public let currrent_state: ParserState
+extension ParserStateNoTransition: EvaluatableParserState {
public func execute(
program: Common.ProgramExecution
- ) -> (any ParserStateInstance, Common.ProgramExecution) {
+ ) -> (any EvaluatableParserState, Common.ProgramExecution) {
return (self, program)
}
@@ -113,41 +76,27 @@ public struct ParserStateNoTransition: ParserStateInstance {
}
public func state() -> P4Lang.ParserState {
- return currrent_state
+ return self
}
}
-public struct ParserStateSelectTransition: ParserStateInstance {
- public func type() -> any Common.P4Type {
- return P4ParserState.create()
- }
-
- public func eq(rhs: any Common.P4Value) -> Bool {
- switch rhs {
- case let state as ParserStateInstance: return currrent_state == state.state()
- default: return false
- }
- }
-
- public var description: String {
- return "Instance of \(currrent_state)"
- }
+extension ParserStateSelectTransition: EvaluatableParserState {
public func execute(
program: Common.ProgramExecution
- ) -> (any ParserStateInstance, Common.ProgramExecution) {
+ ) -> (any EvaluatableParserState, Common.ProgramExecution) {
var program = program.enter_scope()
// First, evaluate the statements.
- for statement in currrent_state.statements {
+ for statement in statements {
program = statement.evaluate(execution: program)
}
let res = self.selectExpression.evaluate(execution: program)
if case .Ok(let value) = res {
- if value.type().eq(rhs: P4ParserState.create()) {
- return (value as! ParserStateInstance, program.exit_scope())
+ if value.type().eq(rhs: self) {
+ return (value as! EvaluatableParserState, program.exit_scope())
}
}
@@ -160,95 +109,32 @@ public struct ParserStateSelectTransition: ParserStateInstance {
}
public func state() -> P4Lang.ParserState {
- return currrent_state
- }
-
- public let selectExpression: SelectExpression
- public let currrent_state: ParserState
-}
-
-extension ParserState: Compilable {
- public typealias ToCompile = ParserState
- public typealias Compiled = ParserStateInstance
- public static func compile(_ state: ToCompile) -> Result {
-
- if state.direct_transition(),
- let transition_statement = state.transition
- {
- return .Ok(
- ParserStateDirectTransition(
- currrent_state: state, next_state_identifier: transition_statement.next_state!))
- }
-
- if let transition_select_statement = state.transition,
- let transition_select_expression = transition_select_statement.transition_expression
- {
-
- return .Ok(
- ParserStateSelectTransition(
- selectExpression: transition_select_expression, currrent_state: state))
- }
-
- return .Error(Error(withMessage: "Invalid parser state: No meaningful transition"))
+ return self
}
}
-extension ParserStates: Compilable {
- public typealias ToCompile = ParserStates
- public typealias Compiled = (ParserStateInstance, [ParserStateInstance])
- public static func compile(_ parser: ToCompile) -> Result {
- var compiled_states: [ParserStateInstance] = Array()
+extension Parser: ParserExecution {
+ public func execute(execution: ProgramExecution) -> (ParserState, ProgramExecution) {
+ var execution = execution.enter_scope()
- compiled_states.append(ParserStateNoTransition(currrent_state: accept))
- compiled_states.append(ParserStateNoTransition(currrent_state: reject))
+ execution = execution.declare(identifier: accept.state().state, withValue: accept)
+ execution = execution.declare(identifier: reject.state().state, withValue: reject)
- var start_state: ParserStateInstance? = .none
-
- // TODO: We assume that states are in transition-order!
- for state in parser.states {
- switch ParserState.compile(state) {
- case .Ok(let compiled):
- if compiled.state().state == Identifier(name: "start") {
- start_state = compiled
- }
- compiled_states.append(compiled)
- case .Error(let e): return .Error(e)
- }
+ // First, add every state to the scope!
+ for state in self.states.states {
+ execution = execution.declare(identifier: state.state, withValue: state)
}
- // Now, find the start state:
- if let start_state = start_state {
- return .Ok((start_state, compiled_states))
- } else {
- return .Error(Error(withMessage: "No start state defined"))
+ guard let _current_state = self.findStartState(),
+ var current_state = _current_state as? EvaluatableParserState else {
+ return (reject, execution.setError(error: Error(withMessage: "Could not find the start state")))
}
- }
-}
-public class ParserInstance: ProgramExecution {
- let states: [ParserStateInstance]
- let start_state: ParserStateInstance
-
- public init(start: ParserStateInstance, states: [ParserStateInstance]) {
- start_state = start
- self.states = states
- }
-
- public override var description: String {
- return "Execution: \(super.description)\nStates: \(states)"
- }
-}
-
-extension ParserInstance: Compilable {
- public typealias ToCompile = Parser
- public typealias Compiled = ParserInstance
-
- public static func compile(_ parser: ToCompile) -> Result {
- return switch ParserStates.compile(parser.states) {
- case .Ok(let (start_state, states)):
- Result.Ok(ParserInstance(start: start_state, states: states))
- case .Error(let e): Result.Error(e)
+ // Evaluate until the state is either accept or reject.
+ while !current_state.done() && !execution.hasError() {
+ (current_state, execution) = current_state.execute(program: execution)
}
+ return (current_state.state(), execution)
}
-}
+}
\ No newline at end of file
diff --git a/Sources/P4Runtime/Protocols.swift b/Sources/P4Runtime/Protocols.swift
index 5a0866d..dae3e98 100644
--- a/Sources/P4Runtime/Protocols.swift
+++ b/Sources/P4Runtime/Protocols.swift
@@ -19,7 +19,7 @@ import Common
import P4Lang
public protocol Execution {
- func execute() -> (ParserState, ProgramExecution)
+ func execute(execution: ProgramExecution) -> ProgramExecution
}
public protocol Compilable {
@@ -28,12 +28,12 @@ public protocol Compilable {
static func compile(_: ToCompile) -> Result
}
-public protocol ParserStateInstance: P4Value {
- func execute(program: ProgramExecution) -> (ParserStateInstance, ProgramExecution)
+public protocol EvaluatableParserState: P4Value {
+ func execute(program: ProgramExecution) -> (EvaluatableParserState, ProgramExecution)
func done() -> Bool
func state() -> ParserState
}
public protocol ParserExecution {
- func execute() -> (ParserState, ProgramExecution)
+ func execute(execution: ProgramExecution) -> (ParserState, ProgramExecution)
}
diff --git a/Sources/P4Runtime/Runtime.swift b/Sources/P4Runtime/Runtime.swift
index 0429507..5f25a42 100644
--- a/Sources/P4Runtime/Runtime.swift
+++ b/Sources/P4Runtime/Runtime.swift
@@ -19,11 +19,11 @@ import Common
import P4Lang
/// The runtime for a parser
-public class ParserRuntime: CustomStringConvertible {
- public var parser: ParserInstance
+public struct ParserRuntime: CustomStringConvertible {
+ public var parser: Parser
- init(execution: ParserInstance) {
- self.parser = execution
+ init(parser: Parser) {
+ self.parser = parser
}
/// Create a parser runtime from a P4 program
@@ -31,17 +31,15 @@ public class ParserRuntime: CustomStringConvertible {
return switch program.starting_parser() {
case .Ok(let parser):
- switch ParserInstance.compile(parser) {
- case .Ok(let execution): .Ok(P4Runtime.ParserRuntime(execution: execution))
- case .Error(let error): .Error(error)
- }
+ .Ok(P4Runtime.ParserRuntime(parser: parser))
case .Error(let error): .Error(error)
}
}
/// Run the P4 parser on a given packet
public func run() -> Result<(ParserState, ProgramExecution)> {
- let (end_state, execution) = parser.execute()
+
+ let (end_state, execution) = parser.execute(execution: ProgramExecution())
if let error = execution.getError() {
return .Error(error)
}
@@ -51,25 +49,4 @@ public class ParserRuntime: CustomStringConvertible {
public var description: String {
return "Runtime:\nExecution: \(parser)"
}
-}
-
-/// Instances of parsers are executable
-extension ParserInstance: ParserExecution {
- public func execute() -> (ParserState, ProgramExecution) {
- var execution = self as ProgramExecution
-
- execution = execution.enter_scope()
- // First, add every state to the scope!
- for state in self.states {
- execution = execution.declare(identifier: state.state().state, withValue: state)
- }
-
- var c = self.start_state
-
- // Evaluate until the state is either accept or reject.
- while !c.done() && !execution.hasError() {
- (c, execution) = c.execute(program: execution)
- }
- return (c.state(), execution)
- }
-}
+}
\ No newline at end of file
diff --git a/Sources/P4Runtime/Program.swift b/Sources/P4Runtime/Statements.swift
similarity index 100%
rename from Sources/P4Runtime/Program.swift
rename to Sources/P4Runtime/Statements.swift
diff --git a/Tests/p4rseTests/RuntimeTests.swift b/Tests/p4rseTests/RuntimeTests.swift
index 3c5ff68..2d33533 100644
--- a/Tests/p4rseTests/RuntimeTests.swift
+++ b/Tests/p4rseTests/RuntimeTests.swift
@@ -73,11 +73,12 @@ import TreeSitterP4
"""
let program = try #UseOkResult(Program.Compile(simple_parser_declaration))
+ let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program))
#expect(
- #RequireErrorResult(
- Error(withMessage: "No start state defined"),
- P4Runtime.ParserRuntime.create(program: program)))
+ #RequireErrorResult<(ParserState, ProgramExecution)>(
+ Error(withMessage: "Could not find the start state"),
+ runtime.run()))
}
@Test func test_simple_parser_with_transition_select_expression() async throws {