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 {