Skip to content

Commit

Permalink
Make the STF parser and lexer target specific.
Browse files Browse the repository at this point in the history
  • Loading branch information
fruffy committed Aug 2, 2023
1 parent ec05f6b commit 1b18cb8
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 156 deletions.
3 changes: 3 additions & 0 deletions backends/bmv2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
parser.out
parsetab.py
*.pyc
152 changes: 150 additions & 2 deletions backends/bmv2/bmv2stf.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
# Append tools to the import path.
sys.path.append(str(FILE_DIR.joinpath("../../tools")))
import testutils
from stf.stf_parser import STFParser
from stf.stf_parser import STFLexer, STFParser


class TimeoutException(Exception):
Expand Down Expand Up @@ -334,6 +334,154 @@ def makeKeyInstance(self):
return TableKeyInstance(self.key)


class BMv2StfLexer(STFLexer):
def __init__(self):
super().__init__()
tokens = [
"MIRRORING_ADD",
"MIRRORING_ADD_MC",
"MIRRORING_DELETE",
"MIRRORING_GET",
"MC_MGRP_CREATE",
"MC_NODE_CREATE",
"MC_NODE_UPDATE",
"MC_NODE_ASSOCIATE",
"COUNTER_READ",
"COUNTER_WRITE",
"REGISTER_READ",
"REGISTER_WRITE",
"REGISTER_RESET",
"METER_GET_RATES",
"METER_SET_RATES",
"METER_ARRAY_SET_RATES",
]
self.keywords.extend(tokens)
self.tokens.extend(tokens)


# PARSER GRAMMAR --------------------------------------------------------------


# statement : ADD qualified_name priority match_list action [= ID]
# | ADD qualified_name match_list action [= ID]
# | REMOVE [ALL | entry]
# | CHECK_COUNTER ID(id_or_index) [count_type logical_cond number]
# | EXPECT port expect_data
# | EXPECT port
# | NO_PACKET
# | PACKET port packet_data
# | SETDEFAULT qualified_name action
# | WAIT
# | direct_cmd
#
# direct_cmd : MIRRORING_ADD number number
# | MIRRORING_ADD_MC number number
# | MIRRORING_DELETE number
# | MIRRORING_GET number
# | MC_MGRP_CREATE number
# | MC_NODE_CREATE number number_list
# | MC_NODE_UPDATE number number_list
# | MC_NODE_ASSOCIATE number number
# | COUNTER_READ qualified_name number
# | COUNTER_WRITE qualified_name number number number
# | REGISTER_READ qualified_name number
# | REGISTER_WRITE qualified_name number number
# | REGISTER_RESET qualified_name
# | METER_GET_RATES qualified_name number
# | METER_SET_RATES qualified_name number meter_rate
# | METER_ARRAY_SET_RATES qualified_name meter_rate
#
# meter_rate : number COLON number meter_rate
# | number COLON number
class Bmv2StfParser(STFParser):
def __init__(self):
super().__init__(lexer=BMv2StfLexer())

def p_statement_direct_cmd(self, p):
"statement : direct_cmd"
p[0] = p[1]

def p_statement_check_counter(self, p):
"statement : CHECK_COUNTER ID LPAREN id_or_index RPAREN"
p[0] = (p[1].lower(), p[2], p[4], (None, "==", 0))

def p_statement_check_counter_with_check(self, p):
"statement : CHECK_COUNTER ID LPAREN id_or_index RPAREN count_type logical_cond number"
p[0] = (p[1].lower(), p[2], p[4], (p[6], p[7], p[8]))

def p_direct_cmd_mirroring_add(self, p):
"direct_cmd : MIRRORING_ADD number number"
p[0] = (p[1].lower(), p[2], p[3])

def p_direct_cmd_mirroring_add_mc(self, p):
"direct_cmd : MIRRORING_ADD_MC number number"
p[0] = (p[1].lower(), p[2], p[3])

def p_direct_cmd_mirroring_delete(self, p):
"direct_cmd : MIRRORING_DELETE number"
p[0] = (p[1].lower(), p[2])

def p_direct_cmd_mirroring_get(self, p):
"direct_cmd : MIRRORING_GET number"
p[0] = (p[1].lower(), p[2])

def p_direct_cmd_mc_mgrp_create(self, p):
"direct_cmd : MC_MGRP_CREATE number"
p[0] = (p[1].lower(), p[2])

