grammar,compiler: Add Support For Fixed-Width Integers
Continuous Integration / Grammar Tests (push) Successful in 4m13s
Continuous Integration / Library Format Tests (push) Successful in 5m17s
Continuous Integration / Library Tests (push) Failing after 8m34s
Continuous Integration / Cli Tests (push) Failing after 4m40s

Distinguishing between signed and unsigned fixed-width integer
types must still be done.

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
Will Hawkins
2026-05-18 06:52:21 -04:00
parent cbebcae20a
commit a7d8fd1304
16 changed files with 328 additions and 48 deletions
+20 -5
View File
@@ -424,19 +424,30 @@ public class P4BooleanValue: P4DataValue {
} }
} }
public enum BitWidth: Equatable {
case Infinite
case Width(Int)
}
/// A P4 int type /// A P4 int type
public struct P4Int: P4Type { public struct P4Int: P4Type {
public init() {} let width: BitWidth
public init(_ width: BitWidth = BitWidth.Infinite) {
self.width = width
}
public var description: String { public var description: String {
return "Int" return "Int (width: \(self.width))"
} }
public func eq(rhs: P4Type) -> Bool { public func eq(rhs: P4Type) -> Bool {
return switch rhs { return switch rhs {
case is P4Int: true case let rrhs as P4Int: rrhs.width == self.width
default: false default: false
} }
} }
public func def() -> P4DataValue? { public func def() -> P4DataValue? {
return P4IntValue(withValue: 0) return P4IntValue(withValue: 0)
} }
@@ -444,12 +455,16 @@ public struct P4Int: P4Type {
/// An instance of a P4 integer /// An instance of a P4 integer
public class P4IntValue: P4DataValue { public class P4IntValue: P4DataValue {
let int_type: P4Int
public func type() -> P4Type { public func type() -> P4Type {
return P4Int() return int_type
} }
let value: Int let value: Int
public init(withValue value: Int) { public init(withValue value: Int, andWidth width: BitWidth = BitWidth.Infinite) {
self.int_type = P4Int(width)
self.value = value self.value = value
} }
+2
View File
@@ -101,6 +101,8 @@ public func Fold<T, A>(input: [T], initial: A, block: (T, A) -> A) -> A {
#externalMacro(module: "Macros", type: "RequireNodesType") #externalMacro(module: "Macros", type: "RequireNodesType")
@freestanding(codeItem) public macro SkipUnlessNodeType<N>(node: N, type: String) = @freestanding(codeItem) public macro SkipUnlessNodeType<N>(node: N, type: String) =
#externalMacro(module: "Macros", type: "SkipUnlessNodeType") #externalMacro(module: "Macros", type: "SkipUnlessNodeType")
@freestanding(codeItem) public macro SkipUnlessNodesTypes<N>(node: N, types: [String]) =
#externalMacro(module: "Macros", type: "SkipUnlessNodesTypes")
@freestanding(codeItem) public macro MustOr<E, N>(result: E, thing: E?, or: N) = @freestanding(codeItem) public macro MustOr<E, N>(result: E, thing: E?, or: N) =
#externalMacro(module: "Macros", type: "MustOr") #externalMacro(module: "Macros", type: "MustOr")
+34 -1
View File
@@ -229,6 +229,38 @@ public struct SkipUnlessNodeType: CodeItemMacro {
} }
} }
public struct SkipUnlessNodesTypes: CodeItemMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext
) throws -> [CodeBlockItemSyntax] {
let arguments = node.arguments.indices
var arg_index = arguments.startIndex
let node_to_check = node.arguments[arg_index].expression
arg_index = arguments.index(after: arg_index)
guard let expected_types = node.arguments[arg_index].expression.as(ArrayExprSyntax.self) else {
throw MacroError(withMessage: "Node(s) to check must be in an array")
}
arg_index = arguments.index(after: arg_index)
let ifs = expected_types.elements.map { l in
"\(node_to_check).nodeType != \(l.expression)"
}.joined(separator: " && ")
return [
CodeBlockItemSyntax(
"""
if \(raw: ifs) {
return Result.Ok(.none)
}
""")
]
}
}
public struct MustOr: CodeItemMacro { public struct MustOr: CodeItemMacro {
public static func expansion( public static func expansion(
of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext
@@ -261,6 +293,7 @@ public struct MustOr: CodeItemMacro {
struct P4Macros: CompilerPlugin { 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, RequireNodesType.self, MustOr.self, RequireNodeType.self, SkipUnlessNodeType.self, SkipUnlessNodesTypes.self, RequireNodesType.self,
MustOr.self,
] ]
} }
+35 -3
View File
@@ -101,9 +101,41 @@ extension P4IntValue: CompilableExpression {
node: SwiftTreeSitter.Node, withContext context: CompilerContext node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Result<EvaluatableExpression?> { ) -> Result<EvaluatableExpression?> {
let node = node.child(at: 0)! let node = node.child(at: 0)!
#SkipUnlessNodeType<SwiftTreeSitter.Node>(node: node, type: "integer")
if let parsed_int = Int(node.text!) { #SkipUnlessNodesTypes<SwiftTreeSitter.Node>(
return .Ok(P4Value(P4IntValue(withValue: parsed_int))) node: node, types: ["integer", "integer_elaborated"])
var bit_width: BitWidth = BitWidth.Infinite
let value_source: String
if node.nodeType == "integer_elaborated" {
let re = /([0-9]+)([ws])([\-0-9]+)/
let integer_components = node.text!.matches(of: re)
if integer_components.isEmpty || integer_components.count > 1 {
return .Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Failed to parse elaborated integer: \(node.text!)"))
}
let width_source = "\(integer_components[0].1)"
guard let width = Int(width_source) else {
return .Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Failed to parse width from elaborated integer: \(width_source)"))
}
/// TODO: Handle signed vs. unsigned.
bit_width = BitWidth.Width(width)
value_source = "\(integer_components[0].3)"
} else {
value_source = node.text!
}
if let parsed_int = Int(value_source) {
return .Ok(P4Value(P4IntValue(withValue: parsed_int, andWidth: bit_width)))
} else { } else {
return .Error( return .Error(
ErrorWithLocation( ErrorWithLocation(
+36 -1
View File
@@ -34,7 +34,42 @@ extension P4Int: CompilableType {
public static func CompileType( public static func CompileType(
type: SwiftTreeSitter.Node, withContext: CompilerContext type: SwiftTreeSitter.Node, withContext: CompilerContext
) -> Common.Result<(any Common.P4Type)?> { ) -> Common.Result<(any Common.P4Type)?> {
return type.text == "int" ? .Ok(P4Int()) : .Ok(.none)
// Drill down, as appropriate.
let base_type_node = type.child(at: 0)!
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
node: base_type_node, type: "baseType")
let type_node = base_type_node.child(at: 0)!
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
node: type_node, type: "int_type")
var walker = Walker(node: type_node)
var int_node: Node? = .none
#MustOr(
result: int_node, thing: walker.getNext(),
or: Result<P4Type?>.Error(
ErrorWithLocation(
sourceLocation: type_node.toSourceLocation(),
withError: "Missing elements in int type declaration")))
// Move passed the keyword.
walker.next()
if let bit_width_node = walker.getNext() {
guard let bit_width = Int(bit_width_node.child(at: 1)!.text!),
bit_width != 0
else {
return .Error(
ErrorWithLocation(
sourceLocation: bit_width_node.toSourceLocation(),
withError: "Could not parse \(bit_width_node.text!) into integer"))
}
return .Ok(P4Int(BitWidth.Width(bit_width)))
}
return .Ok(P4Int())
} }
} }
+2 -2
View File
@@ -17,6 +17,7 @@
import Common import Common
import P4Lang import P4Lang
import P4Protos
public struct Generated { public struct Generated {
let gen: String let gen: String
@@ -48,13 +49,12 @@ public struct CodeGenerator: LanguageVisitor {
return visitor.start(node, context: generated) return visitor.start(node, context: generated)
} }
/// TODO: Can we generate these implementations somehow?
public typealias Context = Generated public typealias Context = Generated
public func visit( public func visit(
_ v: Program, _ c: VisitorContext<Generated> _ v: Program, _ c: VisitorContext<Generated>
) -> Result<VisitorContext<Generated>> { ) -> Result<VisitorContext<Generated>> {
var result: Result<VisitorContext<Generated>> = Fold( var result: Result<VisitorContext<Generated>> = Fold(
input: v.types, initial: .Ok(c.next(uc: c.getUserContext().append("["))) input: v.types, initial: .Ok(c.next(uc: c.getUserContext().append("[")))
) { (current, acc) in ) { (current, acc) in
+1 -1
View File
@@ -283,7 +283,7 @@ import P4Lang
#RequireErrorResult( #RequireErrorResult(
Error( Error(
withMessage: withMessage:
"{57, 10}: Failed to parse a statement element: {57, 1}: Cannot assign value with type Boolean to identifier z with type Int" "{57, 10}: Failed to parse a statement element: {57, 1}: Cannot assign value with type Boolean to identifier z with type Int (width: Infinite)"
), ),
Program.Compile(simple_parser_declaration)) Program.Compile(simple_parser_declaration))
) )
@@ -182,5 +182,5 @@ import TreeSitterP4
let error = try #UseErrorResult(Program.Compile(simple_parser_declaration)) let error = try #UseErrorResult(Program.Compile(simple_parser_declaration))
#expect(error.msg().contains("{29, 12}: Type of expression in return statement (Boolean) is not compatible with function return type (Int)")) #expect(error.msg().contains("{29, 12}: Type of expression in return statement (Boolean) is not compatible with function return type (Int (width: Infinite))"))
} }
@@ -132,7 +132,7 @@ import TreeSitterP4
#RequireErrorResult( #RequireErrorResult(
Error( Error(
withMessage: withMessage:
"Error(s) parsing select cases: {81, 4}: Key expression of type Boolean is not compatible with selector type Int" "Error(s) parsing select cases: {81, 4}: Key expression of type Boolean is not compatible with selector type Int (width: Infinite)"
), ),
Program.Compile(simple_parser_declaration))) Program.Compile(simple_parser_declaration)))
} }
+1 -1
View File
@@ -147,7 +147,7 @@ import TreeSitterP4
#expect( #expect(
#RequireErrorResult<(InstantiatedParserState, ProgramExecution)>( #RequireErrorResult<(InstantiatedParserState, ProgramExecution)>(
Error(withMessage: "Cannot call parser: Argument 1's type (Int) is incompatible with the parameter type (Boolean)"), Error(withMessage: "Cannot call parser: Argument 1's type (Int (width: Infinite)) is incompatible with the parameter type (Boolean)"),
runtime.run(withArguments: args))) runtime.run(withArguments: args)))
} }
+2 -2
View File
@@ -327,7 +327,7 @@ import TreeSitterP4
#expect( #expect(
#RequireErrorResult( #RequireErrorResult(
Error( Error(
withMessage: "{49, 13}: Failed to parse a statement element: {49, 8}: Cannot assign value of type Int to field yesno of type Boolean" withMessage: "{49, 13}: Failed to parse a statement element: {49, 8}: Cannot assign value of type Int (width: Infinite) to field yesno of type Boolean"
), ),
Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
) )
@@ -457,7 +457,7 @@ import TreeSitterP4
#expect( #expect(
#RequireErrorResult( #RequireErrorResult(
Error( Error(
withMessage: "{49, 20}: Failed to parse a statement element: {49, 11}: Cannot assign value of type Boolean to field count of type Int" withMessage: "{49, 20}: Failed to parse a statement element: {49, 11}: Cannot assign value of type Boolean to field count of type Int (width: Infinite)"
), ),
Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
) )
+1 -1
View File
@@ -45,5 +45,5 @@ struct StringConvertible: CustomStringConvertible {
@Test func test_result_type_p4value_convertible() async throws { @Test func test_result_type_p4value_convertible() async throws {
let result = Result.Ok(P4Value(P4IntValue(withValue: 5))) let result = Result.Ok(P4Value(P4IntValue(withValue: 5)))
#expect("\(result)" == "Ok: Value: 5 of Int type of type Int") #expect("\(result)" == "Ok: Value: 5 of Int (width: Infinite) type of type Int (width: Infinite)")
} }
+105 -11
View File
@@ -18,8 +18,8 @@
import Common import Common
import Foundation import Foundation
import Macros import Macros
import P4Runtime
import P4Lang import P4Lang
import P4Runtime
import SwiftTreeSitter import SwiftTreeSitter
import Testing import Testing
import TreeSitter import TreeSitter
@@ -36,13 +36,15 @@ import TreeSitterP4
transition reject; transition reject;
} }
}; };
"""; """
let err = Program.Compile(simple_parser_declaration) let err = Program.Compile(simple_parser_declaration)
guard case Result.Error(let e) = err else { guard case Result.Error(let e) = err else {
assert(false, "Expected an error, but had success") assert(false, "Expected an error, but had success")
} }
#expect(e.msg().contains("Failed to parse a statement element: Could not parse a P4 type from \(invalid_type_name)")) #expect(
e.msg().contains(
"Failed to parse a statement element: Could not parse a P4 type from \(invalid_type_name)"))
} }
} }
@@ -128,6 +130,90 @@ import TreeSitterP4
Program.Compile(simple_parser_declaration))) Program.Compile(simple_parser_declaration)))
} }
@Test func test_invalid_type_in_declaration3() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
int<5> specific_width_int = 5;
int unspecific_width_int = specific_width_int;
transition reject;
}
};
"""
let error = try! #UseErrorResult(Program.Compile(simple_parser_declaration))
#expect(
error.msg().contains(
"Cannot initialize specific_width_int (with type Int (width: Width(5))) from expression with type Int (width: Infinite)"
))
}
@Test func test_valid_specific_width_int_type_in_declaration() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
int<5> specific_width_int = 5w5;
int<5> unspecific_width_int = specific_width_int;
transition reject;
}
};
"""
#expect(#RequireOkResult(Program.Compile(simple_parser_declaration)))
}
@Test func test_expression_in_declaration_initializer_specific_width_int_type() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
int<5> specific_width_int = 5w5;
bool where_to = 5w5 == specific_width_int == true;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(Program.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.Parser>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
// 5w5 == specific_width_int == true
// true == true
// true
#expect(AsInstantiatedParserState(state_result) == P4Lang.accept)
}
@Test func test_expression_in_declaration_initializer_specific_width_int_type2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
int<5> specific_width_int = 5w5;
bool where_to = 5w6 == specific_width_int == false;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(Program.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.Parser>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
// 5w6 == specific_width_int == false
// false == false
// true
#expect(AsInstantiatedParserState(state_result) == P4Lang.accept)
}
@Test func test_expression_in_declaration_initializer() async throws { @Test func test_expression_in_declaration_initializer() async throws {
let simple_parser_declaration = """ let simple_parser_declaration = """
parser main_parser() { parser main_parser() {
@@ -141,7 +227,8 @@ import TreeSitterP4
}; };
""" """
let program = try #UseOkResult(Program.Compile(simple_parser_declaration)) let program = try #UseOkResult(Program.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.Parser>.create(program: program)) let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.Parser>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run()) let (state_result, _) = try! #UseOkResult(runtime.run())
// 5 == 5 == true // 5 == 5 == true
@@ -163,7 +250,8 @@ import TreeSitterP4
}; };
""" """
let program = try #UseOkResult(Program.Compile(simple_parser_declaration)) let program = try #UseOkResult(Program.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.Parser>.create(program: program)) let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.Parser>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run()) let (state_result, _) = try! #UseOkResult(runtime.run())
// 5 == 5 == true // 5 == 5 == true
@@ -185,7 +273,8 @@ import TreeSitterP4
}; };
""" """
let program = try #UseOkResult(Program.Compile(simple_parser_declaration)) let program = try #UseOkResult(Program.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.Parser>.create(program: program)) let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.Parser>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run()) let (state_result, _) = try! #UseOkResult(runtime.run())
// 6 == 5 == true // 6 == 5 == true
@@ -207,7 +296,8 @@ import TreeSitterP4
}; };
""" """
let program = try #UseOkResult(Program.Compile(simple_parser_declaration)) let program = try #UseOkResult(Program.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.Parser>.create(program: program)) let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.Parser>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run()) let (state_result, _) = try! #UseOkResult(runtime.run())
// 6 == 5 == false // 6 == 5 == false
@@ -229,7 +319,8 @@ import TreeSitterP4
}; };
""" """
let program = try #UseOkResult(Program.Compile(simple_parser_declaration)) let program = try #UseOkResult(Program.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.Parser>.create(program: program)) let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.Parser>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run()) let (state_result, _) = try! #UseOkResult(runtime.run())
// TODO: This test should throw an error. // TODO: This test should throw an error.
@@ -253,12 +344,14 @@ import TreeSitterP4
}; };
""" """
var test_types = VarTypeScopes().enter() var test_types = VarTypeScopes().enter()
test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4QualifiedType(P4Array(withValueType: P4QualifiedType(P4Int())))) test_types = test_types.declare(
identifier: Identifier(name: "ta"),
withValue: P4QualifiedType(P4Array(withValueType: P4QualifiedType(P4Int()))))
#expect( #expect(
#RequireErrorResult( #RequireErrorResult(
Error( Error(
withMessage: withMessage:
"{49, 22}: Failed to parse a statement element: Cannot initialize where_to (with type Boolean) from expression with type Int" "{49, 22}: Failed to parse a statement element: Cannot initialize where_to (with type Boolean) from expression with type Int (width: Infinite)"
), ),
Program.Compile(simple_parser_declaration, withGlobalInstances: test_types))) Program.Compile(simple_parser_declaration, withGlobalInstances: test_types)))
} }
@@ -275,7 +368,8 @@ import TreeSitterP4
#expect( #expect(
#RequireErrorResult( #RequireErrorResult(
Error( Error(
withMessage: "{85, 9}: Failed to parse a statement element: {85, 4}: Cannot assign value with type Int to identifier pmtr with type Boolean" withMessage:
"{85, 9}: Failed to parse a statement element: {85, 4}: Cannot assign value with type Int (width: Infinite) to identifier pmtr with type Boolean"
), ),
Program.Compile(simple_parser_declaration))) Program.Compile(simple_parser_declaration)))
} }
+6 -2
View File
@@ -40,9 +40,12 @@ export default grammar({
// Common - Types // Common - Types
typeRef: $ => choice($.baseType, $.type_identifier), typeRef: $ => choice($.baseType, $.type_identifier),
baseType: $ => choice($.bool, $.error, $.string, $.int, $.bit /* omitting "templated" types" */), baseType: $ => choice($.bool, $.error, $.string, $.int_type, $.bit /* omitting "templated" types" */),
constructor_parameters: $ => seq('(', optional($.parameter_list), ')'), constructor_parameters: $ => seq('(', optional($.parameter_list), ')'),
int_type: $ => seq($.int, optional($.bit_width)),
bit_width: $ => seq('<', $.integer, '>'),
// Common - Parsers // Common - Parsers
parserType: $ => seq(optional($.annotations), $.parser, field('parser_name', $.identifier), optional($.typeParameters), $.parameters), parserType: $ => seq(optional($.annotations), $.parser, field('parser_name', $.identifier), optional($.typeParameters), $.parameters),
@@ -120,7 +123,7 @@ export default grammar({
// Expressions // Expressions
expression: $ => choice($.grouped_expression, $.simple_expression), expression: $ => choice($.grouped_expression, $.simple_expression),
grouped_expression: $ => seq('(', $.expression, ')'), grouped_expression: $ => seq('(', $.expression, ')'),
simple_expression: $ => choice($.identifier, $.integer, $.booleanLiteralExpression, $.string_literal, $.binaryOperatorExpression, $.arrayAccessExpression, $.fieldAccessExpression, $.function_call), // Very limited. simple_expression: $ => choice($.identifier, $.integer, $.integer_elaborated, $.booleanLiteralExpression, $.string_literal, $.binaryOperatorExpression, $.arrayAccessExpression, $.fieldAccessExpression, $.function_call), // Very limited.
booleanLiteralExpression: $ => choice($.true, $.false), booleanLiteralExpression: $ => choice($.true, $.false),
selectExpression: $ => seq($.select, '(', $.expression, ')', '{', $.selectBody, '}'), // TODO: Should be expression list and not just a single expression selectExpression: $ => seq($.select, '(', $.expression, ')', '{', $.selectBody, '}'), // TODO: Should be expression list and not just a single expression
transitionSelectionExpression: $ => choice($.identifier, $.selectExpression), transitionSelectionExpression: $ => choice($.identifier, $.selectExpression),
@@ -211,6 +214,7 @@ export default grammar({
type_identifier: $ => /[A-Za-z_]+/, type_identifier: $ => /[A-Za-z_]+/,
string_literal: $ => /"[^"]*"/, string_literal: $ => /"[^"]*"/,
integer: $ => /[0-9]+/, integer: $ => /[0-9]+/,
integer_elaborated: $ => /[0-9]+[ws][-0-9]+/,
annotation_literal: $ => /@[A-Za-z_]+/, annotation_literal: $ => /@[A-Za-z_]+/,
default_keyset: $=> '_', default_keyset: $=> '_',
+62 -1
View File
@@ -46,7 +46,7 @@ parser simple() {
) )
========================= =========================
Simple Declaration (int) Simple Declaration (infinite-precision int)
========================= =========================
parser simple() { parser simple() {
state start { state start {
@@ -73,9 +73,11 @@ parser simple() {
(variableDeclaration (variableDeclaration
(typeRef (typeRef
(baseType (baseType
(int_type
(int) (int)
) )
) )
)
(identifier) (identifier)
) )
) )
@@ -92,6 +94,59 @@ parser simple() {
) )
) )
=========================
Simple Declaration (fixed-precision int)
=========================
parser simple() {
state start {
int<55> l;
transition accept;
}
};
---
(p4program
(declaration
(parserDeclaration
(parserType
(parser)
(identifier)
(parameters)
)
(parserStates
(parserState
(state)
(identifier)
(parserStatements
(parserStatement
(variableDeclaration
(typeRef
(baseType
(int_type
(int)
(bit_width
(integer)
)
)
)
)
(identifier)
)
)
)
(parserTransitionStatement
(transition)
(transitionSelectionExpression
(identifier)
)
)
)
)
)
)
)
========================= =========================
Simple Declaration (string) Simple Declaration (string)
========================= =========================
@@ -331,9 +386,11 @@ bool functionb(bool a, int b) {
(parameter (parameter
(typeRef (typeRef
(baseType (baseType
(int_type
(int) (int)
) )
) )
)
(identifier) (identifier)
) )
) )
@@ -393,9 +450,11 @@ bool functionb(in bool a, out int b, inout string c) {
) )
(typeRef (typeRef
(baseType (baseType
(int_type
(int) (int)
) )
) )
)
(identifier) (identifier)
) )
) )
@@ -468,9 +527,11 @@ extern bool functionb(in bool a, out int b, inout string c);
) )
(typeRef (typeRef
(baseType (baseType
(int_type
(int) (int)
) )
) )
)
(identifier) (identifier)
) )
) )
@@ -38,9 +38,11 @@ int fun() {
(function_declaration (function_declaration
(typeRef (typeRef
(baseType (baseType
(int_type
(int) (int)
) )
) )
)
(identifier) (identifier)
(parameters) (parameters)
(blockStatement (blockStatement
@@ -382,9 +384,11 @@ parser simple() {
(variableDeclaration (variableDeclaration
(typeRef (typeRef
(baseType (baseType
(int_type
(int) (int)
) )
) )
)
(identifier) (identifier)
(assignment) (assignment)
(expression (expression