def test_simple_gen_with_size_invalid(self): op_format = [0x11, 0x8, "$0", 0xff, "$(w:1)", 0xff, 0xff] parameters = [0x0, 0x1234] with self.assertRaises(RuntimeError): output = codegen.simple_gen(op_format, parameters) # Fail if it doesn't raise self.assertNotEqual(output, output)
def parse(source: str, base_addr: int, debug=False) -> bytearray: symbol_table = {} icode = [] current_addr = base_addr for line_number, line in enumerate(source.splitlines()): tokens = TokenStream(line_number, line) token = tokens.next() if token is None: # Empty or comment only line continue if isinstance(token, RawCommandToken): parameters = [] token = tokens.expect(GRAMMAR["$$value$$"]) while token is not None: if isinstance(token, SymbolToken): if token in symbol_table: parameters.append(symbol_table[token]) else: raise SymbolNotDefinedError(token, line, line_number) else: parameters.append(token) token = tokens.expect(GRAMMAR["$$value$$"]) icode.append(parameters) current_addr += parameters[1] else: # Save the op name op_name = token if type(token) not in GRAMMAR: raise ParserSyntaxError(token, line, line_number) match = GRAMMAR[type(token)] if isinstance(match, dict): rule_set = match["rule"] else: rule_set = match parameters = [] if rule_set is not None: for rule in rule_set: if isinstance(rule, str) and rule.startswith("$$"): rule = GRAMMAR[rule] token = tokens.expect(rule) if token is None: raise ParserSyntaxError(token, line, line_number) if isinstance(op_name, SymbolToken): parameters.append(token) else: if isinstance(token, SymbolToken): if token in symbol_table: parameters.append(symbol_table[token]) else: raise SymbolNotDefinedError( token, line, line_number) else: parameters.append(token) verify_end = tokens.expect(CommentToken()) else: verify_end = tokens.expect(CommentToken()) if op_name == "def_symbol" or op_name == "def_label": name = parameters[0] value = parameters[1] if name in symbol_table: raise DuplicateSymbolError(name, line, line_number) if isinstance(value, ColonToken): value = current_addr symbol_table[name] = value else: if isinstance(op_name, list): output = simple_gen(op_name, parameters) else: method = getattr(codegen, op_name) output = method(parameters) if output is not None: icode.append(output) current_addr += output[1] # At this point, all of the intermediate code is built and the only thing left is to resolve # the left over symbols, which will all bel labels. bytecode = OutputStream() for code in icode: txt = "" for bd in code: if isinstance(bd, LabelToken): label = bd if label not in symbol_table: raise UndefinedLabel(label) bytecode.put_u32(symbol_table[label]) txt += f"{label} ({hex(symbol_table[label])}) " else: txt += f"{hex(bd)} " bytecode.put_u8(bd) if debug: print(txt) # Done! return bytecode.get_buffer()
def test_simple_gen_with_size_u32(self): op_format = [0x11, 0x8, "$0", 0xff, "$(U:1)"] parameters = [0x0, 0x12345678] output = codegen.simple_gen(op_format, parameters) self.assertEqual(output, [0x11, 0x8, 0x0, 0xff, 0x78, 0x56, 0x34, 0x12])
def test_simple_gen_with_size_u16(self): op_format = [0x11, 0x8, "$0", 0xff, "$(u:1)", 0xff, 0xff] parameters = [0x0, 0x1234] output = codegen.simple_gen(op_format, parameters) self.assertEqual(output, [0x11, 0x8, 0x0, 0xff, 0x34, 0x12, 0xff, 0xff])
def test_simple_gen_with_size_byte(self): op_format = [0xc, 0x8, 0xff, 0xff, "$(x:0)"] parameters = [".EventEnd"] output = codegen.simple_gen(op_format, parameters) self.assertEqual(output, [0xc, 0x8, 0xff, 0xff, ".EventEnd"])
def test_simple_gen_params(self): op_format = [0xc, 0x8, 0xff, 0xff, "$0"] parameters = [".EventEnd"] output = codegen.simple_gen(op_format, parameters) self.assertEqual(output, [0xc, 0x8, 0xff, 0xff, ".EventEnd"])
def test_simple_gen_no_params(self): op_format = [0x0, 0x4, 0xff, 0xff] parameters = [] output = codegen.simple_gen(op_format, parameters) self.assertEqual(output, [0x0, 0x4, 0xff, 0xff])