Refactor into four major components:

1. Common: Things shared among all other components.
2. Lang: P4-language-related components.
3. Runtime: Components required to run a P4 program.
4. Parser: Components for parsing a P4 program from source.

Other components:

1. Macros
2. Tests
3. TreeSitterExtensions: Extra tree sitter functionality

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
Will Hawkins
2026-02-03 08:22:58 -05:00
parent 1203c0c90a
commit 989c9b1212
20 changed files with 513 additions and 320 deletions
+50
View File
@@ -0,0 +1,50 @@
// 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
import Lang
extension ParserTransitionStatement: EvaluatableParserTransitionStatement {
// TODO: Currently transitions to accept.
func transition(execution: ProgramExecution) -> (ParserState, ProgramExecution) {
return (accept, execution)
}
}
extension ParserState: EvaluatableParserState {
public func evaluate(execution: ProgramExecution) -> (ParserState, ProgramExecution) {
var currentExecution = execution
// First, evaluate the local elements.
for local_element in local_elements {
currentExecution = local_element.evaluate(execution: currentExecution)
}
// Then, evaluate the statements.
for statement in statements {
currentExecution = statement.evaluate(execution: currentExecution)
}
return if let transition = transition {
transition.transition(execution: currentExecution)
} else {
(reject, currentExecution)
}
}
}
+33
View File
@@ -0,0 +1,33 @@
// 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 Lang
import Common
extension VariableDeclarationStatement: EvaluatableParserStatement {
public func evaluate(execution: ProgramExecution) -> ProgramExecution {
let new_scopes = execution.scopes.declare(variable: self.variable)
execution.scopes = new_scopes
return execution
}
}
extension ExpressionStatement: EvaluatableParserStatement {
public func evaluate(execution: ProgramExecution) -> ProgramExecution {
return execution
}
}
+31
View File
@@ -0,0 +1,31 @@
// 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
import Lang
protocol EvaluatableParserState {
func evaluate(execution: ProgramExecution) -> (ParserState, ProgramExecution)
}
protocol EvaluatableParserTransitionStatement {
func transition(execution: ProgramExecution) -> (ParserState, ProgramExecution)
}
public protocol Execution {
func execute() -> (ParserState, ProgramExecution)
}
+58
View File
@@ -0,0 +1,58 @@
// 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
import Lang
public class ParserRuntime: CustomStringConvertible {
var execution: ParserExecution
init(execution: ParserExecution) {
self.execution = execution
}
public static func create(program: Lang.Parser) -> Result<ParserRuntime> {
switch ParserExecution.create(program) {
case .Ok(let execution): return .Ok(Runtime.ParserRuntime(execution: execution))
case .Error(let error): return .Error(error)
}
}
public func run(input: Packet) -> Result<(ParserState, ProgramExecution)> {
execution.scopes.enter()
return .Ok(execution.execute())
}
public var description: String {
//return "\(super.description)\nState: \(execution?.description ?? "N/A")\nError: \(error?.description ?? "None")"
return "Runtime:\nExecution: \(execution)"
}
}
extension ParserExecution: Execution {
public func execute() -> (ParserState, ProgramExecution) {
var execution = self as ProgramExecution
var state = self.state
// Evaluate until the state is either accept or reject.
while state != accept && state != reject {
(state, execution) = self.state.evaluate(execution: execution)
}
return (state, execution)
}
}