Refactor P4Compiler to P4Parser
Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
+5
-5
@@ -10,8 +10,8 @@ let package = Package(
|
|||||||
products: [
|
products: [
|
||||||
// Products define the executables and libraries a package produces, making them visible to other packages.
|
// Products define the executables and libraries a package produces, making them visible to other packages.
|
||||||
.library(
|
.library(
|
||||||
name: "P4Compiler",
|
name: "P4Parser",
|
||||||
targets: ["P4Compiler"]
|
targets: ["P4Parser"]
|
||||||
),
|
),
|
||||||
.library(
|
.library(
|
||||||
name: "Common",
|
name: "Common",
|
||||||
@@ -40,7 +40,7 @@ let package = Package(
|
|||||||
],
|
],
|
||||||
swiftSettings: [.enableExperimentalFeature("CodeItemMacros")]),
|
swiftSettings: [.enableExperimentalFeature("CodeItemMacros")]),
|
||||||
.target(
|
.target(
|
||||||
name: "P4Compiler",
|
name: "P4Parser",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.product(name: "SwiftTreeSitter", package: "swift-tree-sitter"),
|
.product(name: "SwiftTreeSitter", package: "swift-tree-sitter"),
|
||||||
.product(name: "SwiftTreeSitterLayer", package: "swift-tree-sitter"),
|
.product(name: "SwiftTreeSitterLayer", package: "swift-tree-sitter"),
|
||||||
@@ -70,14 +70,14 @@ let package = Package(
|
|||||||
.target(
|
.target(
|
||||||
name: "P4CodeGen",
|
name: "P4CodeGen",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
"P4Compiler", "Common",
|
"P4Parser", "Common",
|
||||||
//.product(name: "SwiftProtobuf", package: "swift-protobuf"),
|
//.product(name: "SwiftProtobuf", package: "swift-protobuf"),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
.testTarget(
|
.testTarget(
|
||||||
name: "Tests",
|
name: "Tests",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
"P4Compiler", "P4CodeGen", "Macros", "TreeSitterExtensions", "Common",
|
"P4Parser", "P4CodeGen", "Macros", "TreeSitterExtensions", "Common",
|
||||||
.product(name: "SystemPackage", package: "swift-system"),
|
.product(name: "SystemPackage", package: "swift-system"),
|
||||||
],
|
],
|
||||||
//swiftSettings: [.enableExperimentalFeature("CodeItemMacros"), .unsafeFlags(["-Xfrontend", "-dump-macro-expansions"])],
|
//swiftSettings: [.enableExperimentalFeature("CodeItemMacros"), .unsafeFlags(["-Xfrontend", "-dump-macro-expansions"])],
|
||||||
|
|||||||
@@ -1,50 +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 <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import Common
|
|
||||||
import Foundation
|
|
||||||
import Runtime
|
|
||||||
import SwiftTreeSitter
|
|
||||||
import Testing
|
|
||||||
import TreeSitter
|
|
||||||
import TreeSitterP4
|
|
||||||
import P4Compiler
|
|
||||||
|
|
||||||
let p4_program_with_control_decl = """
|
|
||||||
control simple() {
|
|
||||||
action a() {
|
|
||||||
}
|
|
||||||
table t {
|
|
||||||
key = {
|
|
||||||
true: exact;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
"""
|
|
||||||
|
|
||||||
/*
|
|
||||||
// snippet.include
|
|
||||||
let flter = { (tipe: P4QualifiedType) -> Bool in
|
|
||||||
switch tipe.baseType(){
|
|
||||||
case let c as Control: c.name == "simple"
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if case .Ok(let program) = SpecialCompilers.ProgramCompiler.Compile(p4_program_with_control_decl) {
|
|
||||||
print(program.InstancesWithTypes(flter))
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,45 +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 <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import Common
|
|
||||||
import Foundation
|
|
||||||
import Runtime
|
|
||||||
import SwiftTreeSitter
|
|
||||||
import Testing
|
|
||||||
import TreeSitter
|
|
||||||
import TreeSitterP4
|
|
||||||
import P4Compiler
|
|
||||||
|
|
||||||
let p4_program_with_struct_decl = """
|
|
||||||
struct agg {
|
|
||||||
int x;
|
|
||||||
};
|
|
||||||
"""
|
|
||||||
|
|
||||||
/*
|
|
||||||
// snippet.include
|
|
||||||
let flter = { (tipe: P4Type) -> Bool in
|
|
||||||
switch tipe {
|
|
||||||
case let c as P4Struct: c.name == "agg"
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if case .Ok(let program) = SpecialCompilers.ProgramCompiler.Compile(p4_program_with_struct_decl) {
|
|
||||||
print(program.TypesWithTypes(flter))
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
@@ -439,7 +439,7 @@ public struct CliTestDeclarationMacro: PeerMacro, Sendable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DeriveCompilableStatement: MemberMacro {
|
public enum DeriveParsableStatement: MemberMacro {
|
||||||
public static func expansion(
|
public static func expansion(
|
||||||
of: AttributeSyntax, providingMembersOf type: some DeclGroupSyntax, conformingTo: [TypeSyntax],
|
of: AttributeSyntax, providingMembersOf type: some DeclGroupSyntax, conformingTo: [TypeSyntax],
|
||||||
in: some MacroExpansionContext
|
in: some MacroExpansionContext
|
||||||
@@ -447,10 +447,10 @@ public enum DeriveCompilableStatement: MemberMacro {
|
|||||||
|
|
||||||
let implementation = DeclSyntax(
|
let implementation = DeclSyntax(
|
||||||
"""
|
"""
|
||||||
public static func CompileStatement(
|
public static func ParseStatement(
|
||||||
node: Node, withContext context: ASTCompilerContext
|
node: Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnStatement> {
|
) -> Result<CST.Statement> {
|
||||||
return switch Compile(node: node, withContext: context) {
|
return switch Parse(node: node, withContext: context) {
|
||||||
case .Ok(let res): .Ok(res)
|
case .Ok(let res): .Ok(res)
|
||||||
case .Error(let e): .Error(e)
|
case .Error(let e): .Error(e)
|
||||||
}
|
}
|
||||||
@@ -465,6 +465,6 @@ struct P4Macros: CompilerPlugin {
|
|||||||
var providingMacros: [Macro.Type] = [
|
var providingMacros: [Macro.Type] = [
|
||||||
RequireResult.self, RequireErrorResult.self, UseOkResult.self, UseErrorResult.self,
|
RequireResult.self, RequireErrorResult.self, UseOkResult.self, UseErrorResult.self,
|
||||||
RequireNodeType.self, SkipUnlessNodeType.self, SkipUnlessNodesTypes.self, RequireNodesType.self,
|
RequireNodeType.self, SkipUnlessNodeType.self, SkipUnlessNodesTypes.self, RequireNodesType.self,
|
||||||
MustOr.self, CliTestDeclarationMacro.self, DeriveCompilableStatement.self,
|
MustOr.self, CliTestDeclarationMacro.self, DeriveParsableStatement.self,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,50 +16,50 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import Common
|
import Common
|
||||||
import P4Compiler
|
import P4Parser
|
||||||
|
|
||||||
public struct TextSerializer {
|
public struct CSTTextSerializer {
|
||||||
public init() {}
|
public init() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct TextSerializerContext {
|
public struct CSTTextSerializerContext {
|
||||||
public let serialized: String
|
public let serialized: String
|
||||||
|
|
||||||
public init(_ serialized: String = "") {
|
public init(_ serialized: String = "") {
|
||||||
self.serialized = serialized
|
self.serialized = serialized
|
||||||
}
|
}
|
||||||
|
|
||||||
public func append(_ a: String) -> TextSerializerContext {
|
public func append(_ a: String) -> CSTTextSerializerContext {
|
||||||
return TextSerializerContext(self.serialized + a)
|
return CSTTextSerializerContext(self.serialized + a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TextSerializer: ASTVisitor<TextSerializerContext> {
|
extension CSTTextSerializer: CSTVisitor<CSTTextSerializerContext> {
|
||||||
public func visit(
|
public func visit(
|
||||||
node: P4Compiler.AST.BinaryOperatorExpression, driver: P4Compiler.ASTVisitorDriver,
|
node: CST.BinaryOperatorExpression, driver: CSTVisitorDriver,
|
||||||
context: TextSerializerContext
|
context: CSTTextSerializerContext
|
||||||
) -> Common.Result<TextSerializerContext> {
|
) -> Common.Result<CSTTextSerializerContext> {
|
||||||
return .Ok(context.append("Binary Operator Expression"))
|
return .Ok(context.append("Binary Operator Expression"))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func visit(
|
public func visit(
|
||||||
node: P4Compiler.AST.Literal, driver: P4Compiler.ASTVisitorDriver,
|
node: CST.Literal, driver: CSTVisitorDriver,
|
||||||
context: TextSerializerContext
|
context: CSTTextSerializerContext
|
||||||
) -> Common.Result<TextSerializerContext> {
|
) -> Common.Result<CSTTextSerializerContext> {
|
||||||
return .Ok(context.append("Literal Expression"))
|
return .Ok(context.append("Literal Expression"))
|
||||||
}
|
}
|
||||||
|
|
||||||
public func visit(
|
public func visit(
|
||||||
node: P4Compiler.AST.Identifier, driver: P4Compiler.ASTVisitorDriver,
|
node: CST.Identifier, driver: CSTVisitorDriver,
|
||||||
context: TextSerializerContext
|
context: CSTTextSerializerContext
|
||||||
) -> Common.Result<TextSerializerContext> {
|
) -> Common.Result<CSTTextSerializerContext> {
|
||||||
return .Ok(context.append("Identifier Expression"))
|
return .Ok(context.append("Identifier Expression"))
|
||||||
}
|
}
|
||||||
|
|
||||||
public func visit(
|
public func visit(
|
||||||
node: P4Compiler.AST.Parser, driver: P4Compiler.ASTVisitorDriver, context: TextSerializerContext
|
node: CST.Parser, driver: CSTVisitorDriver, context: CSTTextSerializerContext
|
||||||
) -> Common.Result<TextSerializerContext> {
|
) -> Common.Result<CSTTextSerializerContext> {
|
||||||
var context = context.append("Identifier Expression")
|
var context = context.append("Identifier Expression")
|
||||||
for s in node.states.states {
|
for s in node.states.states {
|
||||||
switch driver.visit(state: s, visitor: self, context: context) {
|
switch driver.visit(state: s, visitor: self, context: context) {
|
||||||
@@ -72,24 +72,23 @@ extension TextSerializer: ASTVisitor<TextSerializerContext> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func visit(
|
public func visit(
|
||||||
node: P4Compiler.AST.ParserStateDirectTransition, driver: P4Compiler.ASTVisitorDriver,
|
node: CST.ParserStateDirectTransition, driver: CSTVisitorDriver,
|
||||||
context: TextSerializerContext
|
context: CSTTextSerializerContext
|
||||||
) -> Common.Result<TextSerializerContext> {
|
) -> Common.Result<CSTTextSerializerContext> {
|
||||||
return .Ok(context.append("State: Direct Transition"))
|
return .Ok(context.append("State: Direct Transition"))
|
||||||
}
|
}
|
||||||
|
|
||||||
public func visit(
|
public func visit(
|
||||||
node: P4Compiler.AST.ParserStateNoTransition, driver: P4Compiler.ASTVisitorDriver,
|
node: CST.ParserStateNoTransition, driver: CSTVisitorDriver,
|
||||||
context: TextSerializerContext
|
context: CSTTextSerializerContext
|
||||||
) -> Common.Result<TextSerializerContext> {
|
) -> Common.Result<CSTTextSerializerContext> {
|
||||||
return .Ok(context.append("State: No Transition"))
|
return .Ok(context.append("State: No Transition"))
|
||||||
}
|
}
|
||||||
|
|
||||||
public func visit(
|
public func visit(
|
||||||
node: P4Compiler.AST.ParserStateSelectTransition, driver: P4Compiler.ASTVisitorDriver,
|
node: CST.ParserStateSelectTransition, driver: CSTVisitorDriver,
|
||||||
context: TextSerializerContext
|
context: CSTTextSerializerContext
|
||||||
) -> Common.Result<TextSerializerContext> {
|
) -> Common.Result<CSTTextSerializerContext> {
|
||||||
return .Ok(context.append("State: Direct Transition"))
|
return .Ok(context.append("State: Direct Transition"))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,71 +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 <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import Common
|
|
||||||
import SwiftTreeSitter
|
|
||||||
import TreeSitterExtensions
|
|
||||||
import TreeSitterP4
|
|
||||||
|
|
||||||
public protocol CompilableValue {
|
|
||||||
static func CompileValue(withValue value: String) -> Result<P4DataValue>
|
|
||||||
}
|
|
||||||
|
|
||||||
public protocol MaybeCompilableType {
|
|
||||||
static func MaybeCompileType(
|
|
||||||
type: SwiftTreeSitter.Node, withContext: ASTCompilerContext
|
|
||||||
) -> Result<AST.Tipe?>
|
|
||||||
}
|
|
||||||
|
|
||||||
public protocol CompilableType {
|
|
||||||
static func CompileType(
|
|
||||||
type: SwiftTreeSitter.Node, withContext: ASTCompilerContext
|
|
||||||
) -> Result<AST.Tipe>
|
|
||||||
}
|
|
||||||
public protocol CompilableExpression {
|
|
||||||
static func CompileExpression(
|
|
||||||
node: Node, withContext context: ASTCompilerContext
|
|
||||||
) -> Result<AST.AnExpression>
|
|
||||||
}
|
|
||||||
|
|
||||||
public protocol Compilable<C> {
|
|
||||||
associatedtype C
|
|
||||||
static func Compile(
|
|
||||||
node: Node, withContext context: ASTCompilerContext
|
|
||||||
) -> Result<C>
|
|
||||||
}
|
|
||||||
|
|
||||||
public protocol CompilableStatement {
|
|
||||||
static func CompileStatement(
|
|
||||||
node: Node, withContext context: ASTCompilerContext
|
|
||||||
) -> Result<AST.AnStatement>
|
|
||||||
}
|
|
||||||
|
|
||||||
public protocol ASTVisitor<T> {
|
|
||||||
associatedtype T
|
|
||||||
func visit(node: AST.BinaryOperatorExpression, driver: ASTVisitorDriver, context: T) -> Result<T>
|
|
||||||
func visit(node: AST.Literal, driver: ASTVisitorDriver, context: T) -> Result<T>
|
|
||||||
func visit(node: AST.Identifier, driver: ASTVisitorDriver, context: T) -> Result<T>
|
|
||||||
|
|
||||||
func visit(node: AST.Parser, driver: ASTVisitorDriver, context: T) -> Result<T>
|
|
||||||
func visit(
|
|
||||||
node: AST.ParserStateDirectTransition, driver: ASTVisitorDriver, context: T
|
|
||||||
) -> Result<T>
|
|
||||||
func visit(node: AST.ParserStateNoTransition, driver: ASTVisitorDriver, context: T) -> Result<T>
|
|
||||||
func visit(
|
|
||||||
node: AST.ParserStateSelectTransition, driver: ASTVisitorDriver, context: T
|
|
||||||
) -> Result<T>
|
|
||||||
}
|
|
||||||
@@ -1,240 +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 <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import Common
|
|
||||||
import SwiftTreeSitter
|
|
||||||
import TreeSitterExtensions
|
|
||||||
import TreeSitterP4
|
|
||||||
|
|
||||||
extension AST.TransitionStatement: Compilable {
|
|
||||||
public static func Compile(
|
|
||||||
node: Node, withContext context: ASTCompilerContext
|
|
||||||
) -> Result<AST.AnState> {
|
|
||||||
|
|
||||||
guard let state_identifier = context.lexical_context_name else {
|
|
||||||
return .Error(
|
|
||||||
ErrorWithLocation(
|
|
||||||
sourceLocation: node.toSourceLocation(),
|
|
||||||
withError: "Cannot parse a transition statement without the name of the containing state."
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let stmts = context.lexical_context_statements else {
|
|
||||||
return .Error(
|
|
||||||
ErrorWithLocation(
|
|
||||||
sourceLocation: node.toSourceLocation(),
|
|
||||||
withError:
|
|
||||||
"Cannot parse a transition statement without statements of the containing state."))
|
|
||||||
}
|
|
||||||
|
|
||||||
#RequireNodeType<Node, P4Statement>(
|
|
||||||
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
|
|
||||||
)
|
|
||||||
|
|
||||||
guard let tse_node = node.child(at: 1),
|
|
||||||
tse_node.nodeType! == "transitionSelectionExpression"
|
|
||||||
else {
|
|
||||||
return .Error(
|
|
||||||
ErrorWithLocation(
|
|
||||||
sourceLocation: node.toSourceLocation(),
|
|
||||||
withError: "Could not find transition select expression"))
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let next_node = tse_node.child(at: 0) else {
|
|
||||||
return .Error(
|
|
||||||
ErrorWithLocation(
|
|
||||||
sourceLocation: node.toSourceLocation(),
|
|
||||||
withError: "Could not find the next token in a transition selection expression"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the next node is an identifier, we have the simple form ...
|
|
||||||
if next_node.nodeType == "identifier" {
|
|
||||||
let maybe_parsed_next_state_id = AST.Identifier.CompileExpression(
|
|
||||||
node: next_node, withContext: context)
|
|
||||||
switch maybe_parsed_next_state_id {
|
|
||||||
case .Ok(let next_state_id):
|
|
||||||
return .Ok(
|
|
||||||
AST.ParserStateDirectTransition(
|
|
||||||
name: (state_identifier),
|
|
||||||
withNextStateIdentifier: next_state_id as! AST.Identifier, withStatements: stmts))
|
|
||||||
case .Error(let e):
|
|
||||||
return .Error(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We know that the next node is a select expression.
|
|
||||||
return
|
|
||||||
switch AST.SelectExpression.CompileExpression(node: next_node, withContext: context)
|
|
||||||
{
|
|
||||||
case .Ok(let tse):
|
|
||||||
.Ok(
|
|
||||||
AST.ParserStateSelectTransition(
|
|
||||||
name: state_identifier, withTransitionExpression: tse as! AST.SelectExpression,
|
|
||||||
withStatements: stmts,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
case .Error(let e): .Error(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct SpecialCompilers {
|
|
||||||
public struct Statements {
|
|
||||||
static func Compile(
|
|
||||||
node: Node, withContext context: ASTCompilerContext
|
|
||||||
) -> Result<[AST.AnStatement]> {
|
|
||||||
if node.nodeType != "statements" && node.nodeType != "parserStatements" {
|
|
||||||
return Result.Error(
|
|
||||||
ErrorWithLocation(
|
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Did not find expected statements"))
|
|
||||||
}
|
|
||||||
|
|
||||||
var errors: (any Errorable)? = .none
|
|
||||||
var parsed_s: [AST.AnStatement] = Array()
|
|
||||||
|
|
||||||
node.enumerateNamedChildren { node in
|
|
||||||
switch AST.Statement.Compile(
|
|
||||||
node: node, withContext: context)
|
|
||||||
{
|
|
||||||
case .Ok(let parsed_statement):
|
|
||||||
parsed_s.append(parsed_statement)
|
|
||||||
case .Error(let e):
|
|
||||||
errors =
|
|
||||||
if let errors = errors {
|
|
||||||
errors.append(error: e)
|
|
||||||
} else {
|
|
||||||
e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let errors = errors {
|
|
||||||
return .Error(errors)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.Ok(parsed_s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static func CompileParserBody(
|
|
||||||
withName name: AST.Identifier, withParameters parameters: AST.ParameterList, node: Node,
|
|
||||||
withContext context: ASTCompilerContext
|
|
||||||
) -> Result<AST.Parser> {
|
|
||||||
|
|
||||||
var parser = AST.Parser(withName: name, withParameters: parameters)
|
|
||||||
|
|
||||||
// Build a state from each one listed.
|
|
||||||
var errors: (any Errorable)? = .none
|
|
||||||
|
|
||||||
/// TODO: Assert that there is only one.
|
|
||||||
node.enumerateNamedChildren { parser_state in
|
|
||||||
if parser_state.nodeType != "parserState" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse a state in a nested scope.
|
|
||||||
switch AST.ParserState.Compile(
|
|
||||||
node: parser_state,
|
|
||||||
withContext: context)
|
|
||||||
{
|
|
||||||
case Result.Ok(let state):
|
|
||||||
// All states are instances inside the parser.
|
|
||||||
parser.states = parser.states.append(state: state)
|
|
||||||
case Result.Error(let e):
|
|
||||||
errors =
|
|
||||||
if let errors = errors {
|
|
||||||
errors.append(error: e)
|
|
||||||
} else {
|
|
||||||
e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let errors = errors {
|
|
||||||
return .Error(errors)
|
|
||||||
}
|
|
||||||
|
|
||||||
return .Ok(parser)
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct ProgramCompiler {
|
|
||||||
public static func Compile(_ source: String) -> Result<AST.Program> {
|
|
||||||
|
|
||||||
let maybe_parser = ConfigureP4Parser()
|
|
||||||
guard case .Ok(let p) = maybe_parser else {
|
|
||||||
return .Error(maybe_parser.error()!)
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = p.parse(source)
|
|
||||||
guard let tree = result,
|
|
||||||
!tree.isError(lang: p4lang),
|
|
||||||
!tree.containsMissing(lang: p4lang)
|
|
||||||
else {
|
|
||||||
return Result.Error(Error(withMessage: "Could not compile the P4 program"))
|
|
||||||
}
|
|
||||||
|
|
||||||
var program = AST.Program()
|
|
||||||
|
|
||||||
// Set up a context for parsing.
|
|
||||||
let compilation_context = ASTCompilerContext()
|
|
||||||
|
|
||||||
var errors: (any Errorable)? = .none
|
|
||||||
|
|
||||||
// Try to parse all top-level declarations.
|
|
||||||
result?.rootNode?.enumerateNamedChildren { (declaration_node: Node) in
|
|
||||||
let declaration_parsers: [String: CompilableStatement.Type] = [
|
|
||||||
"declaration": AST.Declaration.self,
|
|
||||||
"instantiation": AST.Instantiation.self,
|
|
||||||
]
|
|
||||||
|
|
||||||
if let parser = declaration_parsers[declaration_node.nodeType!] {
|
|
||||||
let r = parser.CompileStatement(node: declaration_node, withContext: compilation_context)
|
|
||||||
switch r {
|
|
||||||
case .Ok(let compiled):
|
|
||||||
program.statements = program.statements + [compiled]
|
|
||||||
case .Error(let e):
|
|
||||||
errors =
|
|
||||||
if let errors = errors {
|
|
||||||
errors.append(error: e)
|
|
||||||
} else {
|
|
||||||
e
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let e = ErrorWithLocation(
|
|
||||||
sourceLocation: declaration_node.toSourceLocation(),
|
|
||||||
withError:
|
|
||||||
"\(declaration_node.nodeType!) cannot be at a P4 program top level")
|
|
||||||
errors =
|
|
||||||
if let errors = errors {
|
|
||||||
errors.append(error: e)
|
|
||||||
} else {
|
|
||||||
e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let errors = errors {
|
|
||||||
return .Error(errors)
|
|
||||||
}
|
|
||||||
return Result.Ok(program)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -17,24 +17,31 @@
|
|||||||
|
|
||||||
import Common
|
import Common
|
||||||
|
|
||||||
extension P4Value: AST.AnExpression {}
|
extension P4Value: CST.AnExpression {}
|
||||||
|
|
||||||
public struct AST {
|
public struct CST {
|
||||||
|
|
||||||
public protocol AnExpression {}
|
public protocol AnExpression {}
|
||||||
public protocol AnStatement {}
|
public protocol Statement {}
|
||||||
public protocol AnState {}
|
public protocol AnState {}
|
||||||
|
|
||||||
public struct Statement {}
|
|
||||||
struct Expression {}
|
struct Expression {}
|
||||||
|
|
||||||
public struct VariableDeclarationStatement: AnStatement {
|
public struct Statements {
|
||||||
|
public let statements: [Statement]
|
||||||
|
|
||||||
|
public init(_ s: [Statement]) {
|
||||||
|
self.statements = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct VariableDeclarationStatement: Statement {
|
||||||
public var initializer: AnExpression?
|
public var initializer: AnExpression?
|
||||||
public var identifier: AST.Identifier
|
public var identifier: CST.Identifier
|
||||||
public var tipe: AST.Tipe
|
public var tipe: CST.Tipe
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
identifier: Identifier, withType tipe: AST.Tipe, withInitializer initializer: AnExpression?
|
identifier: Identifier, withType tipe: CST.Tipe, withInitializer initializer: AnExpression?
|
||||||
) {
|
) {
|
||||||
self.identifier = identifier
|
self.identifier = identifier
|
||||||
self.initializer = initializer
|
self.initializer = initializer
|
||||||
@@ -42,20 +49,20 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ConditionalStatement: AnStatement {
|
public struct ConditionalStatement: Statement {
|
||||||
public var condition: AnExpression
|
public var condition: AnExpression
|
||||||
public var thenn: AnStatement
|
public var thenn: Statement
|
||||||
public var elss: AnStatement?
|
public var elss: Statement?
|
||||||
|
|
||||||
public init(condition: AnExpression, withThen thenn: AnStatement) {
|
public init(condition: AnExpression, withThen thenn: Statement) {
|
||||||
self.condition = condition
|
self.condition = condition
|
||||||
self.thenn = thenn
|
self.thenn = thenn
|
||||||
self.elss = .none
|
self.elss = .none
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
condition: AnExpression, withThen thenn: AnStatement,
|
condition: AnExpression, withThen thenn: Statement,
|
||||||
andElse elss: AnStatement
|
andElse elss: Statement
|
||||||
) {
|
) {
|
||||||
self.condition = condition
|
self.condition = condition
|
||||||
self.thenn = thenn
|
self.thenn = thenn
|
||||||
@@ -63,16 +70,16 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct BlockStatement: AnStatement {
|
public struct BlockStatement: Statement {
|
||||||
public var statements: [AnStatement]
|
public var statements: Statements
|
||||||
|
|
||||||
public init(_ statements: [AnStatement]) {
|
public init(_ statements: Statements) {
|
||||||
self.statements = statements
|
self.statements = statements
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ReturnStatement: AnStatement {
|
public struct ReturnStatement: Statement {
|
||||||
public let value: AnExpression
|
public let value: AnExpression
|
||||||
|
|
||||||
public init(_ value: AnExpression) {
|
public init(_ value: AnExpression) {
|
||||||
@@ -80,11 +87,11 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ApplyStatement: AnStatement {
|
public struct ApplyStatement: Statement {
|
||||||
public let body: AST.BlockStatement?
|
public let body: CST.BlockStatement?
|
||||||
|
|
||||||
public init() { self.body = .none }
|
public init() { self.body = .none }
|
||||||
public init(_ body: AST.BlockStatement) {
|
public init(_ body: CST.BlockStatement) {
|
||||||
self.body = body
|
self.body = body
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,14 +102,14 @@ public struct AST {
|
|||||||
+ "\(self.name) with parameters \(self.params) and body \(String(describing: self.body))"
|
+ "\(self.name) with parameters \(self.params) and body \(String(describing: self.body))"
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: AST.BlockStatement?
|
public var body: CST.BlockStatement?
|
||||||
public var params: AST.ParameterList
|
public var params: CST.ParameterList
|
||||||
public var name: AST.Identifier
|
public var name: CST.Identifier
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
named name: AST.Identifier = AST.Identifier(Common.Identifier(name: "")),
|
named name: CST.Identifier = CST.Identifier(Common.Identifier(name: "")),
|
||||||
withParameters parameters: ParameterList = ParameterList([]),
|
withParameters parameters: ParameterList = ParameterList([]),
|
||||||
withBody body: AST.BlockStatement? = .none
|
withBody body: CST.BlockStatement? = .none
|
||||||
) {
|
) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.params = parameters
|
self.params = parameters
|
||||||
@@ -112,8 +119,8 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct Actions: CustomStringConvertible {
|
public struct Actions: CustomStringConvertible {
|
||||||
public let actions: [AST.Action]
|
public let actions: [CST.Action]
|
||||||
public init(withActions actions: [AST.Action]) {
|
public init(withActions actions: [CST.Action]) {
|
||||||
self.actions = actions
|
self.actions = actions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,10 +137,10 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct TableKeyEntry: CustomStringConvertible {
|
public struct TableKeyEntry: CustomStringConvertible {
|
||||||
public let key: AST.KeysetExpression
|
public let key: CST.KeysetExpression
|
||||||
public let match_type: AST.TableKeyMatchType
|
public let match_type: CST.TableKeyMatchType
|
||||||
|
|
||||||
public init(_ key: AST.KeysetExpression, _ match: AST.TableKeyMatchType) {
|
public init(_ key: CST.KeysetExpression, _ match: CST.TableKeyMatchType) {
|
||||||
self.key = key
|
self.key = key
|
||||||
self.match_type = match
|
self.match_type = match
|
||||||
}
|
}
|
||||||
@@ -144,9 +151,9 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct TableKeys: CustomStringConvertible {
|
public struct TableKeys: CustomStringConvertible {
|
||||||
public let keys: [AST.TableKeyEntry]
|
public let keys: [CST.TableKeyEntry]
|
||||||
|
|
||||||
public init(withEntries entries: [AST.TableKeyEntry]) {
|
public init(withEntries entries: [CST.TableKeyEntry]) {
|
||||||
self.keys = entries
|
self.keys = entries
|
||||||
}
|
}
|
||||||
public init() {
|
public init() {
|
||||||
@@ -162,8 +169,8 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct TableActionsProperty: CustomStringConvertible {
|
public struct TableActionsProperty: CustomStringConvertible {
|
||||||
public let actions: [AST.Identifier]
|
public let actions: [CST.Identifier]
|
||||||
public init(_ actions: [AST.Identifier] = []) {
|
public init(_ actions: [CST.Identifier] = []) {
|
||||||
self.actions = actions
|
self.actions = actions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,9 +183,9 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct TablePropertyList: CustomStringConvertible {
|
public struct TablePropertyList: CustomStringConvertible {
|
||||||
public let actions: AST.TableActionsProperty
|
public let actions: CST.TableActionsProperty
|
||||||
public let keys: AST.TableKeys
|
public let keys: CST.TableKeys
|
||||||
public init(withActions actions: AST.TableActionsProperty, withKeys keys: AST.TableKeys) {
|
public init(withActions actions: CST.TableActionsProperty, withKeys keys: CST.TableKeys) {
|
||||||
self.actions = actions
|
self.actions = actions
|
||||||
self.keys = keys
|
self.keys = keys
|
||||||
}
|
}
|
||||||
@@ -189,13 +196,13 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct Table: CustomStringConvertible {
|
public struct Table: CustomStringConvertible {
|
||||||
public let properties: AST.TablePropertyList
|
public let properties: CST.TablePropertyList
|
||||||
let name: AST.Identifier
|
let name: CST.Identifier
|
||||||
public let entries: [(P4Value, AST.Identifier)]
|
public let entries: [(P4Value, CST.Identifier)]
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
withName name: AST.Identifier, withPropertyList property_list: AST.TablePropertyList,
|
withName name: CST.Identifier, withPropertyList property_list: CST.TablePropertyList,
|
||||||
withEntries entries: [(P4Value, AST.Identifier)] = []
|
withEntries entries: [(P4Value, CST.Identifier)] = []
|
||||||
) {
|
) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.properties = property_list
|
self.properties = property_list
|
||||||
@@ -210,13 +217,13 @@ public struct AST {
|
|||||||
/// compared to the entries and the match is assocated with an action
|
/// compared to the entries and the match is assocated with an action
|
||||||
/// that is invoked when the match occurs!
|
/// that is invoked when the match occurs!
|
||||||
|
|
||||||
public func update(addEntry entry: (P4Value, AST.Identifier)) -> Table {
|
public func update(addEntry entry: (P4Value, CST.Identifier)) -> Table {
|
||||||
return Table(
|
return Table(
|
||||||
withName: self.name, withPropertyList: self.properties, withEntries: self.entries + [entry])
|
withName: self.name, withPropertyList: self.properties, withEntries: self.entries + [entry])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol AnDeclaration: AnStatement {}
|
public protocol AnDeclaration: Statement {}
|
||||||
|
|
||||||
public struct Declaration {}
|
public struct Declaration {}
|
||||||
|
|
||||||
@@ -225,24 +232,24 @@ public struct AST {
|
|||||||
return "Control named \(self._name) \(self.parameters) \(self.actions) \(self.table)"
|
return "Control named \(self._name) \(self.parameters) \(self.actions) \(self.table)"
|
||||||
}
|
}
|
||||||
|
|
||||||
public let actions: AST.Actions
|
public let actions: CST.Actions
|
||||||
public let table: AST.Table
|
public let table: CST.Table
|
||||||
let _parameters: AST.ParameterList
|
let _parameters: CST.ParameterList
|
||||||
let _name: AST.Identifier
|
let _name: CST.Identifier
|
||||||
let apply: AST.ApplyStatement
|
let apply: CST.ApplyStatement
|
||||||
|
|
||||||
public var parameters: AST.ParameterList {
|
public var parameters: CST.ParameterList {
|
||||||
_parameters
|
_parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
public var name: AST.Identifier {
|
public var name: CST.Identifier {
|
||||||
_name
|
_name
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
named: AST.Identifier, withParameters parameters: AST.ParameterList,
|
named: CST.Identifier, withParameters parameters: CST.ParameterList,
|
||||||
withTable table: AST.Table,
|
withTable table: CST.Table,
|
||||||
withActions actions: AST.Actions, withApply apply: AST.ApplyStatement
|
withActions actions: CST.Actions, withApply apply: CST.ApplyStatement
|
||||||
) {
|
) {
|
||||||
self._name = named
|
self._name = named
|
||||||
self._parameters = parameters
|
self._parameters = parameters
|
||||||
@@ -251,7 +258,7 @@ public struct AST {
|
|||||||
self.apply = apply
|
self.apply = apply
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateTable(addEntry entry: (P4Value, AST.Identifier)) -> Control {
|
public func updateTable(addEntry entry: (P4Value, CST.Identifier)) -> Control {
|
||||||
let table = self.table.update(addEntry: entry)
|
let table = self.table.update(addEntry: entry)
|
||||||
|
|
||||||
return Control(
|
return Control(
|
||||||
@@ -266,9 +273,9 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct ExternDeclaration: AnDeclaration {
|
public struct ExternDeclaration: AnDeclaration {
|
||||||
public let declaration: AST.AnDeclaration
|
public let declaration: CST.AnDeclaration
|
||||||
|
|
||||||
public init(_ declaration: AST.AnDeclaration) {
|
public init(_ declaration: CST.AnDeclaration) {
|
||||||
self.declaration = declaration
|
self.declaration = declaration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,15 +285,15 @@ public struct AST {
|
|||||||
return "Function named \(self.name) that returns \(self.tipe) with parameters \(self.params)"
|
return "Function named \(self.name) that returns \(self.tipe) with parameters \(self.params)"
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: AST.BlockStatement?
|
public var body: CST.BlockStatement?
|
||||||
public var params: AST.ParameterList
|
public var params: CST.ParameterList
|
||||||
public var name: AST.Identifier
|
public var name: CST.Identifier
|
||||||
public var tipe: AST.Tipe
|
public var tipe: CST.Tipe
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
named name: AST.Identifier, ofType type: AST.Tipe,
|
named name: CST.Identifier, ofType type: CST.Tipe,
|
||||||
withParameters parameters: AST.ParameterList,
|
withParameters parameters: CST.ParameterList,
|
||||||
withBody body: AST.BlockStatement?
|
withBody body: CST.BlockStatement?
|
||||||
) {
|
) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.tipe = type
|
self.tipe = type
|
||||||
@@ -296,22 +303,22 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct StructDeclaration: AnDeclaration {
|
public struct StructDeclaration: AnDeclaration {
|
||||||
public let fields: [AST.VariableDeclarationStatement]
|
public let fields: [CST.VariableDeclarationStatement]
|
||||||
public let identifier: AST.Identifier
|
public let identifier: CST.Identifier
|
||||||
public init(_ id: AST.Identifier, _ fields: [AST.VariableDeclarationStatement]) {
|
public init(_ id: CST.Identifier, _ fields: [CST.VariableDeclarationStatement]) {
|
||||||
self.identifier = id
|
self.identifier = id
|
||||||
self.fields = fields
|
self.fields = fields
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Instantiation: AnStatement {
|
public struct Instantiation: Statement {
|
||||||
public let name: AST.Identifier
|
public let name: CST.Identifier
|
||||||
public var tipe: AST.Identifier
|
public var tipe: CST.Identifier
|
||||||
public let arguments: AST.ArgumentList
|
public let arguments: CST.ArgumentList
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
named name: AST.Identifier, withType tipe: AST.Identifier,
|
named name: CST.Identifier, withType tipe: CST.Identifier,
|
||||||
withArguments arguments: AST.ArgumentList
|
withArguments arguments: CST.ArgumentList
|
||||||
) {
|
) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.arguments = arguments
|
self.arguments = arguments
|
||||||
@@ -319,7 +326,7 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ExpressionStatement: AnStatement {
|
public struct ExpressionStatement: Statement {
|
||||||
public let expression: AnExpression
|
public let expression: AnExpression
|
||||||
|
|
||||||
public init(_ expr: AnExpression) {
|
public init(_ expr: AnExpression) {
|
||||||
@@ -347,10 +354,10 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct SelectCaseExpression: AnExpression {
|
public struct SelectCaseExpression: AnExpression {
|
||||||
public let key: AST.KeysetExpression
|
public let key: CST.KeysetExpression
|
||||||
public let next_state_identifier: AST.Identifier
|
public let next_state_identifier: CST.Identifier
|
||||||
|
|
||||||
public init(withKey key: AST.KeysetExpression, withNextState next_state_id: AST.Identifier) {
|
public init(withKey key: CST.KeysetExpression, withNextState next_state_id: CST.Identifier) {
|
||||||
self.key = key
|
self.key = key
|
||||||
self.next_state_identifier = next_state_id
|
self.next_state_identifier = next_state_id
|
||||||
}
|
}
|
||||||
@@ -358,17 +365,17 @@ public struct AST {
|
|||||||
|
|
||||||
public struct SelectExpression: AnExpression {
|
public struct SelectExpression: AnExpression {
|
||||||
public let selector: AnExpression
|
public let selector: AnExpression
|
||||||
public let case_expressions: [AST.SelectCaseExpression]
|
public let case_expressions: [CST.SelectCaseExpression]
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
withSelector selector: AnExpression,
|
withSelector selector: AnExpression,
|
||||||
withSelectCaseExpressions sces: [AST.SelectCaseExpression]
|
withSelectCaseExpressions sces: [CST.SelectCaseExpression]
|
||||||
) {
|
) {
|
||||||
self.selector = selector
|
self.selector = selector
|
||||||
self.case_expressions = sces
|
self.case_expressions = sces
|
||||||
}
|
}
|
||||||
|
|
||||||
public func append_checked_sce(sce: AST.SelectCaseExpression) -> AST.SelectExpression {
|
public func append_checked_sce(sce: CST.SelectCaseExpression) -> CST.SelectExpression {
|
||||||
var new_cses = self.case_expressions
|
var new_cses = self.case_expressions
|
||||||
new_cses.append(sce)
|
new_cses.append(sce)
|
||||||
return SelectExpression(
|
return SelectExpression(
|
||||||
@@ -443,7 +450,7 @@ public struct AST {
|
|||||||
|
|
||||||
public struct LocalElement {}
|
public struct LocalElement {}
|
||||||
|
|
||||||
public struct ParserAssignmentStatement: AnStatement {
|
public struct ParserAssignmentStatement: Statement {
|
||||||
public let lvalue: AnExpression
|
public let lvalue: AnExpression
|
||||||
public let value: AnExpression
|
public let value: AnExpression
|
||||||
|
|
||||||
@@ -458,7 +465,7 @@ public struct AST {
|
|||||||
/// A P4 Parser State
|
/// A P4 Parser State
|
||||||
public class ParserState {
|
public class ParserState {
|
||||||
let name: Identifier
|
let name: Identifier
|
||||||
public let statements: [AnStatement]
|
public let statements: CST.Statements?
|
||||||
|
|
||||||
public var description: String {
|
public var description: String {
|
||||||
return "Parser State named \(self.name)"
|
return "Parser State named \(self.name)"
|
||||||
@@ -468,12 +475,12 @@ public struct AST {
|
|||||||
return self.name
|
return self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
public func getStatements() -> [AnStatement] {
|
public func getStatements() -> CST.Statements? {
|
||||||
return self.statements
|
return self.statements
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a ParserState
|
/// Construct a ParserState
|
||||||
public init(_ name: Identifier, _ statements: [AnStatement] = Array()) {
|
public init(_ name: Identifier, _ statements: CST.Statements? = .none) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.statements = statements
|
self.statements = statements
|
||||||
}
|
}
|
||||||
@@ -489,7 +496,7 @@ public struct AST {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
name: Identifier, withNextStateIdentifier next_state_id: Identifier,
|
name: Identifier, withNextStateIdentifier next_state_id: Identifier,
|
||||||
withStatements stmts: [AnStatement] = Array(),
|
withStatements stmts: CST.Statements? = .none
|
||||||
) {
|
) {
|
||||||
self.next_state_identifier = next_state_id
|
self.next_state_identifier = next_state_id
|
||||||
super.init(name, stmts)
|
super.init(name, stmts)
|
||||||
@@ -499,7 +506,7 @@ public struct AST {
|
|||||||
public class ParserStateNoTransition: ParserState, AnState {
|
public class ParserStateNoTransition: ParserState, AnState {
|
||||||
/// Construct a ParserState
|
/// Construct a ParserState
|
||||||
public init(
|
public init(
|
||||||
name: Identifier, withStatements stmts: [AnStatement] = Array(),
|
name: Identifier, withStatements stmts: CST.Statements? = .none
|
||||||
) {
|
) {
|
||||||
super.init(name, stmts)
|
super.init(name, stmts)
|
||||||
}
|
}
|
||||||
@@ -511,7 +518,7 @@ public struct AST {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
name: Identifier, withTransitionExpression te: SelectExpression,
|
name: Identifier, withTransitionExpression te: SelectExpression,
|
||||||
withStatements stmts: [AnStatement] = Array()
|
withStatements stmts: CST.Statements? = .none
|
||||||
) {
|
) {
|
||||||
self.te = te
|
self.te = te
|
||||||
super.init(name, stmts)
|
super.init(name, stmts)
|
||||||
@@ -572,11 +579,11 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct Parameter: CustomStringConvertible {
|
public struct Parameter: CustomStringConvertible {
|
||||||
public var name: AST.Identifier
|
public var name: CST.Identifier
|
||||||
public var type: AST.Tipe
|
public var type: CST.Tipe
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
identifier: Identifier, withType type: AST.Tipe
|
identifier: Identifier, withType type: CST.Tipe
|
||||||
) {
|
) {
|
||||||
self.name = identifier
|
self.name = identifier
|
||||||
self.type = type
|
self.type = type
|
||||||
@@ -589,18 +596,18 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct ParameterList: CustomStringConvertible {
|
public struct ParameterList: CustomStringConvertible {
|
||||||
public var parameters: [AST.Parameter]
|
public var parameters: [CST.Parameter]
|
||||||
|
|
||||||
public init() {
|
public init() {
|
||||||
self.parameters = Array()
|
self.parameters = Array()
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(_ parameters: [AST.Parameter]) {
|
public init(_ parameters: [CST.Parameter]) {
|
||||||
self.parameters = parameters
|
self.parameters = parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
public func addParameter(_ parameter: AST.Parameter) -> AST.ParameterList {
|
public func addParameter(_ parameter: CST.Parameter) -> CST.ParameterList {
|
||||||
return AST.ParameterList(self.parameters + [parameter])
|
return CST.ParameterList(self.parameters + [parameter])
|
||||||
}
|
}
|
||||||
|
|
||||||
public var description: String {
|
public var description: String {
|
||||||
@@ -612,57 +619,57 @@ public struct AST {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct ArgumentList {
|
public struct ArgumentList {
|
||||||
public let arguments: [AST.Argument]
|
public let arguments: [CST.Argument]
|
||||||
|
|
||||||
public init(_ arguments: [AST.Argument] = []) {
|
public init(_ arguments: [CST.Argument] = []) {
|
||||||
self.arguments = arguments
|
self.arguments = arguments
|
||||||
}
|
}
|
||||||
|
|
||||||
public func addArgument(_ argument: AST.Argument) -> AST.ArgumentList {
|
public func addArgument(_ argument: CST.Argument) -> CST.ArgumentList {
|
||||||
return ArgumentList(self.arguments + [argument])
|
return ArgumentList(self.arguments + [argument])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Argument {
|
public struct Argument {
|
||||||
public let index: Int
|
public let index: Int
|
||||||
public let argument: AST.AnExpression
|
public let argument: CST.AnExpression
|
||||||
|
|
||||||
public init(_ argument: AST.AnExpression, atIndex index: Int) {
|
public init(_ argument: CST.AnExpression, atIndex index: Int) {
|
||||||
self.argument = argument
|
self.argument = argument
|
||||||
self.index = index
|
self.index = index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct Program {
|
public struct Program {
|
||||||
public var statements: [AnStatement]
|
public var statements: Statements
|
||||||
public init(_ stmts: [AnStatement] = Array()) {
|
public init(_ stmts: Statements = Statements([])) {
|
||||||
self.statements = stmts
|
self.statements = stmts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ASTCompilerContext {
|
public struct CSTCompilerContext {
|
||||||
public let lexical_context_name: AST.Identifier?
|
public let lexical_context_name: CST.Identifier?
|
||||||
public let lexical_context_statements: [AST.AnStatement]?
|
public let lexical_context_statements: CST.Statements?
|
||||||
public let extern_context: Bool
|
public let extern_context: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
_ name: AST.Identifier? = .none, _ stmts: [AST.AnStatement]? = .none, _ extern: Bool = false
|
_ name: CST.Identifier? = .none, _ stmts: CST.Statements? = .none, _ extern: Bool = false
|
||||||
) {
|
) {
|
||||||
self.lexical_context_name = name
|
self.lexical_context_name = name
|
||||||
self.lexical_context_statements = stmts
|
self.lexical_context_statements = stmts
|
||||||
self.extern_context = extern
|
self.extern_context = extern
|
||||||
}
|
}
|
||||||
|
|
||||||
public func update(withContextName cn: AST.Identifier?) -> ASTCompilerContext {
|
public func update(withContextName cn: CST.Identifier?) -> CSTCompilerContext {
|
||||||
return ASTCompilerContext(cn, self.lexical_context_statements, self.extern_context)
|
return CSTCompilerContext(cn, self.lexical_context_statements, self.extern_context)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func update(withContextStatements stmts: [AST.AnStatement]?) -> ASTCompilerContext {
|
public func update(withContextStatements stmts: CST.Statements?) -> CSTCompilerContext {
|
||||||
return ASTCompilerContext(self.lexical_context_name, stmts, self.extern_context)
|
return CSTCompilerContext(self.lexical_context_name, stmts, self.extern_context)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func update(withExtern extern: Bool) -> ASTCompilerContext {
|
public func update(withExtern extern: Bool) -> CSTCompilerContext {
|
||||||
return ASTCompilerContext(self.lexical_context_name, self.lexical_context_statements, extern)
|
return CSTCompilerContext(self.lexical_context_name, self.lexical_context_statements, extern)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,6 +26,6 @@ extension Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@attached(member, names: named(CompileStatement))
|
@attached(member, names: named(ParseStatement))
|
||||||
public macro deriveCompilableStatement() =
|
public macro deriveParsableStatement() =
|
||||||
#externalMacro(module: "Macros", type: "DeriveCompilableStatement")
|
#externalMacro(module: "Macros", type: "DeriveParsableStatement")
|
||||||
@@ -33,3 +33,25 @@ public func ConfigureP4Parser() -> Result<SwiftTreeSitter.Parser> {
|
|||||||
|
|
||||||
return .Ok(p)
|
return .Ok(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func compile(_ s: String) -> Result<CST.Program> {
|
||||||
|
let maybe_parser = ConfigureP4Parser()
|
||||||
|
guard case .Ok(let p) = maybe_parser else {
|
||||||
|
return .Error(maybe_parser.error()!)
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = p.parse(s)
|
||||||
|
guard let tree = result,
|
||||||
|
!tree.isError(lang: p4lang),
|
||||||
|
!tree.containsMissing(lang: p4lang)
|
||||||
|
else {
|
||||||
|
return Result.Error(Error(withMessage: "Could not parse the P4 program"))
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let root = tree.rootNode else {
|
||||||
|
return Result.Error(Error(withMessage: "No P4 program compiled"))
|
||||||
|
}
|
||||||
|
|
||||||
|
let compilation_context = CSTCompilerContext()
|
||||||
|
return CST.Program.Parse(node: root, withContext: compilation_context)
|
||||||
|
}
|
||||||
+254
-228
File diff suppressed because it is too large
Load Diff
@@ -19,31 +19,31 @@ import Common
|
|||||||
import SwiftTreeSitter
|
import SwiftTreeSitter
|
||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
extension AST.Identifier: CompilableExpression {
|
extension CST.Identifier: ParsableExpression {
|
||||||
public static func CompileExpression(
|
public static func ParseExpression(
|
||||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnExpression> {
|
) -> Result<CST.AnExpression> {
|
||||||
|
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: node, type: "identifier", nice_type_name: "Identifier")
|
node: node, type: "identifier", nice_type_name: "Identifier")
|
||||||
|
|
||||||
/// TODO: If there is a value here, then we can make this a compile-time constant!
|
/// TODO: If there is a value here, then we can make this a compile-time constant!
|
||||||
return .Ok(AST.Identifier(Common.Identifier(name: node.text!)))
|
return .Ok(CST.Identifier(Common.Identifier(name: node.text!)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension P4BooleanValue: CompilableExpression {
|
extension P4BooleanValue: ParsableExpression {
|
||||||
public static func CompileExpression(
|
public static func ParseExpression(
|
||||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnExpression> {
|
) -> Result<CST.AnExpression> {
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: node, type: "booleanLiteralExpression", nice_type_name: "Boolean Literal Expression")
|
node: node, type: "booleanLiteralExpression", nice_type_name: "Boolean Literal Expression")
|
||||||
|
|
||||||
if node.text == "false" {
|
if node.text == "false" {
|
||||||
return .Ok(AST.Literal(P4Value(P4BooleanValue(withValue: false))))
|
return .Ok(CST.Literal(P4Value(P4BooleanValue(withValue: false))))
|
||||||
} else if node.text == "true" {
|
} else if node.text == "true" {
|
||||||
return .Ok(AST.Literal(P4Value(P4BooleanValue(withValue: true))))
|
return .Ok(CST.Literal(P4Value(P4BooleanValue(withValue: true))))
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Error(
|
return .Error(
|
||||||
@@ -53,13 +53,13 @@ extension P4BooleanValue: CompilableExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension P4IntValue: CompilableExpression {
|
extension P4IntValue: ParsableExpression {
|
||||||
public static func CompileExpression(
|
public static func ParseExpression(
|
||||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnExpression> {
|
) -> Result<CST.AnExpression> {
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
|
|
||||||
#RequireNodesType<Node, AST.AnExpression>(
|
#RequireNodesType<Node, CST.AnExpression>(
|
||||||
nodes: node, type: ["integer", "integer_elaborated"],
|
nodes: node, type: ["integer", "integer_elaborated"],
|
||||||
nice_type_names: ["Integer", "Elaborated Integer"])
|
nice_type_names: ["Integer", "Elaborated Integer"])
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ extension P4IntValue: CompilableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let parsed_int = Int(value_source) {
|
if let parsed_int = Int(value_source) {
|
||||||
return .Ok(AST.Literal(P4Value(P4IntValue(withValue: parsed_int, andWidth: bit_width))))
|
return .Ok(CST.Literal(P4Value(P4IntValue(withValue: parsed_int, andWidth: bit_width))))
|
||||||
} else {
|
} else {
|
||||||
return .Error(
|
return .Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
@@ -103,43 +103,43 @@ extension P4IntValue: CompilableExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension P4StringValue: CompilableExpression {
|
extension P4StringValue: ParsableExpression {
|
||||||
public static func CompileExpression(
|
public static func ParseExpression(
|
||||||
node: SwiftTreeSitter.Node, withContext scopes: ASTCompilerContext
|
node: SwiftTreeSitter.Node, withContext scopes: CSTCompilerContext
|
||||||
) -> Result<AST.AnExpression> {
|
) -> Result<CST.AnExpression> {
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: node, type: "string_literal", nice_type_name: "String Literal")
|
node: node, type: "string_literal", nice_type_name: "String Literal")
|
||||||
return .Ok(AST.Literal(P4Value(P4StringValue(withValue: node.text!))))
|
return .Ok(CST.Literal(P4Value(P4StringValue(withValue: node.text!))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AST.Expression: Compilable {
|
extension CST.Expression: Parsable {
|
||||||
public static func Compile(
|
public static func Parse(
|
||||||
node: Node, withContext context: ASTCompilerContext
|
node: Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnExpression> {
|
) -> Result<CST.AnExpression> {
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: node, type: "expression", nice_type_name: "expression")
|
node: node, type: "expression", nice_type_name: "expression")
|
||||||
|
|
||||||
let expression_node = node.child(at: 0)!
|
let expression_node = node.child(at: 0)!
|
||||||
#RequireNodesType<Node, AST.AnExpression>(
|
#RequireNodesType<Node, CST.AnExpression>(
|
||||||
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
|
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
|
||||||
nice_type_names: ["grouped expression", "simple expression"])
|
nice_type_names: ["grouped expression", "simple expression"])
|
||||||
|
|
||||||
// If this is a grouped expression, recurse!
|
// If this is a grouped expression, recurse!
|
||||||
if expression_node.nodeType == "grouped_expression" {
|
if expression_node.nodeType == "grouped_expression" {
|
||||||
return AST.Expression.Compile(node: expression_node.child(at: 1)!, withContext: context)
|
return CST.Expression.Parse(node: expression_node.child(at: 1)!, withContext: context)
|
||||||
}
|
}
|
||||||
|
|
||||||
let expression_parsers: [CompilableExpression.Type] = [
|
let expression_parsers: [ParsableExpression.Type] = [
|
||||||
P4BooleanValue.self, P4StringValue.self, P4IntValue.self, AST.Identifier.self,
|
P4BooleanValue.self, P4StringValue.self, P4IntValue.self, CST.Identifier.self,
|
||||||
AST.BinaryOperatorExpression.self, AST.ArrayAccessExpression.self,
|
CST.BinaryOperatorExpression.self, CST.ArrayAccessExpression.self,
|
||||||
AST.FieldAccessExpression.self,
|
CST.FieldAccessExpression.self,
|
||||||
AST.FunctionCall.self,
|
CST.FunctionCall.self,
|
||||||
]
|
]
|
||||||
|
|
||||||
for candidate_expression_parser in expression_parsers {
|
for candidate_expression_parser in expression_parsers {
|
||||||
switch candidate_expression_parser.CompileExpression(
|
switch candidate_expression_parser.ParseExpression(
|
||||||
node: expression_node, withContext: context)
|
node: expression_node, withContext: context)
|
||||||
{
|
{
|
||||||
case .Ok(let parsed): return .Ok(parsed)
|
case .Ok(let parsed): return .Ok(parsed)
|
||||||
@@ -151,37 +151,37 @@ extension AST.Expression: Compilable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AST.KeysetExpression: CompilableExpression {
|
extension CST.KeysetExpression: ParsableExpression {
|
||||||
public static func CompileExpression(
|
public static func ParseExpression(
|
||||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnExpression> {
|
) -> Result<CST.AnExpression> {
|
||||||
let keyset_expression_node = node.child(at: 0)!
|
let keyset_expression_node = node.child(at: 0)!
|
||||||
|
|
||||||
#RequireNodesType<Node, AST.AnExpression>(
|
#RequireNodesType<Node, CST.AnExpression>(
|
||||||
nodes: keyset_expression_node, type: ["expression", "default_keyset"],
|
nodes: keyset_expression_node, type: ["expression", "default_keyset"],
|
||||||
nice_type_names: ["expression", "default keyset"])
|
nice_type_names: ["expression", "default keyset"])
|
||||||
|
|
||||||
// If there is a default keyset, that's easy!
|
// If there is a default keyset, that's easy!
|
||||||
if keyset_expression_node.nodeType == "default_keyset" {
|
if keyset_expression_node.nodeType == "default_keyset" {
|
||||||
return .Ok(AST.KeysetExpression.Default)
|
return .Ok(CST.KeysetExpression.Default)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile the expression:
|
// Compile the expression:
|
||||||
let maybe_compiled_set_expression = AST.Expression.Compile(
|
let maybe_compiled_set_expression = CST.Expression.Parse(
|
||||||
node: keyset_expression_node, withContext: context)
|
node: keyset_expression_node, withContext: context)
|
||||||
guard case .Ok(let compiled_expression) = maybe_compiled_set_expression else {
|
guard case .Ok(let compiled_expression) = maybe_compiled_set_expression else {
|
||||||
return .Error(maybe_compiled_set_expression.error()!)
|
return .Error(maybe_compiled_set_expression.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok(AST.KeysetExpression.Value(compiled_expression))
|
return .Ok(CST.KeysetExpression.Value(compiled_expression))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AST.SelectExpression: CompilableExpression {
|
extension CST.SelectExpression: ParsableExpression {
|
||||||
public static func CompileExpression(
|
public static func ParseExpression(
|
||||||
node: Node, withContext context: ASTCompilerContext
|
node: Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnExpression> {
|
) -> Result<CST.AnExpression> {
|
||||||
#RequireNodeType<Node, (AST.SelectExpression, ASTCompilerContext)>(
|
#RequireNodeType<Node, (CST.SelectExpression, CSTCompilerContext)>(
|
||||||
node: node, type: "selectExpression", nice_type_name: "parser select expression")
|
node: node, type: "selectExpression", nice_type_name: "parser select expression")
|
||||||
|
|
||||||
guard let selector_node = node.child(at: 2),
|
guard let selector_node = node.child(at: 2),
|
||||||
@@ -201,7 +201,7 @@ extension AST.SelectExpression: CompilableExpression {
|
|||||||
withError: "Could not find select expression body"))
|
withError: "Could not find select expression body"))
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_selector = AST.Expression.Compile(node: selector_node, withContext: context)
|
let maybe_selector = CST.Expression.Parse(node: selector_node, withContext: context)
|
||||||
guard case .Ok(let selector) = maybe_selector else {
|
guard case .Ok(let selector) = maybe_selector else {
|
||||||
return .Error(
|
return .Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
@@ -211,14 +211,14 @@ extension AST.SelectExpression: CompilableExpression {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
var sces: [AST.SelectCaseExpression] = Array()
|
var sces: [CST.SelectCaseExpression] = Array()
|
||||||
var sces_errors: (any Errorable)? = .none
|
var sces_errors: (any Errorable)? = .none
|
||||||
|
|
||||||
select_body_node.enumerateNamedChildren { current_node in
|
select_body_node.enumerateNamedChildren { current_node in
|
||||||
let maybe_parsed_cse = AST.SelectCaseExpression.CompileExpression(
|
let maybe_parsed_cse = CST.SelectCaseExpression.ParseExpression(
|
||||||
node: current_node, withContext: context)
|
node: current_node, withContext: context)
|
||||||
switch maybe_parsed_cse {
|
switch maybe_parsed_cse {
|
||||||
case .Ok(let parsed_cse): sces.append(parsed_cse as! AST.SelectCaseExpression)
|
case .Ok(let parsed_cse): sces.append(parsed_cse as! CST.SelectCaseExpression)
|
||||||
case .Error(let e):
|
case .Error(let e):
|
||||||
sces_errors =
|
sces_errors =
|
||||||
if let sces_errors = sces_errors {
|
if let sces_errors = sces_errors {
|
||||||
@@ -234,17 +234,17 @@ extension AST.SelectExpression: CompilableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return .Ok(
|
return .Ok(
|
||||||
AST.SelectExpression(withSelector: selector, withSelectCaseExpressions: sces),
|
CST.SelectExpression(withSelector: selector, withSelectCaseExpressions: sces),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AST.SelectCaseExpression: CompilableExpression {
|
extension CST.SelectCaseExpression: ParsableExpression {
|
||||||
public static func CompileExpression(
|
public static func ParseExpression(
|
||||||
node: Node, withContext context: ASTCompilerContext
|
node: Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnExpression> {
|
) -> Result<CST.AnExpression> {
|
||||||
|
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: node, type: "selectCase", nice_type_name: "Select Case")
|
node: node, type: "selectCase", nice_type_name: "Select Case")
|
||||||
|
|
||||||
guard let keysetexpression_node = node.child(at: 0),
|
guard let keysetexpression_node = node.child(at: 0),
|
||||||
@@ -259,34 +259,34 @@ extension AST.SelectCaseExpression: CompilableExpression {
|
|||||||
return Result.Error(Error(withMessage: "Missing target state in select case"))
|
return Result.Error(Error(withMessage: "Missing target state in select case"))
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_parsed_keysetexpression = AST.KeysetExpression.CompileExpression(
|
let maybe_parsed_keysetexpression = CST.KeysetExpression.ParseExpression(
|
||||||
node: keysetexpression_node, withContext: context)
|
node: keysetexpression_node, withContext: context)
|
||||||
guard case Result.Ok(let maybe_keysetexpression) = maybe_parsed_keysetexpression else {
|
guard case Result.Ok(let maybe_keysetexpression) = maybe_parsed_keysetexpression else {
|
||||||
return Result.Error(maybe_parsed_keysetexpression.error()!)
|
return Result.Error(maybe_parsed_keysetexpression.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
let keysetexpression = maybe_keysetexpression as! AST.KeysetExpression
|
let keysetexpression = maybe_keysetexpression as! CST.KeysetExpression
|
||||||
|
|
||||||
let maybe_parsed_targetstate = AST.Identifier.CompileExpression(
|
let maybe_parsed_targetstate = CST.Identifier.ParseExpression(
|
||||||
node: targetstate_node, withContext: context)
|
node: targetstate_node, withContext: context)
|
||||||
guard case .Ok(let targetstate) = maybe_parsed_targetstate else {
|
guard case .Ok(let targetstate) = maybe_parsed_targetstate else {
|
||||||
return Result.Error(maybe_parsed_targetstate.error()!)
|
return Result.Error(maybe_parsed_targetstate.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok(
|
return .Ok(
|
||||||
AST.SelectCaseExpression(
|
CST.SelectCaseExpression(
|
||||||
withKey: keysetexpression, withNextState: targetstate as! AST.Identifier)
|
withKey: keysetexpression, withNextState: targetstate as! CST.Identifier)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AST.BinaryOperatorExpression: CompilableExpression {
|
extension CST.BinaryOperatorExpression: ParsableExpression {
|
||||||
public static func CompileExpression(
|
public static func ParseExpression(
|
||||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnExpression> {
|
) -> Result<CST.AnExpression> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
|
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: expression, type: "binaryOperatorExpression",
|
node: expression, type: "binaryOperatorExpression",
|
||||||
nice_type_name: "Binary Operator Expression")
|
nice_type_name: "Binary Operator Expression")
|
||||||
let binary_operator_expression_node = expression.child(at: 0)!
|
let binary_operator_expression_node = expression.child(at: 0)!
|
||||||
@@ -295,20 +295,20 @@ extension AST.BinaryOperatorExpression: CompilableExpression {
|
|||||||
var current_node: Node? = .none
|
var current_node: Node? = .none
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnExpression>.Error(
|
or: Result<CST.AnExpression>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Malformed binary operator expression"
|
sourceLocation: node.toSourceLocation(), withError: "Malformed binary operator expression"
|
||||||
)))
|
)))
|
||||||
|
|
||||||
/// TODO: This macro cannot handle new lines in the arrays
|
/// TODO: This macro cannot handle new lines in the arrays
|
||||||
// swift-format-ignore
|
// swift-format-ignore
|
||||||
#RequireNodesType<Node, AST.AnExpression>(
|
#RequireNodesType<Node, CST.AnExpression>(
|
||||||
nodes: binary_operator_expression_node,
|
nodes: binary_operator_expression_node,
|
||||||
type: ["binaryEqualOperatorExpression", "binaryLessThanOperatorExpression", "binaryLessThanEqualOperatorExpression", "binaryGreaterThanOperatorExpression", "binaryGreaterThanEqualOperatorExpression", "binaryAndOperatorExpression", "binaryOrOperatorExpression", "binaryAddOperatorExpression", "binarySubtractOperatorExpression", "binaryMultiplyOperatorExpression", "binaryDivideOperatorExpression"],
|
type: ["binaryEqualOperatorExpression", "binaryLessThanOperatorExpression", "binaryLessThanEqualOperatorExpression", "binaryGreaterThanOperatorExpression", "binaryGreaterThanEqualOperatorExpression", "binaryAndOperatorExpression", "binaryOrOperatorExpression", "binaryAddOperatorExpression", "binarySubtractOperatorExpression", "binaryMultiplyOperatorExpression", "binaryDivideOperatorExpression"],
|
||||||
nice_type_names: [ "binary equal operator", "binary less than operator", "binary less than or equal to operator", "binary greater than operator", "binary greater than or equal to operator", "binary and operator", "binary or operator", "binary add operator", "binary subtract operator", "binary multiply operator", "binary divide operator"])
|
nice_type_names: [ "binary equal operator", "binary less than operator", "binary less than or equal to operator", "binary greater than operator", "binary greater than or equal to operator", "binary and operator", "binary or operator", "binary add operator", "binary subtract operator", "binary multiply operator", "binary divide operator"])
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnExpression>.Error(
|
or: Result<CST.AnExpression>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing LHS for binary operator expression")))
|
withError: "Missing LHS for binary operator expression")))
|
||||||
@@ -318,7 +318,7 @@ extension AST.BinaryOperatorExpression: CompilableExpression {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnExpression>.Error(
|
or: Result<CST.AnExpression>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing binary operator for binary operator expression")))
|
withError: "Missing binary operator for binary operator expression")))
|
||||||
@@ -326,69 +326,69 @@ extension AST.BinaryOperatorExpression: CompilableExpression {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnExpression>.Error(
|
or: Result<CST.AnExpression>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing RHS for binary operator expression")))
|
withError: "Missing RHS for binary operator expression")))
|
||||||
|
|
||||||
let right_hand_side_raw = current_node!
|
let right_hand_side_raw = current_node!
|
||||||
|
|
||||||
let maybe_left_hand_side = AST.Expression.Compile(
|
let maybe_left_hand_side = CST.Expression.Parse(
|
||||||
node: left_hand_side_raw, withContext: context)
|
node: left_hand_side_raw, withContext: context)
|
||||||
guard case Result.Ok(let left_hand_side) = maybe_left_hand_side else {
|
guard case Result.Ok(let left_hand_side) = maybe_left_hand_side else {
|
||||||
return Result.Error(maybe_left_hand_side.error()!)
|
return Result.Error(maybe_left_hand_side.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_right_hand_side = AST.Expression.Compile(
|
let maybe_right_hand_side = CST.Expression.Parse(
|
||||||
node: right_hand_side_raw, withContext: context)
|
node: right_hand_side_raw, withContext: context)
|
||||||
guard case Result.Ok(let right_hand_side) = maybe_right_hand_side else {
|
guard case Result.Ok(let right_hand_side) = maybe_right_hand_side else {
|
||||||
return Result.Error(maybe_right_hand_side.error()!)
|
return Result.Error(maybe_right_hand_side.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
let evaluators: [String: (String, P4QualifiedType, AST.BinaryOperatorExpressionType)] = [
|
let evaluators: [String: (String, P4QualifiedType, CST.BinaryOperatorExpressionType)] = [
|
||||||
"binaryEqualOperatorExpression": (
|
"binaryEqualOperatorExpression": (
|
||||||
"Binary Equal", P4QualifiedType(P4Boolean()),
|
"Binary Equal", P4QualifiedType(P4Boolean()),
|
||||||
AST.BinaryOperatorExpressionType.Eq
|
CST.BinaryOperatorExpressionType.Eq
|
||||||
),
|
),
|
||||||
"binaryLessThanOperatorExpression": (
|
"binaryLessThanOperatorExpression": (
|
||||||
"Binary Less Than", P4QualifiedType(P4Boolean()),
|
"Binary Less Than", P4QualifiedType(P4Boolean()),
|
||||||
AST.BinaryOperatorExpressionType.Lt
|
CST.BinaryOperatorExpressionType.Lt
|
||||||
),
|
),
|
||||||
"binaryLessThanEqualOperatorExpression": (
|
"binaryLessThanEqualOperatorExpression": (
|
||||||
"Binary Less Than Or Equal", P4QualifiedType(P4Boolean()),
|
"Binary Less Than Or Equal", P4QualifiedType(P4Boolean()),
|
||||||
AST.BinaryOperatorExpressionType.Lte
|
CST.BinaryOperatorExpressionType.Lte
|
||||||
),
|
),
|
||||||
"binaryGreaterThanOperatorExpression": (
|
"binaryGreaterThanOperatorExpression": (
|
||||||
"Binary Greater Than", P4QualifiedType(P4Boolean()),
|
"Binary Greater Than", P4QualifiedType(P4Boolean()),
|
||||||
AST.BinaryOperatorExpressionType.Gt
|
CST.BinaryOperatorExpressionType.Gt
|
||||||
),
|
),
|
||||||
"binaryGreaterThanEqualOperatorExpression": (
|
"binaryGreaterThanEqualOperatorExpression": (
|
||||||
"Binary Greater Than Or Equal", P4QualifiedType(P4Boolean()),
|
"Binary Greater Than Or Equal", P4QualifiedType(P4Boolean()),
|
||||||
AST.BinaryOperatorExpressionType.Gte
|
CST.BinaryOperatorExpressionType.Gte
|
||||||
),
|
),
|
||||||
"binaryAndOperatorExpression": (
|
"binaryAndOperatorExpression": (
|
||||||
"Binary Or", P4QualifiedType(P4Boolean()),
|
"Binary Or", P4QualifiedType(P4Boolean()),
|
||||||
AST.BinaryOperatorExpressionType.And
|
CST.BinaryOperatorExpressionType.And
|
||||||
),
|
),
|
||||||
"binaryOrOperatorExpression": (
|
"binaryOrOperatorExpression": (
|
||||||
"Binary And", P4QualifiedType(P4Boolean()),
|
"Binary And", P4QualifiedType(P4Boolean()),
|
||||||
AST.BinaryOperatorExpressionType.Or
|
CST.BinaryOperatorExpressionType.Or
|
||||||
),
|
),
|
||||||
"binaryAddOperatorExpression": (
|
"binaryAddOperatorExpression": (
|
||||||
"Binary Add", P4QualifiedType(P4Int()),
|
"Binary Add", P4QualifiedType(P4Int()),
|
||||||
AST.BinaryOperatorExpressionType.Add
|
CST.BinaryOperatorExpressionType.Add
|
||||||
),
|
),
|
||||||
"binarySubtractOperatorExpression": (
|
"binarySubtractOperatorExpression": (
|
||||||
"Binary Subtract", P4QualifiedType(P4Int()),
|
"Binary Subtract", P4QualifiedType(P4Int()),
|
||||||
AST.BinaryOperatorExpressionType.Subtract
|
CST.BinaryOperatorExpressionType.Subtract
|
||||||
),
|
),
|
||||||
"binaryMultiplyOperatorExpression": (
|
"binaryMultiplyOperatorExpression": (
|
||||||
"Binary Multiply", P4QualifiedType(P4Int()),
|
"Binary Multiply", P4QualifiedType(P4Int()),
|
||||||
AST.BinaryOperatorExpressionType.Multiply
|
CST.BinaryOperatorExpressionType.Multiply
|
||||||
),
|
),
|
||||||
"binaryDivideOperatorExpression": (
|
"binaryDivideOperatorExpression": (
|
||||||
"Binary Divide", P4QualifiedType(P4Int()),
|
"Binary Divide", P4QualifiedType(P4Int()),
|
||||||
AST.BinaryOperatorExpressionType.Divide
|
CST.BinaryOperatorExpressionType.Divide
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -398,19 +398,19 @@ extension AST.BinaryOperatorExpression: CompilableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return .Ok(
|
return .Ok(
|
||||||
AST.BinaryOperatorExpression(
|
CST.BinaryOperatorExpression(
|
||||||
withType: selected_evaluator.2,
|
withType: selected_evaluator.2,
|
||||||
withLhs: left_hand_side, withRhs: right_hand_side))
|
withLhs: left_hand_side, withRhs: right_hand_side))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AST.ArrayAccessExpression: CompilableExpression {
|
extension CST.ArrayAccessExpression: ParsableExpression {
|
||||||
public static func CompileExpression(
|
public static func ParseExpression(
|
||||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnExpression> {
|
) -> Result<CST.AnExpression> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
|
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: expression, type: "arrayAccessExpression", nice_type_name: "Array Access Expression")
|
node: expression, type: "arrayAccessExpression", nice_type_name: "Array Access Expression")
|
||||||
let array_access_expression_node = expression
|
let array_access_expression_node = expression
|
||||||
|
|
||||||
@@ -419,11 +419,11 @@ extension AST.ArrayAccessExpression: CompilableExpression {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnExpression>.Error(
|
or: Result<CST.AnExpression>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Malformed array access expression")))
|
sourceLocation: node.toSourceLocation(), withError: "Malformed array access expression")))
|
||||||
|
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: current_node!, type: "expression",
|
node: current_node!, type: "expression",
|
||||||
nice_type_name: "array identifier expression")
|
nice_type_name: "array identifier expression")
|
||||||
let array_access_identifier_node = current_node!
|
let array_access_identifier_node = current_node!
|
||||||
@@ -431,7 +431,7 @@ extension AST.ArrayAccessExpression: CompilableExpression {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnExpression>.Error(
|
or: Result<CST.AnExpression>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing [ for array access expression")))
|
withError: "Missing [ for array access expression")))
|
||||||
@@ -440,42 +440,42 @@ extension AST.ArrayAccessExpression: CompilableExpression {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnExpression>.Error(
|
or: Result<CST.AnExpression>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing indexor expression for array access expression")))
|
withError: "Missing indexor expression for array access expression")))
|
||||||
|
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: current_node!, type: "expression",
|
node: current_node!, type: "expression",
|
||||||
nice_type_name: "array indexor expression")
|
nice_type_name: "array indexor expression")
|
||||||
|
|
||||||
let array_access_indexor_node = current_node!
|
let array_access_indexor_node = current_node!
|
||||||
|
|
||||||
let maybe_array_identifier = AST.Expression.Compile(
|
let maybe_array_identifier = CST.Expression.Parse(
|
||||||
node: array_access_identifier_node, withContext: context)
|
node: array_access_identifier_node, withContext: context)
|
||||||
guard case Result.Ok(let array_identifier) = maybe_array_identifier else {
|
guard case Result.Ok(let array_identifier) = maybe_array_identifier else {
|
||||||
return Result.Error(maybe_array_identifier.error()!)
|
return Result.Error(maybe_array_identifier.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_array_indexor = AST.Expression.Compile(
|
let maybe_array_indexor = CST.Expression.Parse(
|
||||||
node: array_access_indexor_node, withContext: context)
|
node: array_access_indexor_node, withContext: context)
|
||||||
guard case Result.Ok(let array_indexor) = maybe_array_indexor else {
|
guard case Result.Ok(let array_indexor) = maybe_array_indexor else {
|
||||||
return Result.Error(maybe_array_indexor.error()!)
|
return Result.Error(maybe_array_indexor.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok(
|
return .Ok(
|
||||||
AST.ArrayAccessExpression(
|
CST.ArrayAccessExpression(
|
||||||
withName: array_identifier, withIndexor: array_indexor))
|
withName: array_identifier, withIndexor: array_indexor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AST.FieldAccessExpression: CompilableExpression {
|
extension CST.FieldAccessExpression: ParsableExpression {
|
||||||
public static func CompileExpression(
|
public static func ParseExpression(
|
||||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnExpression> {
|
) -> Result<CST.AnExpression> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
|
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: expression, type: "fieldAccessExpression", nice_type_name: "Array Access Expression")
|
node: expression, type: "fieldAccessExpression", nice_type_name: "Array Access Expression")
|
||||||
|
|
||||||
let field_access_expression_node = expression
|
let field_access_expression_node = expression
|
||||||
@@ -485,11 +485,11 @@ extension AST.FieldAccessExpression: CompilableExpression {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnExpression>.Error(
|
or: Result<CST.AnExpression>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Malformed field access expression")))
|
sourceLocation: node.toSourceLocation(), withError: "Malformed field access expression")))
|
||||||
|
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: current_node!, type: "expression",
|
node: current_node!, type: "expression",
|
||||||
nice_type_name: "struct identifier expression")
|
nice_type_name: "struct identifier expression")
|
||||||
let struct_identifier_node = current_node!
|
let struct_identifier_node = current_node!
|
||||||
@@ -497,7 +497,7 @@ extension AST.FieldAccessExpression: CompilableExpression {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnExpression>.Error(
|
or: Result<CST.AnExpression>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing . for field access expression")))
|
withError: "Missing . for field access expression")))
|
||||||
@@ -505,44 +505,44 @@ extension AST.FieldAccessExpression: CompilableExpression {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnExpression>.Error(
|
or: Result<CST.AnExpression>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing field name for field access expression")))
|
withError: "Missing field name for field access expression")))
|
||||||
|
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: current_node!, type: "identifier",
|
node: current_node!, type: "identifier",
|
||||||
nice_type_name: "field name")
|
nice_type_name: "field name")
|
||||||
|
|
||||||
let field_name_node = current_node!
|
let field_name_node = current_node!
|
||||||
|
|
||||||
// Make sure that the identifier really identifies a struct.
|
// Make sure that the identifier really identifies a struct.
|
||||||
let maybe_struct_identifier = AST.Expression.Compile(
|
let maybe_struct_identifier = CST.Expression.Parse(
|
||||||
node: struct_identifier_node, withContext: context)
|
node: struct_identifier_node, withContext: context)
|
||||||
guard case Result.Ok(let struct_identifier) = maybe_struct_identifier else {
|
guard case Result.Ok(let struct_identifier) = maybe_struct_identifier else {
|
||||||
return Result.Error(maybe_struct_identifier.error()!)
|
return Result.Error(maybe_struct_identifier.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_field_name = AST.Identifier.CompileExpression(
|
let maybe_field_name = CST.Identifier.ParseExpression(
|
||||||
node: field_name_node, withContext: context)
|
node: field_name_node, withContext: context)
|
||||||
guard case Result.Ok(let field_name) = maybe_field_name else {
|
guard case Result.Ok(let field_name) = maybe_field_name else {
|
||||||
return Result.Error(maybe_field_name.error()!)
|
return Result.Error(maybe_field_name.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok(
|
return .Ok(
|
||||||
AST.FieldAccessExpression(
|
CST.FieldAccessExpression(
|
||||||
withStruct: struct_identifier,
|
withStruct: struct_identifier,
|
||||||
withField: field_name as! AST.Identifier))
|
withField: field_name as! CST.Identifier))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AST.FunctionCall: CompilableExpression {
|
extension CST.FunctionCall: ParsableExpression {
|
||||||
public static func CompileExpression(
|
public static func ParseExpression(
|
||||||
node: Node, withContext context: ASTCompilerContext
|
node: Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnExpression> {
|
) -> Result<CST.AnExpression> {
|
||||||
|
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
#RequireNodeType<Node, AST.AnExpression>(
|
#RequireNodeType<Node, CST.AnExpression>(
|
||||||
node: expression, type: "function_call", nice_type_name: "Function Call")
|
node: expression, type: "function_call", nice_type_name: "Function Call")
|
||||||
|
|
||||||
var walker = Walker(node: expression)
|
var walker = Walker(node: expression)
|
||||||
@@ -550,11 +550,11 @@ extension AST.FunctionCall: CompilableExpression {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnExpression>.Error(
|
or: Result<CST.AnExpression>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
||||||
|
|
||||||
let maybe_callee_name = AST.Identifier.CompileExpression(
|
let maybe_callee_name = CST.Identifier.ParseExpression(
|
||||||
node: current_node!, withContext: context)
|
node: current_node!, withContext: context)
|
||||||
guard case .Ok(let callee_name) = maybe_callee_name else {
|
guard case .Ok(let callee_name) = maybe_callee_name else {
|
||||||
return Result.Error(maybe_callee_name.error()!)
|
return Result.Error(maybe_callee_name.error()!)
|
||||||
@@ -563,15 +563,15 @@ extension AST.FunctionCall: CompilableExpression {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnExpression>.Error(
|
or: Result<CST.AnExpression>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
||||||
|
|
||||||
let maybe_argument_list = AST.ArgumentList.Compile(node: current_node!, withContext: context)
|
let maybe_argument_list = CST.ArgumentList.Parse(node: current_node!, withContext: context)
|
||||||
|
|
||||||
guard case .Ok(let arguments) = maybe_argument_list else {
|
guard case .Ok(let arguments) = maybe_argument_list else {
|
||||||
return .Error(maybe_argument_list.error()!)
|
return .Error(maybe_argument_list.error()!)
|
||||||
}
|
}
|
||||||
return .Ok(AST.FunctionCall(callee_name as! AST.Identifier, withArguments: arguments))
|
return .Ok(CST.FunctionCall(callee_name as! CST.Identifier, withArguments: arguments))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,55 +20,13 @@ import SwiftTreeSitter
|
|||||||
import TreeSitterExtensions
|
import TreeSitterExtensions
|
||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
extension AST.Statement: Compilable {
|
extension CST.LocalElements: Parsable {
|
||||||
public typealias C = AST.AnStatement
|
public typealias C = CST.Statement
|
||||||
public static func Compile(
|
public static func Parse(
|
||||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
node: Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnStatement> {
|
) -> Result<CST.Statement> {
|
||||||
|
let localElementsParsers: [String: ParsableStatement.Type] = [
|
||||||
if node.nodeType != "parserStatement" && node.nodeType != "statement" {
|
"variableDeclaration": CST.VariableDeclarationStatement.self
|
||||||
return Result.Error(
|
|
||||||
ErrorWithLocation(
|
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing expected parser statement")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
let statement = node.child(at: 0)!
|
|
||||||
|
|
||||||
let statementParsers: [String: CompilableStatement.Type] = [
|
|
||||||
"assignmentStatement": AST.ParserAssignmentStatement.self,
|
|
||||||
"expressionStatement": AST.ExpressionStatement.self,
|
|
||||||
"variableDeclaration": AST.VariableDeclarationStatement.self,
|
|
||||||
"conditionalStatement": AST.ConditionalStatement.self,
|
|
||||||
"blockStatement": AST.BlockStatement.self,
|
|
||||||
"return_statement": AST.ReturnStatement.self,
|
|
||||||
]
|
|
||||||
guard let parser = statementParsers[statement.nodeType ?? ""] else {
|
|
||||||
return Result.Error(
|
|
||||||
ErrorWithLocation(
|
|
||||||
sourceLocation: statement.toSourceLocation(),
|
|
||||||
withError:
|
|
||||||
"Unparseable statement type (\(statement.nodeType ?? "Unknown Statement Type"))"))
|
|
||||||
}
|
|
||||||
switch parser.CompileStatement(node: statement, withContext: context) {
|
|
||||||
case Result.Ok(let parsed):
|
|
||||||
return .Ok(parsed)
|
|
||||||
case Result.Error(let e):
|
|
||||||
return .Error(
|
|
||||||
ErrorWithLocation(
|
|
||||||
sourceLocation: node.toSourceLocation(),
|
|
||||||
withError: "Failed to parse a statement element: \(e)"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AST.LocalElements: Compilable {
|
|
||||||
public typealias C = AST.AnStatement
|
|
||||||
public static func Compile(
|
|
||||||
node: Node, withContext context: ASTCompilerContext
|
|
||||||
) -> Result<AST.AnStatement> {
|
|
||||||
let localElementsParsers: [String: CompilableStatement.Type] = [
|
|
||||||
"variableDeclaration": AST.VariableDeclarationStatement.self
|
|
||||||
]
|
]
|
||||||
|
|
||||||
guard let parser = localElementsParsers[node.nodeType ?? ""] else {
|
guard let parser = localElementsParsers[node.nodeType ?? ""] else {
|
||||||
@@ -78,7 +36,7 @@ extension AST.LocalElements: Compilable {
|
|||||||
withError: "Unparseable statement type (\(node.nodeType ?? "Unknown Statement Type"))"))
|
withError: "Unparseable statement type (\(node.nodeType ?? "Unknown Statement Type"))"))
|
||||||
}
|
}
|
||||||
|
|
||||||
switch parser.CompileStatement(node: node, withContext: context) {
|
switch parser.ParseStatement(node: node, withContext: context) {
|
||||||
case Result.Ok(let parsed):
|
case Result.Ok(let parsed):
|
||||||
return Result.Ok(parsed)
|
return Result.Ok(parsed)
|
||||||
case Result.Error(let e):
|
case Result.Error(let e):
|
||||||
@@ -87,11 +45,11 @@ extension AST.LocalElements: Compilable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AST.ParserState: Compilable {
|
extension CST.ParserState: Parsable {
|
||||||
public typealias C = AST.AnState
|
public typealias C = CST.AnState
|
||||||
public static func Compile(
|
public static func Parse(
|
||||||
node: Node, withContext context: ASTCompilerContext
|
node: Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.AnState> {
|
) -> Result<CST.AnState> {
|
||||||
var walker = Walker(node: node)
|
var walker = Walker(node: node)
|
||||||
|
|
||||||
var current_node: Node? = .none
|
var current_node: Node? = .none
|
||||||
@@ -107,7 +65,7 @@ extension AST.ParserState: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnState>.Error(
|
or: Result<CST.AnState>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing elements in parser state declaration")))
|
withError: "Missing elements in parser state declaration")))
|
||||||
@@ -125,12 +83,12 @@ extension AST.ParserState: Compilable {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnState>.Error(
|
or: Result<CST.AnState>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing elements in parser state declaration")))
|
withError: "Missing elements in parser state declaration")))
|
||||||
|
|
||||||
let maybe_state_identifier = AST.Identifier.CompileExpression(
|
let maybe_state_identifier = CST.Identifier.ParseExpression(
|
||||||
node: current_node!, withContext: context)
|
node: current_node!, withContext: context)
|
||||||
guard case Result.Ok(let state_identifier) = maybe_state_identifier else {
|
guard case Result.Ok(let state_identifier) = maybe_state_identifier else {
|
||||||
return Result.Error(maybe_state_identifier.error()!)
|
return Result.Error(maybe_state_identifier.error()!)
|
||||||
@@ -141,16 +99,16 @@ extension AST.ParserState: Compilable {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnState>.Error(
|
or: Result<CST.AnState>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing body of state declaration")
|
sourceLocation: node.toSourceLocation(), withError: "Missing body of state declaration")
|
||||||
))
|
))
|
||||||
|
|
||||||
var errors: (any Errorable)? = .none
|
var errors: (any Errorable)? = .none
|
||||||
var parsed_s: [AST.AnStatement] = Array()
|
var parsed_s: CST.Statements? = .none
|
||||||
|
|
||||||
if current_node!.nodeType == "parserStatements" {
|
if current_node!.nodeType == "parserStatements" {
|
||||||
switch SpecialCompilers.Statements.Compile(
|
switch CST.Statements.Parse(
|
||||||
node: current_node!, withContext: context)
|
node: current_node!, withContext: context)
|
||||||
{
|
{
|
||||||
case .Ok(let state_statements):
|
case .Ok(let state_statements):
|
||||||
@@ -172,14 +130,14 @@ extension AST.ParserState: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.AnState>.Error(
|
or: Result<CST.AnState>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing transition statement of state declaration")))
|
withError: "Missing transition statement of state declaration")))
|
||||||
|
|
||||||
let updated_context = context.update(withContextName: (state_identifier as! AST.Identifier))
|
let updated_context = context.update(withContextName: (state_identifier as! CST.Identifier))
|
||||||
.update(withContextStatements: parsed_s)
|
.update(withContextStatements: parsed_s)
|
||||||
|
|
||||||
return AST.TransitionStatement.Compile(node: current_node!, withContext: updated_context)
|
return CST.TransitionStatement.Parse(node: current_node!, withContext: updated_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// 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 SwiftTreeSitter
|
||||||
|
|
||||||
|
extension CST.Program: Parsable {
|
||||||
|
public typealias C = CST.Program
|
||||||
|
public static func Parse(
|
||||||
|
node: Node, withContext context: CSTCompilerContext
|
||||||
|
) -> Common.Result<CST.Program> {
|
||||||
|
|
||||||
|
var statements: [CST.Statement] = Array()
|
||||||
|
|
||||||
|
var errors: (any Errorable)? = .none
|
||||||
|
|
||||||
|
// Try to parse all top-level declarations.
|
||||||
|
node.enumerateNamedChildren { (declaration_node: Node) in
|
||||||
|
let declaration_parsers: [String: ParsableStatement.Type] = [
|
||||||
|
"declaration": CST.Declaration.self,
|
||||||
|
"instantiation": CST.Instantiation.self,
|
||||||
|
]
|
||||||
|
|
||||||
|
if let parser = declaration_parsers[declaration_node.nodeType!] {
|
||||||
|
let r = parser.ParseStatement(node: declaration_node, withContext: context)
|
||||||
|
switch r {
|
||||||
|
case .Ok(let compiled):
|
||||||
|
statements.append(compiled)
|
||||||
|
case .Error(let e):
|
||||||
|
errors =
|
||||||
|
if let errors = errors {
|
||||||
|
errors.append(error: e)
|
||||||
|
} else {
|
||||||
|
e
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let e = ErrorWithLocation(
|
||||||
|
sourceLocation: declaration_node.toSourceLocation(),
|
||||||
|
withError:
|
||||||
|
"\(declaration_node.nodeType!) cannot be at a P4 program top level")
|
||||||
|
errors =
|
||||||
|
if let errors = errors {
|
||||||
|
errors.append(error: e)
|
||||||
|
} else {
|
||||||
|
e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let errors = errors {
|
||||||
|
return .Error(errors)
|
||||||
|
}
|
||||||
|
return Result.Ok(CST.Program(CST.Statements(statements)))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
// 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 SwiftTreeSitter
|
||||||
|
import TreeSitterExtensions
|
||||||
|
import TreeSitterP4
|
||||||
|
|
||||||
|
public struct SpecialParsers {
|
||||||
|
public struct Statement {}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SpecialParsers.Statement: Parsable {
|
||||||
|
public typealias C = CST.Statement
|
||||||
|
public static func Parse(
|
||||||
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
||||||
|
) -> Result<CST.Statement> {
|
||||||
|
|
||||||
|
if node.nodeType != "parserStatement" && node.nodeType != "statement" {
|
||||||
|
return Result.Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: node.toSourceLocation(), withError: "Missing expected parser statement")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let statement = node.child(at: 0)!
|
||||||
|
|
||||||
|
let statementParsers: [String: ParsableStatement.Type] = [
|
||||||
|
"assignmentStatement": CST.ParserAssignmentStatement.self,
|
||||||
|
"expressionStatement": CST.ExpressionStatement.self,
|
||||||
|
"variableDeclaration": CST.VariableDeclarationStatement.self,
|
||||||
|
"conditionalStatement": CST.ConditionalStatement.self,
|
||||||
|
"blockStatement": CST.BlockStatement.self,
|
||||||
|
"return_statement": CST.ReturnStatement.self,
|
||||||
|
]
|
||||||
|
guard let parser = statementParsers[statement.nodeType ?? ""] else {
|
||||||
|
return Result.Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: statement.toSourceLocation(),
|
||||||
|
withError:
|
||||||
|
"Unparseable statement type (\(statement.nodeType ?? "Unknown Statement Type"))"))
|
||||||
|
}
|
||||||
|
switch parser.ParseStatement(node: statement, withContext: context) {
|
||||||
|
case Result.Ok(let parsed):
|
||||||
|
return .Ok(parsed)
|
||||||
|
case Result.Error(let e):
|
||||||
|
return .Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: node.toSourceLocation(),
|
||||||
|
withError: "Failed to parse a statement element: \(e)"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,11 +20,11 @@ import SwiftTreeSitter
|
|||||||
import TreeSitterExtensions
|
import TreeSitterExtensions
|
||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
extension AST.BlockStatement: Compilable {
|
extension CST.BlockStatement: Parsable {
|
||||||
public typealias C = AST.BlockStatement
|
public typealias C = CST.BlockStatement
|
||||||
public static func Compile(
|
public static func Parse(
|
||||||
node: Node, withContext context: ASTCompilerContext
|
node: Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.BlockStatement> {
|
) -> Result<CST.BlockStatement> {
|
||||||
/*
|
/*
|
||||||
#RequireNodeType<Node, AST.BlockStatement>(
|
#RequireNodeType<Node, AST.BlockStatement>(
|
||||||
node: node, type: "blockStatement", nice_type_name: "block statement")
|
node: node, type: "blockStatement", nice_type_name: "block statement")
|
||||||
@@ -56,7 +56,7 @@ extension AST.BlockStatement: Compilable {
|
|||||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||||
|
|
||||||
if current_node!.nodeType == "statements" {
|
if current_node!.nodeType == "statements" {
|
||||||
switch SpecialCompilers.Statements.Compile(
|
switch SpecialCompilers.Statements.Parse(
|
||||||
node: current_node!, withContext: context)
|
node: current_node!, withContext: context)
|
||||||
{
|
{
|
||||||
case .Ok(let parsed_statements):
|
case .Ok(let parsed_statements):
|
||||||
@@ -87,20 +87,20 @@ extension AST.BlockStatement: Compilable {
|
|||||||
|
|
||||||
return .Ok(AST.BlockStatement(statements))
|
return .Ok(AST.BlockStatement(statements))
|
||||||
*/
|
*/
|
||||||
return .Ok(AST.BlockStatement([]))
|
return .Ok(CST.BlockStatement(CST.Statements([])))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@deriveCompilableStatement
|
@deriveParsableStatement
|
||||||
extension AST.BlockStatement: CompilableStatement {}
|
extension CST.BlockStatement: ParsableStatement {}
|
||||||
|
|
||||||
extension AST.ConditionalStatement: Compilable {
|
extension CST.ConditionalStatement: Parsable {
|
||||||
public typealias C = AST.ConditionalStatement
|
public typealias C = CST.ConditionalStatement
|
||||||
public static func Compile(
|
public static func Parse(
|
||||||
node: Node, withContext context: ASTCompilerContext
|
node: Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.ConditionalStatement> {
|
) -> Result<CST.ConditionalStatement> {
|
||||||
|
|
||||||
#RequireNodeType<Node, AST.ConditionalStatement>(
|
#RequireNodeType<Node, CST.ConditionalStatement>(
|
||||||
node: node, type: "conditionalStatement", nice_type_name: "conditional statement")
|
node: node, type: "conditionalStatement", nice_type_name: "conditional statement")
|
||||||
|
|
||||||
let maybe_condition_expression = node.child(at: 2)
|
let maybe_condition_expression = node.child(at: 2)
|
||||||
@@ -124,7 +124,7 @@ extension AST.ConditionalStatement: Compilable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok(let condition) = AST.Expression.Compile(
|
case .Ok(let condition) = CST.Expression.Parse(
|
||||||
node: condition_expression, withContext: context)
|
node: condition_expression, withContext: context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
@@ -132,7 +132,7 @@ extension AST.ConditionalStatement: Compilable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok(let thenns) = AST.Statement.Compile(
|
case .Ok(let thenns) = SpecialParsers.Statement.Parse(
|
||||||
node: thens, withContext: context)
|
node: thens, withContext: context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
@@ -141,10 +141,10 @@ extension AST.ConditionalStatement: Compilable {
|
|||||||
"Could not parse the then block in a conditional statement"))
|
"Could not parse the then block in a conditional statement"))
|
||||||
}
|
}
|
||||||
|
|
||||||
let optional_elss: Result<AST.AnStatement>? =
|
let optional_elss: Result<CST.Statement>? =
|
||||||
if let elss = node.child(at: 6) {
|
if let elss = node.child(at: 6) {
|
||||||
.some(
|
.some(
|
||||||
AST.Statement.Compile(
|
SpecialParsers.Statement.Parse(
|
||||||
node: elss, withContext: context))
|
node: elss, withContext: context))
|
||||||
} else {
|
} else {
|
||||||
.none
|
.none
|
||||||
@@ -160,22 +160,22 @@ extension AST.ConditionalStatement: Compilable {
|
|||||||
"Could not parse the else block in a conditional statement"))
|
"Could not parse the else block in a conditional statement"))
|
||||||
}
|
}
|
||||||
return .Ok(
|
return .Ok(
|
||||||
AST.ConditionalStatement(condition: condition, withThen: thenns, andElse: elss))
|
CST.ConditionalStatement(condition: condition, withThen: thenns, andElse: elss))
|
||||||
}
|
}
|
||||||
return .Ok(AST.ConditionalStatement(condition: condition, withThen: thenns))
|
return .Ok(CST.ConditionalStatement(condition: condition, withThen: thenns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@deriveCompilableStatement
|
@deriveParsableStatement
|
||||||
extension AST.ConditionalStatement: CompilableStatement {}
|
extension CST.ConditionalStatement: ParsableStatement {}
|
||||||
|
|
||||||
extension AST.VariableDeclarationStatement: Compilable {
|
extension CST.VariableDeclarationStatement: Parsable {
|
||||||
public typealias C = AST.VariableDeclarationStatement
|
public typealias C = CST.VariableDeclarationStatement
|
||||||
public static func Compile(
|
public static func Parse(
|
||||||
node: Node, withContext context: ASTCompilerContext
|
node: Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.VariableDeclarationStatement> {
|
) -> Result<CST.VariableDeclarationStatement> {
|
||||||
|
|
||||||
#RequireNodeType<Node, AST.VariableDeclarationStatement>(
|
#RequireNodeType<Node, CST.VariableDeclarationStatement>(
|
||||||
node: node, type: "variableDeclaration", nice_type_name: "variable declaration statement")
|
node: node, type: "variableDeclaration", nice_type_name: "variable declaration statement")
|
||||||
|
|
||||||
let maybe_typeref = node.child(at: 0)
|
let maybe_typeref = node.child(at: 0)
|
||||||
@@ -201,7 +201,7 @@ extension AST.VariableDeclarationStatement: Compilable {
|
|||||||
let maybe_rvalue = node.childCount > 3 ? node.child(at: 3) : .none
|
let maybe_rvalue = node.childCount > 3 ? node.child(at: 3) : .none
|
||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok(let parsed_variablename) = AST.Identifier.CompileExpression(
|
case .Ok(let parsed_variablename) = CST.Identifier.ParseExpression(
|
||||||
node: variablename, withContext: context)
|
node: variablename, withContext: context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
@@ -209,13 +209,13 @@ extension AST.VariableDeclarationStatement: Compilable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok(let declaration_p4_type) = AST.Types.CompileType(type: typeref, withContext: context)
|
case .Ok(let declaration_p4_type) = CST.Types.ParseType(type: typeref, withContext: context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(withMessage: "Could not parse a P4 type from \(typeref.text!)"))
|
Error(withMessage: "Could not parse a P4 type from \(typeref.text!)"))
|
||||||
}
|
}
|
||||||
|
|
||||||
var initializer: AST.AnExpression? = .none
|
var initializer: CST.AnExpression? = .none
|
||||||
|
|
||||||
// If there is an initializer, it must be an expression.
|
// If there is an initializer, it must be an expression.
|
||||||
if let initializer_expression = maybe_rvalue {
|
if let initializer_expression = maybe_rvalue {
|
||||||
@@ -226,7 +226,7 @@ extension AST.VariableDeclarationStatement: Compilable {
|
|||||||
withError: "initial value for declaration statement is not an expression"))
|
withError: "initial value for declaration statement is not an expression"))
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_parsed_rvalue = AST.Expression.Compile(
|
let maybe_parsed_rvalue = CST.Expression.Parse(
|
||||||
node: initializer_expression, withContext: context)
|
node: initializer_expression, withContext: context)
|
||||||
guard
|
guard
|
||||||
case .Ok(let parsed_rvalue) = maybe_parsed_rvalue
|
case .Ok(let parsed_rvalue) = maybe_parsed_rvalue
|
||||||
@@ -238,43 +238,43 @@ extension AST.VariableDeclarationStatement: Compilable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Result.Ok(
|
return Result.Ok(
|
||||||
AST.VariableDeclarationStatement(
|
CST.VariableDeclarationStatement(
|
||||||
identifier: parsed_variablename as! AST.Identifier, withType: declaration_p4_type,
|
identifier: parsed_variablename as! CST.Identifier, withType: declaration_p4_type,
|
||||||
withInitializer: initializer),
|
withInitializer: initializer),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@deriveCompilableStatement
|
@deriveParsableStatement
|
||||||
extension AST.VariableDeclarationStatement: CompilableStatement {}
|
extension CST.VariableDeclarationStatement: ParsableStatement {}
|
||||||
|
|
||||||
extension AST.ExpressionStatement: Compilable {
|
extension CST.ExpressionStatement: Parsable {
|
||||||
public typealias C = AST.ExpressionStatement
|
public typealias C = CST.ExpressionStatement
|
||||||
public static func Compile(
|
public static func Parse(
|
||||||
node: Node, withContext context: ASTCompilerContext
|
node: Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.ExpressionStatement> {
|
) -> Result<CST.ExpressionStatement> {
|
||||||
#RequireNodeType<Node, (P4Statement)>(
|
#RequireNodeType<Node, (P4Statement)>(
|
||||||
node: node, type: "expressionStatement", nice_type_name: "expression statement")
|
node: node, type: "expressionStatement", nice_type_name: "expression statement")
|
||||||
|
|
||||||
let expression_node = node.child(at: 0)!
|
let expression_node = node.child(at: 0)!
|
||||||
|
|
||||||
return switch AST.Expression.Compile(node: expression_node, withContext: context) {
|
return switch CST.Expression.Parse(node: expression_node, withContext: context) {
|
||||||
case .Ok(let expression): .Ok(AST.ExpressionStatement(expression))
|
case .Ok(let expression): .Ok(CST.ExpressionStatement(expression))
|
||||||
case .Error(let e): .Error(e)
|
case .Error(let e): .Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@deriveCompilableStatement
|
@deriveParsableStatement
|
||||||
extension AST.ExpressionStatement: CompilableStatement {}
|
extension CST.ExpressionStatement: ParsableStatement {}
|
||||||
|
|
||||||
extension AST.ParserAssignmentStatement: Compilable {
|
extension CST.ParserAssignmentStatement: Parsable {
|
||||||
public typealias C = AST.ParserAssignmentStatement
|
public typealias C = CST.ParserAssignmentStatement
|
||||||
public static func Compile(
|
public static func Parse(
|
||||||
node: Node, withContext context: ASTCompilerContext
|
node: Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.ParserAssignmentStatement> {
|
) -> Result<CST.ParserAssignmentStatement> {
|
||||||
|
|
||||||
#RequireNodeType<Node, AST.ParserAssignmentStatement>(
|
#RequireNodeType<Node, CST.ParserAssignmentStatement>(
|
||||||
node: node, type: "assignmentStatement", nice_type_name: "assignment statement")
|
node: node, type: "assignmentStatement", nice_type_name: "assignment statement")
|
||||||
|
|
||||||
guard let lvalue_node = node.child(at: 0),
|
guard let lvalue_node = node.child(at: 0),
|
||||||
@@ -295,77 +295,77 @@ extension AST.ParserAssignmentStatement: Compilable {
|
|||||||
withError: "Missing rvalue in assignment statement"))
|
withError: "Missing rvalue in assignment statement"))
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_parsed_rvalue = AST.Expression.Compile(
|
let maybe_parsed_rvalue = CST.Expression.Parse(
|
||||||
node: rvalue_node, withContext: context)
|
node: rvalue_node, withContext: context)
|
||||||
guard case Result.Ok(let rvalue) = maybe_parsed_rvalue else {
|
guard case Result.Ok(let rvalue) = maybe_parsed_rvalue else {
|
||||||
return Result.Error(maybe_parsed_rvalue.error()!)
|
return Result.Error(maybe_parsed_rvalue.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_parsed_lvalue = AST.Expression.Compile(node: lvalue_node, withContext: context)
|
let maybe_parsed_lvalue = CST.Expression.Parse(node: lvalue_node, withContext: context)
|
||||||
guard case .Ok(let lvalue) = maybe_parsed_lvalue else {
|
guard case .Ok(let lvalue) = maybe_parsed_lvalue else {
|
||||||
return Result.Error(maybe_parsed_lvalue.error()!)
|
return Result.Error(maybe_parsed_lvalue.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.Ok(
|
return Result.Ok(
|
||||||
AST.ParserAssignmentStatement(
|
CST.ParserAssignmentStatement(
|
||||||
withLValue: lvalue,
|
withLValue: lvalue,
|
||||||
withValue: rvalue
|
withValue: rvalue
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@deriveCompilableStatement
|
@deriveParsableStatement
|
||||||
extension AST.ParserAssignmentStatement: CompilableStatement {}
|
extension CST.ParserAssignmentStatement: ParsableStatement {}
|
||||||
|
|
||||||
extension AST.ReturnStatement: Compilable {
|
extension CST.ReturnStatement: Parsable {
|
||||||
public typealias C = AST.ReturnStatement
|
public typealias C = CST.ReturnStatement
|
||||||
public static func Compile(
|
public static func Parse(
|
||||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.ReturnStatement> {
|
) -> Result<CST.ReturnStatement> {
|
||||||
#RequireNodeType<Node, AST.ReturnStatement>(
|
#RequireNodeType<Node, CST.ReturnStatement>(
|
||||||
node: node, type: "return_statement", nice_type_name: "return statement")
|
node: node, type: "return_statement", nice_type_name: "return statement")
|
||||||
|
|
||||||
let expression_node = node.child(at: 1)!
|
let expression_node = node.child(at: 1)!
|
||||||
|
|
||||||
return switch AST.Expression.Compile(node: expression_node, withContext: context) {
|
return switch CST.Expression.Parse(node: expression_node, withContext: context) {
|
||||||
case .Ok(let result): .Ok(AST.ReturnStatement(result))
|
case .Ok(let result): .Ok(CST.ReturnStatement(result))
|
||||||
case .Error(let e): .Error(e)
|
case .Error(let e): .Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@deriveCompilableStatement
|
@deriveParsableStatement
|
||||||
extension AST.ReturnStatement: CompilableStatement {}
|
extension CST.ReturnStatement: ParsableStatement {}
|
||||||
|
|
||||||
extension AST.ApplyStatement: Compilable {
|
extension CST.ApplyStatement: Parsable {
|
||||||
public typealias C = AST.ApplyStatement
|
public typealias C = CST.ApplyStatement
|
||||||
public static func Compile(
|
public static func Parse(
|
||||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.ApplyStatement> {
|
) -> Result<CST.ApplyStatement> {
|
||||||
#RequireNodeType<Node, AST.ApplyStatement>(
|
#RequireNodeType<Node, CST.ApplyStatement>(
|
||||||
node: node, type: "apply_statement", nice_type_name: "apply statement")
|
node: node, type: "apply_statement", nice_type_name: "apply statement")
|
||||||
|
|
||||||
let expression_node = node.child(at: 1)!
|
let expression_node = node.child(at: 1)!
|
||||||
|
|
||||||
return switch AST.BlockStatement.Compile(node: expression_node, withContext: context) {
|
return switch CST.BlockStatement.Parse(node: expression_node, withContext: context) {
|
||||||
case .Ok(let statement):
|
case .Ok(let statement):
|
||||||
.Ok(AST.ApplyStatement(statement))
|
.Ok(CST.ApplyStatement(statement))
|
||||||
case .Error(let e): .Error(e)
|
case .Error(let e): .Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@deriveCompilableStatement
|
@deriveParsableStatement
|
||||||
extension AST.ApplyStatement: CompilableStatement {}
|
extension CST.ApplyStatement: ParsableStatement {}
|
||||||
|
|
||||||
extension AST.Instantiation: Compilable {
|
extension CST.Instantiation: Parsable {
|
||||||
public typealias C = AST.Instantiation
|
public typealias C = CST.Instantiation
|
||||||
public static func Compile(
|
public static func Parse(
|
||||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.Instantiation> {
|
) -> Result<CST.Instantiation> {
|
||||||
|
|
||||||
let expression = node
|
let expression = node
|
||||||
#RequireNodeType<Node, AST.Instantiation>(
|
#RequireNodeType<Node, CST.Instantiation>(
|
||||||
node: expression, type: "instantiation", nice_type_name: "instantiation statement")
|
node: expression, type: "instantiation", nice_type_name: "instantiation statement")
|
||||||
|
|
||||||
var walker = Walker(node: expression)
|
var walker = Walker(node: expression)
|
||||||
@@ -373,11 +373,11 @@ extension AST.Instantiation: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.Instantiation>.Error(
|
or: Result<CST.Instantiation>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
||||||
|
|
||||||
let maybe_instantiated_type_name = AST.Identifier.CompileExpression(
|
let maybe_instantiated_type_name = CST.Identifier.ParseExpression(
|
||||||
node: current_node!, withContext: context)
|
node: current_node!, withContext: context)
|
||||||
guard case .Ok(let instantiated_type_name) = maybe_instantiated_type_name else {
|
guard case .Ok(let instantiated_type_name) = maybe_instantiated_type_name else {
|
||||||
return Result.Error(maybe_instantiated_type_name.error()!)
|
return Result.Error(maybe_instantiated_type_name.error()!)
|
||||||
@@ -386,11 +386,11 @@ extension AST.Instantiation: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.Instantiation>.Error(
|
or: Result<CST.Instantiation>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing instantiation component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing instantiation component")))
|
||||||
|
|
||||||
let maybe_argument_list = AST.ArgumentList.Compile(node: current_node!, withContext: context)
|
let maybe_argument_list = CST.ArgumentList.Parse(node: current_node!, withContext: context)
|
||||||
|
|
||||||
guard case .Ok(let arguments) = maybe_argument_list else {
|
guard case .Ok(let arguments) = maybe_argument_list else {
|
||||||
return .Error(maybe_argument_list.error()!)
|
return .Error(maybe_argument_list.error()!)
|
||||||
@@ -400,21 +400,125 @@ extension AST.Instantiation: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<AST.Instantiation>.Error(
|
or: Result<CST.Instantiation>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing instantiation name")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing instantiation name")))
|
||||||
|
|
||||||
let name = AST.Identifier.CompileExpression(node: current_node!, withContext: context)
|
let name = CST.Identifier.ParseExpression(node: current_node!, withContext: context)
|
||||||
guard case .Ok(let name) = name else {
|
guard case .Ok(let name) = name else {
|
||||||
return .Error(name.error()!)
|
return .Error(name.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok(
|
return .Ok(
|
||||||
AST.Instantiation(
|
CST.Instantiation(
|
||||||
named: name as! AST.Identifier, withType: instantiated_type_name as! AST.Identifier,
|
named: name as! CST.Identifier, withType: instantiated_type_name as! CST.Identifier,
|
||||||
withArguments: arguments))
|
withArguments: arguments))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@deriveCompilableStatement
|
@deriveParsableStatement
|
||||||
extension AST.Instantiation: CompilableStatement {}
|
extension CST.Instantiation: ParsableStatement {}
|
||||||
|
|
||||||
|
extension CST.Statements: Parsable {
|
||||||
|
public typealias C = CST.Statements
|
||||||
|
public static func Parse(
|
||||||
|
node: Node, withContext context: CSTCompilerContext
|
||||||
|
) -> Result<CST.Statements> {
|
||||||
|
if node.nodeType != "statements" && node.nodeType != "parserStatements" {
|
||||||
|
return Result.Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: node.toSourceLocation(), withError: "Did not find expected statements"))
|
||||||
|
}
|
||||||
|
|
||||||
|
var errors: (any Errorable)? = .none
|
||||||
|
var parsed_s: [CST.Statement] = Array()
|
||||||
|
|
||||||
|
node.enumerateNamedChildren { node in
|
||||||
|
switch SpecialParsers.Statement.Parse(
|
||||||
|
node: node, withContext: context)
|
||||||
|
{
|
||||||
|
case .Ok(let parsed_statement):
|
||||||
|
parsed_s.append(parsed_statement)
|
||||||
|
case .Error(let e):
|
||||||
|
errors =
|
||||||
|
if let errors = errors {
|
||||||
|
errors.append(error: e)
|
||||||
|
} else {
|
||||||
|
e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let errors = errors {
|
||||||
|
return .Error(errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(CST.Statements(parsed_s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CST.TransitionStatement: Parsable {
|
||||||
|
public static func Parse(
|
||||||
|
node: Node, withContext context: CSTCompilerContext
|
||||||
|
) -> Result<CST.AnState> {
|
||||||
|
|
||||||
|
guard let state_identifier = context.lexical_context_name else {
|
||||||
|
return .Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: node.toSourceLocation(),
|
||||||
|
withError: "Cannot parse a transition statement without the name of the containing state."
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
let stmts = context.lexical_context_statements
|
||||||
|
|
||||||
|
#RequireNodeType<Node, P4Statement>(
|
||||||
|
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
|
||||||
|
)
|
||||||
|
|
||||||
|
guard let tse_node = node.child(at: 1),
|
||||||
|
tse_node.nodeType! == "transitionSelectionExpression"
|
||||||
|
else {
|
||||||
|
return .Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: node.toSourceLocation(),
|
||||||
|
withError: "Could not find transition select expression"))
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let next_node = tse_node.child(at: 0) else {
|
||||||
|
return .Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: node.toSourceLocation(),
|
||||||
|
withError: "Could not find the next token in a transition selection expression"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the next node is an identifier, we have the simple form ...
|
||||||
|
if next_node.nodeType == "identifier" {
|
||||||
|
let maybe_parsed_next_state_id = CST.Identifier.ParseExpression(
|
||||||
|
node: next_node, withContext: context)
|
||||||
|
switch maybe_parsed_next_state_id {
|
||||||
|
case .Ok(let next_state_id):
|
||||||
|
return .Ok(
|
||||||
|
CST.ParserStateDirectTransition(
|
||||||
|
name: (state_identifier),
|
||||||
|
withNextStateIdentifier: next_state_id as! CST.Identifier, withStatements: stmts))
|
||||||
|
case .Error(let e):
|
||||||
|
return .Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know that the next node is a select expression.
|
||||||
|
return
|
||||||
|
switch CST.SelectExpression.ParseExpression(node: next_node, withContext: context)
|
||||||
|
{
|
||||||
|
case .Ok(let tse):
|
||||||
|
.Ok(
|
||||||
|
CST.ParserStateSelectTransition(
|
||||||
|
name: state_identifier, withTransitionExpression: tse as! CST.SelectExpression,
|
||||||
|
withStatements: stmts,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
case .Error(let e): .Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,18 +20,18 @@ import SwiftTreeSitter
|
|||||||
import TreeSitterExtensions
|
import TreeSitterExtensions
|
||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
extension P4Boolean: MaybeCompilableType {
|
extension P4Boolean: MaybeParsableType {
|
||||||
public static func MaybeCompileType(
|
public static func MaybeParseType(
|
||||||
type: SwiftTreeSitter.Node, withContext: ASTCompilerContext
|
type: SwiftTreeSitter.Node, withContext: CSTCompilerContext
|
||||||
) -> Common.Result<(AST.Tipe)?> {
|
) -> Common.Result<(CST.Tipe)?> {
|
||||||
return type.text == "bool" ? .Ok(AST.Tipe(P4QualifiedType(P4Boolean()))) : .Ok(.none)
|
return type.text == "bool" ? .Ok(CST.Tipe(P4QualifiedType(P4Boolean()))) : .Ok(.none)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension P4Int: MaybeCompilableType {
|
extension P4Int: MaybeParsableType {
|
||||||
public static func MaybeCompileType(
|
public static func MaybeParseType(
|
||||||
type: SwiftTreeSitter.Node, withContext: ASTCompilerContext
|
type: SwiftTreeSitter.Node, withContext: CSTCompilerContext
|
||||||
) -> Common.Result<(AST.Tipe)?> {
|
) -> Common.Result<(CST.Tipe)?> {
|
||||||
|
|
||||||
// Drill down, as appropriate.
|
// Drill down, as appropriate.
|
||||||
let base_type_node = type.child(at: 0)!
|
let base_type_node = type.child(at: 0)!
|
||||||
@@ -48,7 +48,7 @@ extension P4Int: MaybeCompilableType {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: int_node, thing: walker.getNext(),
|
result: int_node, thing: walker.getNext(),
|
||||||
or: Result<AST.Tipe?>.Error(
|
or: Result<CST.Tipe?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: type_node.toSourceLocation(),
|
sourceLocation: type_node.toSourceLocation(),
|
||||||
withError: "Missing elements in int type declaration")))
|
withError: "Missing elements in int type declaration")))
|
||||||
@@ -65,29 +65,29 @@ extension P4Int: MaybeCompilableType {
|
|||||||
sourceLocation: bit_width_node.toSourceLocation(),
|
sourceLocation: bit_width_node.toSourceLocation(),
|
||||||
withError: "Could not parse \(bit_width_node.text!) into integer"))
|
withError: "Could not parse \(bit_width_node.text!) into integer"))
|
||||||
}
|
}
|
||||||
return .Ok(AST.Tipe(P4QualifiedType(P4Int(BitWidth.Width(bit_width)))))
|
return .Ok(CST.Tipe(P4QualifiedType(P4Int(BitWidth.Width(bit_width)))))
|
||||||
}
|
}
|
||||||
return .Ok(AST.Tipe(P4QualifiedType(P4Int(BitWidth.Infinite))))
|
return .Ok(CST.Tipe(P4QualifiedType(P4Int(BitWidth.Infinite))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension P4String: MaybeCompilableType {
|
extension P4String: MaybeParsableType {
|
||||||
public static func MaybeCompileType(
|
public static func MaybeParseType(
|
||||||
type: SwiftTreeSitter.Node, withContext: ASTCompilerContext
|
type: SwiftTreeSitter.Node, withContext: CSTCompilerContext
|
||||||
) -> Common.Result<(AST.Tipe)?> {
|
) -> Common.Result<(CST.Tipe)?> {
|
||||||
return type.text == "string" ? .Ok(AST.Tipe(P4QualifiedType(P4String()))) : .Ok(.none)
|
return type.text == "string" ? .Ok(CST.Tipe(P4QualifiedType(P4String()))) : .Ok(.none)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AST.Types: CompilableType {
|
extension CST.Types: ParsableType {
|
||||||
public static func CompileType(
|
public static func ParseType(
|
||||||
type: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
type: SwiftTreeSitter.Node, withContext context: CSTCompilerContext
|
||||||
) -> Result<AST.Tipe> {
|
) -> Result<CST.Tipe> {
|
||||||
let type_parsers: [MaybeCompilableType.Type] = [
|
let type_parsers: [MaybeParsableType.Type] = [
|
||||||
P4Boolean.self, P4Int.self, P4String.self, /*P4Struct.self,*/
|
P4Boolean.self, P4Int.self, P4String.self, /*P4Struct.self,*/
|
||||||
]
|
]
|
||||||
for type_parser in type_parsers {
|
for type_parser in type_parsers {
|
||||||
switch type_parser.MaybeCompileType(type: type, withContext: context) {
|
switch type_parser.MaybeParseType(type: type, withContext: context) {
|
||||||
case .Ok(.some(let type)): return .Ok(type)
|
case .Ok(.some(let type)): return .Ok(type)
|
||||||
case .Ok(.none): continue
|
case .Ok(.none): continue
|
||||||
case .Error(let e): return .Error(e)
|
case .Error(let e): return .Error(e)
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
// 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 SwiftTreeSitter
|
||||||
|
import TreeSitterExtensions
|
||||||
|
import TreeSitterP4
|
||||||
|
|
||||||
|
/*
|
||||||
|
public protocol CompilableValue {
|
||||||
|
static func CompileValue(withValue value: String) -> Result<P4DataValue>
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
public protocol MaybeParsableType {
|
||||||
|
static func MaybeParseType(
|
||||||
|
type: SwiftTreeSitter.Node, withContext: CSTCompilerContext
|
||||||
|
) -> Result<CST.Tipe?>
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol ParsableType {
|
||||||
|
static func ParseType(
|
||||||
|
type: SwiftTreeSitter.Node, withContext: CSTCompilerContext
|
||||||
|
) -> Result<CST.Tipe>
|
||||||
|
}
|
||||||
|
public protocol ParsableExpression {
|
||||||
|
static func ParseExpression(
|
||||||
|
node: Node, withContext context: CSTCompilerContext
|
||||||
|
) -> Result<CST.AnExpression>
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol Parsable<C> {
|
||||||
|
associatedtype C
|
||||||
|
static func Parse(
|
||||||
|
node: Node, withContext context: CSTCompilerContext
|
||||||
|
) -> Result<C>
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol ParsableStatement {
|
||||||
|
static func ParseStatement(
|
||||||
|
node: Node, withContext context: CSTCompilerContext
|
||||||
|
) -> Result<CST.Statement>
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol CSTVisitor<T> {
|
||||||
|
associatedtype T
|
||||||
|
func visit(node: CST.BinaryOperatorExpression, driver: CSTVisitorDriver, context: T) -> Result<T>
|
||||||
|
func visit(node: CST.Literal, driver: CSTVisitorDriver, context: T) -> Result<T>
|
||||||
|
func visit(node: CST.Identifier, driver: CSTVisitorDriver, context: T) -> Result<T>
|
||||||
|
|
||||||
|
func visit(node: CST.Parser, driver: CSTVisitorDriver, context: T) -> Result<T>
|
||||||
|
func visit(
|
||||||
|
node: CST.ParserStateDirectTransition, driver: CSTVisitorDriver, context: T
|
||||||
|
) -> Result<T>
|
||||||
|
func visit(node: CST.ParserStateNoTransition, driver: CSTVisitorDriver, context: T) -> Result<T>
|
||||||
|
func visit(
|
||||||
|
node: CST.ParserStateSelectTransition, driver: CSTVisitorDriver, context: T
|
||||||
|
) -> Result<T>
|
||||||
|
}
|
||||||
@@ -17,49 +17,49 @@
|
|||||||
|
|
||||||
import Common
|
import Common
|
||||||
|
|
||||||
public struct ASTVisitorDriver {
|
public struct CSTVisitorDriver {
|
||||||
public init() {}
|
public init() {}
|
||||||
|
|
||||||
public func visit<T>(
|
public func visit<T>(
|
||||||
expression: any AST.AnExpression, visitor: any ASTVisitor<T>, context: T
|
expression: any CST.AnExpression, visitor: any CSTVisitor<T>, context: T
|
||||||
) -> Result<T> {
|
) -> Result<T> {
|
||||||
return switch expression {
|
return switch expression {
|
||||||
case let e as AST.BinaryOperatorExpression:
|
case let e as CST.BinaryOperatorExpression:
|
||||||
visitor.visit(node: e, driver: self, context: context)
|
visitor.visit(node: e, driver: self, context: context)
|
||||||
case let e as AST.Literal: visitor.visit(node: e, driver: self, context: context)
|
case let e as CST.Literal: visitor.visit(node: e, driver: self, context: context)
|
||||||
default: .Error(Error(withMessage: "AST Expression Element Is Not Visitable"))
|
default: .Error(Error(withMessage: "AST Expression Element Is Not Visitable"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func visit<T>(
|
public func visit<T>(
|
||||||
state: any AST.AnState, visitor: any ASTVisitor<T>, context: T
|
state: any CST.AnState, visitor: any CSTVisitor<T>, context: T
|
||||||
) -> Result<T> {
|
) -> Result<T> {
|
||||||
return switch state {
|
return switch state {
|
||||||
case let s as AST.ParserStateDirectTransition:
|
case let s as CST.ParserStateDirectTransition:
|
||||||
visitor.visit(node: s, driver: self, context: context)
|
visitor.visit(node: s, driver: self, context: context)
|
||||||
case let s as AST.ParserStateNoTransition:
|
case let s as CST.ParserStateNoTransition:
|
||||||
visitor.visit(node: s, driver: self, context: context)
|
visitor.visit(node: s, driver: self, context: context)
|
||||||
case let s as AST.ParserStateSelectTransition:
|
case let s as CST.ParserStateSelectTransition:
|
||||||
visitor.visit(node: s, driver: self, context: context)
|
visitor.visit(node: s, driver: self, context: context)
|
||||||
default: .Error(Error(withMessage: "AST State Element (\(state)) Is Not Visitable"))
|
default: .Error(Error(withMessage: "AST State Element (\(state)) Is Not Visitable"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func visit<T>(
|
public func visit<T>(
|
||||||
statement: any AST.AnStatement, visitor: any ASTVisitor<T>, context: T
|
statement: any CST.Statement, visitor: any CSTVisitor<T>, context: T
|
||||||
) -> Result<T> {
|
) -> Result<T> {
|
||||||
return switch statement {
|
return switch statement {
|
||||||
case let s as AST.Parser: visitor.visit(node: s, driver: self, context: context)
|
case let s as CST.Parser: visitor.visit(node: s, driver: self, context: context)
|
||||||
default: .Error(Error(withMessage: "AST Statement Element Is Not Visitable"))
|
default: .Error(Error(withMessage: "AST Statement Element Is Not Visitable"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func visit<T>(
|
public func visit<T>(
|
||||||
program: AST.Program, visitor: any ASTVisitor<T>, context: T
|
program: CST.Program, visitor: any CSTVisitor<T>, context: T
|
||||||
) -> Result<T> {
|
) -> Result<T> {
|
||||||
|
|
||||||
var context = context
|
var context = context
|
||||||
for s in program.statements {
|
for s in program.statements.statements {
|
||||||
switch visit(statement: s, visitor: visitor, context: context) {
|
switch visit(statement: s, visitor: visitor, context: context) {
|
||||||
case .Ok(let c): context = c
|
case .Ok(let c): context = c
|
||||||
case .Error(let e): return .Error(e)
|
case .Error(let e): return .Error(e)
|
||||||
@@ -22,9 +22,9 @@ import SwiftTreeSitter
|
|||||||
import Testing
|
import Testing
|
||||||
import TreeSitter
|
import TreeSitter
|
||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
import P4CodeGen
|
|
||||||
|
|
||||||
@testable import P4Compiler
|
@testable import P4Parser
|
||||||
|
@testable import P4CodeGen
|
||||||
|
|
||||||
@Test func test_text_serializer() async throws {
|
@Test func test_text_serializer() async throws {
|
||||||
let simple_parser_declaration = """
|
let simple_parser_declaration = """
|
||||||
@@ -42,9 +42,9 @@ import P4CodeGen
|
|||||||
};
|
};
|
||||||
"""
|
"""
|
||||||
|
|
||||||
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
|
let program = try #UseOkResult(compile(simple_parser_declaration))
|
||||||
let v = TextSerializer()
|
let v = CSTTextSerializer()
|
||||||
let c = TextSerializerContext();
|
let c = CSTTextSerializerContext();
|
||||||
let vd = ASTVisitorDriver();
|
let vd = CSTVisitorDriver();
|
||||||
#expect(#RequireOkResult((vd.visit(program: program, visitor: v, context: c))))
|
#expect(#RequireOkResult((vd.visit(program: program, visitor: v, context: c))))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Macros
|
import Macros
|
||||||
import P4Compiler
|
|
||||||
import SwiftTreeSitter
|
import SwiftTreeSitter
|
||||||
import SystemPackage
|
import SystemPackage
|
||||||
import Testing
|
import Testing
|
||||||
@@ -25,6 +24,7 @@ import TreeSitter
|
|||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
@testable import Common
|
@testable import Common
|
||||||
|
@testable import P4Parser
|
||||||
|
|
||||||
@Test func test_preprocessor() async throws {
|
@Test func test_preprocessor() async throws {
|
||||||
let sm = SourceManager(["./TestData/Sources/"])
|
let sm = SourceManager(["./TestData/Sources/"])
|
||||||
@@ -32,7 +32,7 @@ import TreeSitterP4
|
|||||||
let file = FilePath.init(stringLiteral: "simple.p4")
|
let file = FilePath.init(stringLiteral: "simple.p4")
|
||||||
|
|
||||||
let source = try! (#UseOkResult(prep.preprocess(file)))
|
let source = try! (#UseOkResult(prep.preprocess(file)))
|
||||||
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(source.getSource())))
|
#expect(#RequireOkResult(compile(source.getSource())))
|
||||||
#expect(source.getLocations().getPath() == file)
|
#expect(source.getLocations().getPath() == file)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ import TreeSitterP4
|
|||||||
let file = FilePath.init(stringLiteral: "simple.p4")
|
let file = FilePath.init(stringLiteral: "simple.p4")
|
||||||
|
|
||||||
let source = try! (#UseOkResult(prep.preprocess(file)))
|
let source = try! (#UseOkResult(prep.preprocess(file)))
|
||||||
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(source.getSource())))
|
#expect(#RequireOkResult(compile(source.getSource())))
|
||||||
#expect(source.getLocations().getPath() == file)
|
#expect(source.getLocations().getPath() == file)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ import TreeSitterP4
|
|||||||
#expect(#RequireOkResult(prep.preprocess(file)))
|
#expect(#RequireOkResult(prep.preprocess(file)))
|
||||||
|
|
||||||
let source = try! (#UseOkResult(prep.preprocess(file)))
|
let source = try! (#UseOkResult(prep.preprocess(file)))
|
||||||
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(source.getSource())))
|
#expect(#RequireOkResult(compile(source.getSource())))
|
||||||
#expect(source.getLocations().getPath() == file)
|
#expect(source.getLocations().getPath() == file)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ import TreeSitterP4
|
|||||||
#expect(#RequireOkResult(prep.preprocess(file)))
|
#expect(#RequireOkResult(prep.preprocess(file)))
|
||||||
|
|
||||||
let source = try! (#UseOkResult(prep.preprocess(file)))
|
let source = try! (#UseOkResult(prep.preprocess(file)))
|
||||||
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(source.getSource())))
|
#expect(#RequireOkResult(compile(source.getSource())))
|
||||||
#expect(source.getLocations().getPath() == file)
|
#expect(source.getLocations().getPath() == file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user