Files
gp4/Sources/P4Lang/Parser.swift
T
Will Hawkins 294f76acd4
Continuous Integration / Grammar Tests (push) Successful in 39s
Continuous Integration / Library Format Tests (push) Successful in 1m51s
Continuous Integration / Library Tests (push) Failing after 4m44s
compiler: Refactor Compiler To Remove Ambiguities
There were significant overlaps in the names of data structures
between the compiler and the language that made it necessary
to litter the code with P4Lang.xxxx. This refactor removes that
requirement in most places (Parser is ambiguous wherever TreeSitter
is used -- cannot avoid that!)

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
2026-05-27 12:59:29 -04:00

399 lines
11 KiB
Swift

// 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 <https://www.gnu.org/licenses/>.
import Common
public struct LocalElements {}
public struct LocalElement {}
public struct ParserAssignmentStatement {
public let lvalue: EvaluatableLValueExpression
public let value: EvaluatableExpression
public init(
withLValue lvalue: EvaluatableLValueExpression, withValue value: EvaluatableExpression
) {
self.lvalue = lvalue
self.value = value
}
}
/// A P4 Parser State
///
/// Note: A P4 Parser State is both a type and a value.
/// This "bare" parser state represents the state more as a type than a value.
public class ParserState: P4Type, Equatable, CustomStringConvertible {
let name: Identifier
public let statements: [EvaluatableStatement]
public static func == (lhs: ParserState, rhs: ParserState) -> Bool {
return lhs.eq(rhs: rhs)
}
public func eq(rhs: any Common.P4Type) -> Bool {
return switch rhs {
case let rrhs as ParserState: self.name == rrhs.name
default: false
}
}
public var description: String {
return "Parser State named \(self.name)"
}
public func getName() -> Identifier {
return self.name
}
public func getStatements() -> [EvaluatableStatement] {
return self.statements
}
/// Construct a ParserState
public init(_ name: Identifier, _ statements: [EvaluatableStatement] = Array()) {
self.name = name
self.statements = statements
}
public func def() -> P4DataValue? {
return .none
}
public func instantiate(_ name: Identifier) -> InstantiatedParserState? {
return .none
}
}
public class _AnyParserState: ParserState {
public override func eq(rhs: any Common.P4Type) -> Bool {
return switch rhs {
case is ParserState: true
default: false
}
}
}
nonisolated(unsafe) public let AnyParserState = _AnyParserState(Identifier(name: "AnyParserState"))
public struct TransitionStatement {}
public class ParserStateDirectTransition: ParserState {
public let next_state: InstantiatedParserState?
public let next_state_identifier: Identifier?
/// Construct a ParserState
public init(
name: Identifier, withNextState next_state: InstantiatedParserState,
withStatements stmts: [EvaluatableStatement] = Array(),
) {
self.next_state = next_state
self.next_state_identifier = .none
super.init(name, stmts)
}
public init(
name: Identifier, withNextStateIdentifier next_state_id: Identifier,
withStatements stmts: [EvaluatableStatement] = Array(),
) {
self.next_state = .none
self.next_state_identifier = next_state_id
super.init(name, stmts)
}
public override func instantiate(_ name: Identifier) -> InstantiatedParserState? {
return if let next_state = self.next_state {
ParserStateDirectTransitionValue(name: name, withState: self, withNextState: next_state)
} else {
ParserStateDirectTransitionValue(
name: name, withState: self, withNextStateIdentifier: self.next_state_identifier!)
}
}
}
public class ParserStateNoTransition: ParserState {
/// Construct a ParserState
public init(
name: Identifier, withStatements stmts: [EvaluatableStatement] = Array(),
) {
super.init(name, stmts)
}
public override func instantiate(_ name: Identifier) -> InstantiatedParserState? {
return ParserStateNoTransitionValue(name: name, withState: self)
}
}
public class ParserStateSelectTransition: ParserState {
public let te: SelectExpression
public init(
name: Identifier, withTransitionExpression te: SelectExpression,
withStatements stmts: [EvaluatableStatement] = Array()
) {
self.te = te
super.init(name, stmts)
}
public override func instantiate(_ name: Identifier) -> InstantiatedParserState? {
return ParserStateSelectTransitionValue(name: name, withState: self, withSelectExpression: te)
}
}
/// Instantiated Parser State
///
public class InstantiatedParserState: P4DataValue {
public static func == (lhs: InstantiatedParserState, rhs: InstantiatedParserState) -> Bool {
return lhs.state == rhs.state
}
public func type() -> any Common.P4Type {
return self.state
}
public func eq(rhs: any Common.P4DataValue) -> Bool {
return switch rhs {
case let other as InstantiatedParserState: self.state == other.state
default: false
}
}
public func lt(rhs: any Common.P4DataValue) -> Bool {
return switch rhs {
case let other as InstantiatedParserState: self.state.getName() < other.state.getName()
default: false
}
}
public func lte(rhs: any Common.P4DataValue) -> Bool {
return switch rhs {
case let other as InstantiatedParserState: self.state.getName() <= other.state.getName()
default: false
}
}
public func gt(rhs: any Common.P4DataValue) -> Bool {
return switch rhs {
case let other as InstantiatedParserState: self.state.getName() > other.state.getName()
default: false
}
}
public func gte(rhs: any Common.P4DataValue) -> Bool {
return switch rhs {
case let other as InstantiatedParserState: self.state.getName() >= other.state.getName()
default: false
}
}
public private(set) var state: ParserState
public private(set) var name: Identifier
public var description: String {
return "Instance of state of type \(state) named \(name)"
}
public init(_ name: Identifier, _ state: ParserState) {
self.name = name
self.state = state
}
}
public class ParserStateDirectTransitionValue: InstantiatedParserState {
public let next_state: InstantiatedParserState?
public let next_state_identifier: Identifier?
public init(
name: Identifier, withState state: ParserStateDirectTransition,
withNextState next_state: InstantiatedParserState
) {
self.next_state = next_state
self.next_state_identifier = .none
super.init(name, state)
}
public init(
name: Identifier, withState state: ParserStateDirectTransition,
withNextStateIdentifier next_state_id: Identifier
) {
self.next_state = .none
self.next_state_identifier = next_state_id
super.init(name, state)
}
}
public class ParserStateNoTransitionValue: InstantiatedParserState {
public init(name: Identifier, withState state: ParserStateNoTransition) {
super.init(name, state)
}
}
public class ParserStateSelectTransitionValue: InstantiatedParserState {
public let te: SelectExpression
public init(
name: Identifier, withState state: ParserStateSelectTransition,
withSelectExpression te: SelectExpression
) {
self.te = te
super.init(name, state)
}
}
nonisolated(unsafe) private let accept_type = ParserStateNoTransition(
name: Identifier(name: "accept"), withStatements: [])
nonisolated(unsafe) private let reject_type = ParserStateNoTransition(
name: Identifier(name: "reject"), withStatements: [])
nonisolated(unsafe) public let accept = ParserStateNoTransitionValue(
name: Identifier(name: "accept"), withState: accept_type)
nonisolated(unsafe) public let reject = ParserStateNoTransitionValue(
name: Identifier(name: "reject"), withState: reject_type)
public struct ParserStates {
public var states: [ParserState] = Array()
public func count() -> Int {
return states.count
}
public func find(withIdentifier id: Identifier) -> ParserState? {
for state in states {
if state.getName() == id {
return .some(state)
}
}
return .none
}
public init(_ states: [ParserState] = Array()) {
self.states = states
}
public func append(state: ParserState) -> 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: P4Type {
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 func findStartState() -> ParserState? {
return self.states.find(withIdentifier: Identifier(name: "start"))
}
public var description: String {
return "Parser \(self.name) with parameters: \(parameters) and states: \(self.states)"
}
public func def() -> P4DataValue? {
return .none
}
public func eq(rhs: any Common.P4Type) -> Bool {
return switch rhs {
case let parser_rhs as Parser: self.name == parser_rhs.name
default: false
}
}
public func instantiate(_ name: Identifier) -> ParserValue {
return ParserValue(self, name)
}
}
/// A instance of a P4 Parser
///
public struct ParserValue: P4DataValue {
public func type() -> P4Type {
return self.tipe
}
public func eq(rhs: any Common.P4DataValue) -> Bool {
return switch rhs {
case let rrhs as ParserValue: rrhs.type().eq(rhs: self.type()) && self.name == rrhs.name
default: false
}
}
public func lt(rhs: any Common.P4DataValue) -> Bool {
return switch rhs {
case let rrhs as ParserValue: rrhs.type().eq(rhs: self.type()) && self.name < rrhs.name
default: false
}
}
public func lte(rhs: any Common.P4DataValue) -> Bool {
return switch rhs {
case let rrhs as ParserValue: rrhs.type().eq(rhs: self.type()) && self.name <= rrhs.name
default: false
}
}
public func gt(rhs: any Common.P4DataValue) -> Bool {
return switch rhs {
case let rrhs as ParserValue: rrhs.type().eq(rhs: self.type()) && self.name > rrhs.name
default: false
}
}
public func gte(rhs: any Common.P4DataValue) -> Bool {
return switch rhs {
case let rrhs as ParserValue: rrhs.type().eq(rhs: self.type()) && self.name >= rrhs.name
default: false
}
}
public var tipe: Parser
public var name: Identifier
public init(_ tipe: Parser, _ name: Identifier) {
self.tipe = tipe
self.name = name
}
public var description: String {
return "Parser \(self.name) of type \(self.tipe)"
}
public func def() -> P4DataValue? {
return self.tipe.def()
}
}