def p_direct_cmd_mc_node_create(self, p):
"direct_cmd : MC_NODE_CREATE number number_list"
p[0] = (p[1].lower(), p[2], p[3])

def p_direct_cmd_mc_node_update(self, p):
"direct_cmd : MC_NODE_UPDATE number number_list"
p[0] = (p[1].lower(), p[2], p[3])

def p_direct_cmd_mc_node_associate(self, p):
"direct_cmd : MC_NODE_ASSOCIATE number number"
p[0] = (p[1].lower(), p[2], p[3])

def p_direct_cmd_counter_read(self, p):
"direct_cmd : COUNTER_READ qualified_name number"
p[0] = (p[1].lower(), p[2], p[3])

def p_direct_cmd_counter_write(self, p):
"direct_cmd : COUNTER_WRITE qualified_name number number number"
p[0] = (p[1].lower(), p[2], p[3], p[4], p[5])

def p_direct_cmd_register_read(self, p):
"direct_cmd : REGISTER_READ qualified_name number"
p[0] = (p[1].lower(), p[2], p[3])

def p_direct_cmd_register_write(self, p):
"direct_cmd : REGISTER_WRITE qualified_name number number"
p[0] = (p[1].lower(), p[2], p[3], p[4])

def p_direct_cmd_register_reset(self, p):
"direct_cmd : REGISTER_RESET qualified_name"
p[0] = (p[1].lower(), p[2])

def p_direct_cmd_meter_get_rates(self, p):
"direct_cmd : METER_GET_RATES qualified_name number"
p[0] = (p[1].lower(), p[2], p[3])

def p_direct_cmd_meter_set_rates(self, p):
"direct_cmd : METER_SET_RATES qualified_name number meter_rate"
p[0] = (p[1].lower(), p[2], p[3], p[4])

def p_direct_cmd_meter_array_set_rates(self, p):
"direct_cmd : METER_ARRAY_SET_RATES qualified_name meter_rate"
p[0] = (p[1].lower(), p[2], p[3])

def p_meter_rate_many(self, p):
"meter_rate : number_or_float COLON number meter_rate"
p[0] = p[1] + ":" + p[3] + " " + p[4]

def p_meter_rate_one(self, p):
"meter_rate : number_or_float COLON number"
p[0] = p[1] + ":" + p[3]


# Represents enough about the program executed to be
# able to invoke the BMV2 simulator, create a CLI file
# and test packets in pcap files.
Expand Down Expand Up @@ -759,6 +907,6 @@ def checkOutputs(self):

def parse_stf_file(self, testfile):
with open(testfile) as raw_stf:
parser = STFParser()
parser = Bmv2StfParser()
stf_str = raw_stf.read()
return parser.parse(stf_str)
24 changes: 4 additions & 20 deletions tools/stf/stf_lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def _error(self, s, token):
("packetdata", "exclusive"),
)

keywords = (
keywords = [
"ADD",
"ALL",
"BYTES",
Expand All @@ -87,23 +87,7 @@ def _error(self, s, token):
"REMOVE",
"SETDEFAULT",
"WAIT",
"MIRRORING_ADD",
"MIRRORING_ADD_MC",
"MIRRORING_DELETE",
"MIRRORING_GET",
"MC_MGRP_CREATE",
"MC_NODE_CREATE",
"MC_NODE_UPDATE",
"MC_NODE_ASSOCIATE",
"COUNTER_READ",
"COUNTER_WRITE",
"REGISTER_READ",
"REGISTER_WRITE",
"REGISTER_RESET",
"METER_GET_RATES",
"METER_SET_RATES",
"METER_ARRAY_SET_RATES",
)
]

keywords_map = {}
for keyword in keywords:
Expand All @@ -112,7 +96,7 @@ def _error(self, s, token):
else:
keywords_map[keyword.lower()] = keyword

tokens = (
tokens = [
"COLON",
"COMMA",
"DATA_DEC",
Expand All @@ -137,7 +121,7 @@ def _error(self, s, token):
"GT",
"GEQ",
"NEQ",
) + keywords
] + keywords

t_ignore_COMMENT = r"\#.*"
t_COLON = r":"
Expand Down
Loading

0 comments on commit 1b18cb8

Please sign in to comment.