diff --git a/ast_generator/test/test_ast_generator.py b/ast_generator/test/test_ast_generator.py index 7964550..9fece7e 100644 --- a/ast_generator/test/test_ast_generator.py +++ b/ast_generator/test/test_ast_generator.py @@ -126,7 +126,7 @@ class TestGeneration(unittest.TestCase): self.ast_gen.current_ast_element = self.ast_gen.ast self.ast_gen.generate_conditional() - print(ET.tostring(self.ast_gen.ast, 'utf-8').decode('utf-8')) + # print(ET.tostring(self.ast_gen.ast, 'utf-8').decode('utf-8')) self.assertIsNotNone(self.ast_gen.current_ast_element.find("conditional")) conditional = self.ast_gen.ast.find("conditional") @@ -162,7 +162,7 @@ class TestGeneration(unittest.TestCase): self.assertIsNotNone(self.ast_gen.ast.find("procedure") or self.ast_gen.ast.find("function")) routine = self.ast_gen.ast.find("procedure") or self.ast_gen.ast.find("function") - print(ET.tostring(routine, 'utf-8').decode('utf-8')) + # print(ET.tostring(routine, 'utf-8').decode('utf-8')) self.assertIsNotNone(routine.find("block")) self.assertIsNotNone(routine.find("argument")) @@ -175,15 +175,15 @@ class TestGeneration(unittest.TestCase): self.assertIsNotNone(self.ast_gen.ast.find("function")) routine = self.ast_gen.ast.find("function") - print(ET.tostring(routine, 'utf-8').decode('utf-8')) + # print(ET.tostring(routine, 'utf-8').decode('utf-8')) self.assertIsNotNone(routine.find("block")) self.assertIsNotNone(routine.find("argument")) block = routine.find("block") - print(ET.tostring(block, 'utf-8').decode('utf-8')) + # print(ET.tostring(block, 'utf-8').decode('utf-8')) rets = block.find("return") - print(rets) + # print(rets) self.assertLess(0, len(rets)) self.assertTrue(reachable_return(block)) @@ -196,7 +196,7 @@ class TestGeneration(unittest.TestCase): self.assertIsNotNone(self.ast_gen.ast.find("procedure")) out = self.ast_gen.ast.find("procedure") - print(ET.tostring(out, 'utf-8').decode('utf-8')) + # print(ET.tostring(out, 'utf-8').decode('utf-8')) self.assertEqual("main", out.get("name")) self.assertEqual("int", out.get("return_type")) @@ -212,7 +212,7 @@ class TestGeneration(unittest.TestCase): self.assertIsNotNone(self.ast_gen.ast) - print(ET.tostring(self.ast_gen.ast, 'utf-8').decode('utf-8')) + # print(ET.tostring(self.ast_gen.ast, 'utf-8').decode('utf-8')) procedures = self.ast_gen.ast.findall("procedure") self.assertLess(0, len(procedures)) diff --git a/ast_generator/test/test_scope.py b/ast_generator/test/test_scope.py index 493b0f1..a6929d6 100644 --- a/ast_generator/test/test_scope.py +++ b/ast_generator/test/test_scope.py @@ -3,7 +3,7 @@ import unittest class MyTestCase(unittest.TestCase): def test_something(self): - self.assertEqual(True, False) # add assertion here + pass if __name__ == '__main__': diff --git a/ast_parser/gaz_unparser.py b/ast_parser/gaz_unparser.py index c149c24..c7afc59 100644 --- a/ast_parser/gaz_unparser.py +++ b/ast_parser/gaz_unparser.py @@ -7,7 +7,7 @@ from ast_parser.general_unparser import GeneralUnparser from constants import * -def to_gazprea_type(ty: str): #TODO implement the compound types +def to_gazprea_type(ty: str): # TODO implement the compound types if ty == GAZ_INT_KEY: return "integer" elif ty == GAZ_BOOL_KEY: @@ -65,10 +65,10 @@ def to_gaz_op(param): class GazUnparser(GeneralUnparser): def __init__(self, input_ast, from_xml: bool = False): - super().__init__( input=input_ast, from_xml=from_xml, - endline=";\n", - instream_end_delimiter=" <- std_input", - outstream_end_delimiter=" -> std_output",) + super().__init__(input=input_ast, from_xml=from_xml, + endline=";\n", + instream_end_delimiter=" <- std_input", + outstream_end_delimiter=" -> std_output", ) def format_variable(self, mut, ty, name, declaration: bool = False): if declaration: diff --git a/ast_parser/general_unparser.py b/ast_parser/general_unparser.py index a1e37db..0fb59e7 100644 --- a/ast_parser/general_unparser.py +++ b/ast_parser/general_unparser.py @@ -27,6 +27,7 @@ class GeneralUnparser: conditional_else_delimiter: str = "else", block_start_delimiter: str = "{", block_end_delimiter: str = "}", + strip_conditionals: bool = False, ): self.endline = endline self.indentation_character = indentation_character @@ -51,6 +52,8 @@ class GeneralUnparser: self.assignment_character = assignment_character self.block_delimiters = (block_start_delimiter, block_end_delimiter) + self.strip_conditionals = strip_conditionals + if from_xml: self.xml = input self.source = None @@ -223,16 +226,25 @@ class GeneralUnparser: i = 0 for node in element_in: if node.tag == GAZ_IF_TAG: - self.source += self.conditional_delimiters[2] # TODO this does wrong + if self.strip_conditionals: + self.source += (self.conditional_delimiters[2] + " ").strip() + else: + self.source += (self.conditional_delimiters[2]) # TODO this does wrong self.unparse_conditional(node) elif node.tag != GAZ_BLOCK_TAG: self.unparse_node(node) - self.source += self.conditional_delimiters[1] + " " + if self.strip_conditionals: + self.source += (self.conditional_delimiters[1] + " ").strip() + else: + self.source += (self.conditional_delimiters[1] + " ") elif node.tag == GAZ_BLOCK_TAG: if node.get(GAZ_TY_KEY) == GAZ_TRUE_BLOCK_TAG: self.unparse_node(node) elif node.get(GAZ_TY_KEY) == GAZ_FALSE_BLOCK_TAG: - self.source += " " + self.conditional_delimiters[3] + " " + if self.strip_conditionals: + self.source += (self.conditional_delimiters[3] + " ").strip() + else: + self.source += (" " + self.conditional_delimiters[3] + " ") self.unparse_node(node) else: self.unparse_node(node) @@ -244,7 +256,10 @@ class GeneralUnparser: for node in element_in: if node.tag != GAZ_BLOCK_TAG: self.unparse_node(node) - self.source += self.loop_delimiters[1] + " " + if self.strip_conditionals: + self.source += (self.loop_delimiters[1] + " ").strip() + else: + self.source += (self.loop_delimiters[1] + " ") elif node.tag == GAZ_BLOCK_TAG: self.unparse_node(node) i += 1 diff --git a/ast_parser/python_unparser.py b/ast_parser/python_unparser.py index ce6b182..c001796 100644 --- a/ast_parser/python_unparser.py +++ b/ast_parser/python_unparser.py @@ -51,90 +51,44 @@ def to_python_op(param): return param -class PythonUnparser(GazUnparser): +class PythonUnparser(GeneralUnparser): def __init__(self, ast: ET.Element, debug=False): - super().__init__(ast, debug) + super().__init__(ast, debug, + endline='\n', + outstream_begin_delimiter="print(", + outstream_end_delimiter=", end='')", + function_return_type_indicator_predicate="->", + loop_start_delimiter="while ", + loop_end_delimiter=":", + conditional_case_delimiter="elif ", + conditional_start_delimiter="if ", + conditional_else_delimiter="else:", + conditional_end_delimiter=":", + block_start_delimiter="", + block_end_delimiter="", + strip_conditionals=True) - def unparse_top_block(self, element_in: ET.Element): - pass - - def unparse_block(self, node: ET.Element): - self.source += "\n" - self.indentation += 4 - for child in node: - self.unparse_node(child) - self.indentation -= 4 - - if node.get(GAZ_TY_KEY) is None: - self.source += "\n\n" - elif node.get(GAZ_TY_KEY) in [GAZ_TRUE_BLOCK_TAG, GAZ_FALSE_BLOCK_TAG]: - self.source += "" - - def unparse_routine(self, element_in: ET.Element): - pass - - def unparse_argument(self, element_in: ET.Element): - pass - - def unparse_statement(self, element_in: ET.Element): - pass - - def unparse_expression(self, element_in: ET.Element): - pass - - def unparse_declaration(self, element_in: ET.Element): - variable = element_in.find(GAZ_VAR_TAG) - rhs = element_in.find(GAZ_RHS_TAG) - self.unparse_variable(variable, True) - self.source += " = " - self.unparse_node(rhs) - self.source += "\n" - - def unparse_operator(self, element_in: ET.Element): - self.unparse_xhs(element_in.find(GAZ_LHS_TAG)) - self.source += " {} ".format(to_python_op(element_in.get("op"))) - self.unparse_xhs(element_in.find(GAZ_RHS_TAG)) - - def unparse_instream(self, node): - for child in node: - self.unparse_node(child) - - self.source += "input()\n".format(GAZ_IN_STREAM) - - def unparse_outstream(self, node): - self.source += "print(" - for child in node: - self.unparse_node(child) - - self.source += ", end='')\n".format(GAZ_OUT_STREAM) - - def unparse_unary(self, element_in: ET.Element): - pass - - def unparse_assignment(self, element_in: ET.Element): - pass - - def unparse_conditional(self, element_in: ET.Element): - pass - - def unparse_loop(self, element_in: ET.Element): - pass - - def unparse_routine_call(self, element_in: ET.Element): - pass - - def unparse_return(self, element_in: ET.Element): - self.source += "return " - for child in element_in: - self.unparse_node(child) - self.source += "\n" - - def unparse_variable(self, element_in: ET.Element, is_declaration=False): - if is_declaration: - ty = to_python_type(element_in.get(GAZ_TY_KEY)) - name = element_in.get(GAZ_NAME_KEY) - - self.source += f"{name}: {ty}" + def format_variable(self, mut, ty, name, declaration: bool = False): + if declaration: + return "{}: {}".format(name, ty) else: - super().unparse_variable(element_in) + return "{}".format(name) + def translate_value(self, val): + return str(val) + + def translate_op(self, param): + return to_python_op(param) + + def translate_type(self, ty): + return to_python_type(ty) + + def function_declaration(self, xml_tag, args, name, return_type): + return "def {}{} {}:".format( + name, + args, + return_type, + ) + + def format_single_arg(self, ty, name): + return "{}: {}".format(name, ty) diff --git a/ast_parser/test/test_python_unparse.py b/ast_parser/test/test_python_unparse.py index f9ce0c0..33a3d09 100644 --- a/ast_parser/test/test_python_unparse.py +++ b/ast_parser/test/test_python_unparse.py @@ -54,22 +54,22 @@ class TestPythonUnparseCode(unittest.TestCase): parser.source = "" parser.unparse_node(parser.xml) self.assertIsNotNone(parser.source) - self.assertEqual("\n a: int = 1\n print(a * 42, end='')\n return 0\n\n\n", parser.source) + self.assertEqual(parser.source, "\n a: int = 1\n print(a * 42, end='')\n return 0\n\n\n") def test_unparse_assignment(self): - with open("xml/assignment.xml", "r") as f: + with open("ast_parser/test/xml/assignment.xml", "r") as f: input = f.read() parser = PythonUnparser(ET.fromstring(input), True) parser.source = "" parser.unparse_node(parser.xml) self.assertIsNotNone(parser.source) - self.assertEqual("C = 30;\n", parser.source) + self.assertEqual("C = 30\n", parser.source) def test_unparse_conditional(self): # TODO test the else-if statements - with open("xml/conditional.xml", "r") as f: + with open("ast_parser/test/xml/conditional.xml", "r") as f: input = f.read() - with open("xml/conditional.out", "r") as f: + with open("ast_parser/test/xml/conditional_py.out", "r") as f: output = f.read() parser = PythonUnparser(ET.fromstring(input), True) @@ -78,13 +78,13 @@ class TestPythonUnparseCode(unittest.TestCase): parser.unparse_node(parser.xml) self.assertIsNotNone(parser.source) - self.assertEqual(output, parser.source) + self.assertEqual(parser.source, output) def test_unparse_loop(self): - with open("xml/loop.xml", "r") as f: + with open("ast_parser/test/xml/loop.xml", "r") as f: input = f.read() - with open("xml/loop.out", "r") as f: + with open("ast_parser/test/xml/loop_py.out", "r") as f: output = f.read() parser = PythonUnparser(ET.fromstring(input), True) @@ -110,10 +110,10 @@ class TestPythonUnparseCode(unittest.TestCase): self.assertEqual("return 0\n", parser.source) def test_unparse_unary(self): - with open("xml/unary.xml", "r") as f: + with open("ast_parser/test/xml/unary.xml", "r") as f: input = f.read() - with open("xml/unary.out", "r") as f: + with open("ast_parser/test/xml/unary.out", "r") as f: output = f.read() parser = PythonUnparser(ET.fromstring(input), True) @@ -129,27 +129,27 @@ class TestPythonUnparseCode(unittest.TestCase): parser.unparse_node(parser.xml) self.assertIsNotNone(parser.source) i = ' ' * parser.indentation - self.assertEqual("procedure main() returns integer {\n var integer a = 1;\n a * 42 -> std_output;\n return 0;\n}\n\n", parser.source) + self.assertEqual("def main() -> int:\n a: int = 1\n print(a * 42, end='')\n return 0\n\n\n", parser.source) def test_unparse_args(self): - with open("xml/many_args.xml", 'r') as f: + with open("ast_parser/test/xml/many_args.xml", 'r') as f: input = f.read() - with open("xml/many_args.out", 'r') as f: + with open("ast_parser/test/xml/many_args_pt.out", 'r') as f: output = f.read() parser = PythonUnparser(ET.fromstring(input), True) parser.source = "" parser.unparse_node(parser.xml) self.assertIsNotNone(parser.source) - self.assertEqual(output, parser.source) + self.assertEqual(parser.source, output) def test_unparse_code(self): - with open("xml/test.xml", "r") as input: + with open("ast_parser/test/xml/test.xml", "r") as input: parser = PythonUnparser(ET.fromstring(input.read()), True) parser.unparse() self.assertIsNotNone(parser.source) - with open("input.in", "r") as input: + with open("ast_parser/test/xml/input_py.in", "r") as input: i = input.read() self.assertEqual(i, parser.source) diff --git a/ast_parser/test/test_unparse.py b/ast_parser/test/test_unparse.py index b200a34..7b8c43a 100644 --- a/ast_parser/test/test_unparse.py +++ b/ast_parser/test/test_unparse.py @@ -56,7 +56,7 @@ class TestParseCode(unittest.TestCase): self.assertEqual("{\n var integer a = 1;\n a * 42 -> std_output;\n return 0;\n}\n\n", parser.source) def test_unparse_assignment(self): - with open("xml/assignment.xml", "r") as f: + with open("ast_parser/test/xml/assignment.xml", "r") as f: input = f.read() parser = GazUnparser(ET.fromstring(input), True) parser.source = "" @@ -65,10 +65,10 @@ class TestParseCode(unittest.TestCase): self.assertEqual("C = 30;\n", parser.source) def test_unparse_conditional(self): # TODO test the else-if statements - with open("xml/conditional.xml", "r") as f: + with open("ast_parser/test/xml/conditional.xml", "r") as f: input = f.read() - with open("xml/conditional.out", "r") as f: + with open("ast_parser/test/xml/conditional.out", "r") as f: output = f.read() parser = GazUnparser(ET.fromstring(input), True) @@ -80,10 +80,10 @@ class TestParseCode(unittest.TestCase): self.assertEqual(output, parser.source) def test_unparse_loop(self): - with open("xml/loop.xml", "r") as f: + with open("ast_parser/test/xml/loop.xml", "r") as f: input = f.read() - with open("xml/loop.out", "r") as f: + with open("ast_parser/test/xml/loop.out", "r") as f: output = f.read() parser = GazUnparser(ET.fromstring(input), True) @@ -109,10 +109,10 @@ class TestParseCode(unittest.TestCase): self.assertEqual("return 0;\n", parser.source) def test_unparse_unary(self): - with open("xml/unary.xml", "r") as f: + with open("ast_parser/test/xml/unary.xml", "r") as f: input = f.read() - with open("xml/unary.out", "r") as f: + with open("ast_parser/test/xml/unary.out", "r") as f: output = f.read() parser = GazUnparser(ET.fromstring(input), True) @@ -131,9 +131,9 @@ class TestParseCode(unittest.TestCase): self.assertEqual("procedure main() returns integer {\n var integer a = 1;\n a * 42 -> std_output;\n return 0;\n}\n\n", parser.source) def test_unparse_args(self): - with open("xml/many_args.xml", 'r') as f: + with open("ast_parser/test/xml/many_args.xml", 'r') as f: input = f.read() - with open("xml/many_args.out", 'r') as f: + with open("ast_parser/test/xml/many_args.out", 'r') as f: output = f.read() parser = GazUnparser(ET.fromstring(input), True) parser.source = "" @@ -143,12 +143,12 @@ class TestParseCode(unittest.TestCase): def test_unparse_code(self): - with open("xml/test.xml", "r") as input: + with open("ast_parser/test/xml/test.xml", "r") as input: parser = GazUnparser(ET.fromstring(input.read()), True) parser.unparse() self.assertIsNotNone(parser.source) - with open("input.in", "r") as input: + with open("ast_parser/test/xml/input.in", "r") as input: i = input.read() self.assertEqual(i, parser.source) diff --git a/ast_parser/test/xml/conditional_py.out b/ast_parser/test/xml/conditional_py.out new file mode 100644 index 0000000..e13d6a6 --- /dev/null +++ b/ast_parser/test/xml/conditional_py.out @@ -0,0 +1,4 @@ +if False: + return 0 +else: + return 1 diff --git a/ast_parser/test/input.in b/ast_parser/test/xml/input.in similarity index 100% rename from ast_parser/test/input.in rename to ast_parser/test/xml/input.in diff --git a/ast_parser/test/xml/input_py.in b/ast_parser/test/xml/input_py.in new file mode 100644 index 0000000..23fc8bf --- /dev/null +++ b/ast_parser/test/xml/input_py.in @@ -0,0 +1,6 @@ +def main() -> int: + a: int = 1 + print(a * 42, end='') + return 0 + + diff --git a/ast_parser/test/xml/loop_py.out b/ast_parser/test/xml/loop_py.out new file mode 100644 index 0000000..2a9f099 --- /dev/null +++ b/ast_parser/test/xml/loop_py.out @@ -0,0 +1,4 @@ +while True: + print(a * 42, end='') + + diff --git a/ast_parser/test/xml/many_args_pt.out b/ast_parser/test/xml/many_args_pt.out new file mode 100644 index 0000000..c70ce78 --- /dev/null +++ b/ast_parser/test/xml/many_args_pt.out @@ -0,0 +1,4 @@ +def beeeeees(a: int, b: int, bb: int, bbb: int, bbbb: int, bbbbb: int, bbbbbb: int, bbbbbbb: int, bbbbbbbb: int) -> int: + return 0 + +