from lark import Lark, Transformer, Token, Tree from script_format import ScriptFormat class LdrXfrm(Transformer): """ transform the parse tree into a more easily consumable form """ def rst(self, items): return ('reset') def NONL(self, items): return ''.join([i for i in items.value]) def rem(self, items): return ('rem', items[0]) def swmatch(self, items): return ('swmatch', items) def cmd(self, items): return ('cmd', {'req': items[0], 'rsp': items[1]}) def todigit(self, item): """ convert from Token/Tree to raw hex-digit """ if isinstance(item, Token): return item.value elif isinstance(item, Tree): return item.data def hex_item(self, items): """ return one byte as two-digit HEX string """ return "%s%s" % (items[0].value, items[1].value) def hexstr(self, items): """ return list of two-digit HEX strings """ return ('hexstr', ''.join(list(items))) def swpattern(self, items): """ return list of four HEX nibbles (or 'x' as wildcard) """ arr = [self.todigit(x) for x in items] return ''.join(arr) class ScriptFormatLDR(ScriptFormat): # parser for the LDR file format as generated by Simulity Profile Editor ldr_parser = Lark(r""" script: statement* ?statement: cmd | rst | rem | NEWLINE BSLASH: "\\\n" %ignore BSLASH NONL: /[^\n]/+ rem: "REM" NONL? NEWLINE ALNUM: DIGIT | LETTER | "_" key: "[" ALNUM+ "]" cmd: "CMD" hexstr [swmatch] NEWLINE cmd_item: hexstr | key hexstr: hex_item+ hex_item: HEXDIGIT HEXDIGIT swmatch: "(" swpattern ("," swpattern)* ")" swpattern: hex_or_x hex_or_x hex_or_x hex_or_x ?hex_or_x: HEXDIGIT | "X" -> x | "x" -> x rst: "RST" NEWLINE %import common.ESCAPED_STRING -> STRING %import common.WS_INLINE %import common.HEXDIGIT %import common.DIGIT %import common.LETTER %import common.NEWLINE %ignore WS_INLINE """, start='script') def parse_xform(self, text): tree = self.ldr_parser.parse(text) #print(tree.pretty()) p = LdrXfrm().transform(tree) return p