Skip to content

Commit

Permalink
WIP: wireshark generator
Browse files Browse the repository at this point in the history
  • Loading branch information
no92 committed Jan 28, 2025
1 parent 706a0a7 commit fbe9474
Show file tree
Hide file tree
Showing 5 changed files with 472 additions and 20 deletions.
21 changes: 16 additions & 5 deletions bin/bragi
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,36 @@
import argparse

from bragi.parser import CompilationUnit
from bragi.cpp_generator import CodeGenerator
from bragi.cpp_generator import CodeGenerator as CppCodeGenerator
from bragi.wireshark_generator import CodeGenerator as WiresharkCodeGenerator

parser = argparse.ArgumentParser(prog = 'bragi', description = 'Bragi IDL to C++ compiler')
subparsers = parser.add_subparsers(title="language", required=True, dest='language')
parser.add_argument('input', nargs=1, help='input file')
parser.add_argument('output', nargs=1, help='output file')
parser.add_argument('-l', '--lib', nargs=1, help='C++ library to use', choices=['frigg', 'stdc++'], default='libc++')
parser.add_argument('--protobuf', help='Generate protobuf compatibilty methods (SerializeAsString/ParseFromArray)', action='store_true')

cpp_parser = subparsers.add_parser('cpp')
cpp_parser.add_argument('-l', '--lib', nargs=1, help='C++ library to use', choices=['frigg', 'stdc++'], default='libc++')
cpp_parser.add_argument('--protobuf', help='Generate protobuf compatibilty methods (SerializeAsString/ParseFromArray)', action='store_true')

ws_parser = subparsers.add_parser('wireshark')

args = parser.parse_args()

source = args.input[0]
output = args.output[0]
lib = args.lib[0]

with open(source, "r") as f:
code = f.read()
unit = CompilationUnit(source, code)
unit.process()
unit.verify()

generator = CodeGenerator(unit, lib, protobuf_compat = args.protobuf)
if(args.language == "cpp"):
lib = args.lib[0]
generator = CppCodeGenerator(unit, lib, protobuf_compat = args.protobuf)
else:
generator = WiresharkCodeGenerator(unit)

with open(output, "w") as o:
o.write(generator.generate())
43 changes: 32 additions & 11 deletions bragi/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
start: (message | enum | consts | ns | struct | using | group)+
tag: "tag" "(" INT ")"
attributes: tag?
format: "format" "(" NAME ")"
attributes: tag? format?
enum_attributes: format?
message: "message" NAME INT message_block
enum: "enum" NAME enum_block
consts: "consts" NAME type_name enum_block
enum: enum_attributes "enum" NAME enum_block
consts: enum_attributes "consts" NAME type_name enum_block
ns: "namespace" ESCAPED_STRING ";"
struct: "struct" NAME "{" message_member* "}"
using: "using" ESCAPED_STRING "=" ESCAPED_STRING ";"
Expand Down Expand Up @@ -90,19 +92,40 @@ def tags_block(self, items, meta):
return TagsBlock(meta.line, meta.column, items)

def attributes(self, items):
return items[0] if len(items) > 0 else None
ret = {}

for i in items:
if type(i) == Tag:
ret['tag'] = i
elif type(i) == Format:
ret['format'] = i

return ret

@v_args(meta = True)
def tag(self, items, meta):
return Tag(meta.line, meta.column, items[0])
return Tag(meta.line, meta.column, items[-1])

@v_args(meta = True)
def format(self, items, meta):
return Format(meta.line, meta.column, items[0])

@v_args(meta = True)
def enum(self, items, meta):
return Enum(meta.line, meta.column, items[0], 'enum', TypeName(0, 0, 'int32'), flatten(items[1:]))
return Enum(meta.line, meta.column, items[1], 'enum', TypeName(0, 0, 'int32'), items[0], flatten(items[2:]))

@v_args(meta = True)
def consts(self, items, meta):
return Enum(meta.line, meta.column, items[0], 'consts', items[1], flatten(items[2:]))
return Enum(meta.line, meta.column, items[1], 'consts', items[2], items[0], flatten(items[3:]))

def enum_attributes(self, items):
ret = {}

for i in items:
if type(i) == Format:
ret['format'] = i

return ret

@v_args(meta = True)
def using(self, items, meta):
Expand Down Expand Up @@ -133,9 +156,6 @@ def type_name(self, items, meta):
def type_size(self, items, meta):
return '[' + ''.join(items) + ']'

def attributes(self, items):
return items[0] if len(items) > 0 else None

@v_args(meta = True)
def group(self, items, meta):
return Group(meta.line, meta.column, items)
Expand Down Expand Up @@ -257,7 +277,8 @@ def process(self):
TypeIdentity.CONSTS if t.mode == 'consts' else TypeIdentity.ENUM,
fixed_size = subtype.fixed_size,
signed = subtype.signed,
subtype = subtype)
subtype = subtype,
attributes = t.attributes)
)

t.type = self.type_registry.get_type(t.name)
Expand Down
18 changes: 15 additions & 3 deletions bragi/tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def __init__(self, line, column, name, id, body):
self.id = id
self.head = None
self.tail = None
self.body = body
for m in body:
if self.head is None and type(m) is HeadSection:
self.head = m
Expand All @@ -45,10 +46,11 @@ def __repr__(self):
return 'Struct(' + self.name + ') { ' + str(self.members) + ' }'

class MessageMember:
def __init__(self, line, column, tag, typename, name):
def __init__(self, line, column, attributes, typename, name):
self.line = line
self.column = column
self.tag = tag
self.tag = attributes.get('tag', None)
self.format = attributes.get('format', None)
self.typename = typename
self.type = None
self.name = name
Expand Down Expand Up @@ -85,14 +87,24 @@ def __init__(self, line, column, value):
def __repr__(self):
return 'tag(' + str(self.value) + ')'

class Format:
def __init__(self, line, column, value):
self.line = line
self.column = column
self.value = value

def __repr__(self):
return 'format(' + str(self.value) + ')'

class Enum:
def __init__(self, line, column, name, mode, typename, members):
def __init__(self, line, column, name, mode, typename, attributes, members):
self.line = line
self.column = column
self.name = name
self.mode = mode
self.type = typename
self.members = members
self.attributes = attributes

def __repr__(self):
return 'Enum(' + self.name + ') { ' + str(self.members) + ' }'
Expand Down
6 changes: 5 additions & 1 deletion bragi/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,25 @@ class TypeIdentity(enum.Enum):
STRING = 6

class Type:
def __init__(self, name, identity, fixed_size = None, dynamic = False, subtype = None, signed = False, n_elements = None):
def __init__(self, name, identity, fixed_size = None, dynamic = False, subtype = None, signed = False, n_elements = None, attributes = {}):
self.name = name
self.identity = identity
self.fixed_size = fixed_size
self.dynamic = dynamic
self.subtype = subtype
self.n_elements = None
self.signed = None
self.attributes = attributes

if self.identity is TypeIdentity.ARRAY and n_elements:
self.n_elements = n_elements

if self.identity is TypeIdentity.INTEGER:
self.signed = signed

def __repr__(self):
return f'{self.name}'

class TypeRegistry:
def __init__(self):
self.types = {
Expand Down
Loading

0 comments on commit fbe9474

Please sign in to comment.