initial python unparsing
Took 31 minutes
This commit is contained in:
parent
eb8a47a5f1
commit
d3460d5c0a
|
@ -1,19 +1,74 @@
|
|||
import warnings
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
from ast_parser.gaz_unparser import GazUnparser
|
||||
from ast_parser.general_unparser import GeneralUnparser
|
||||
from constants import *
|
||||
|
||||
|
||||
class PythonUnparser(GeneralUnparser):
|
||||
def to_python_type(ty):
|
||||
if ty == GAZ_INT_KEY:
|
||||
return "int"
|
||||
elif ty == GAZ_BOOL_KEY:
|
||||
return "bool"
|
||||
elif ty == GAZ_FLOAT_KEY:
|
||||
return "float"
|
||||
elif ty == GAZ_CHAR_KEY:
|
||||
return "str"
|
||||
elif ty == GAZ_STRING_KEY:
|
||||
return "str"
|
||||
else:
|
||||
raise Exception("Unknown type: " + ty)
|
||||
|
||||
def unparse_xhs(self, element_in: ET.Element):
|
||||
pass
|
||||
|
||||
def to_python_op(param):
|
||||
if param == "negation" or param == "subtraction":
|
||||
return "-"
|
||||
elif param == "addition":
|
||||
return "+"
|
||||
elif param == "multiplication":
|
||||
return "*"
|
||||
elif param == "division":
|
||||
return "/"
|
||||
elif param == "modulus":
|
||||
return "%"
|
||||
elif param == "power":
|
||||
return "**"
|
||||
elif param == "equality":
|
||||
return "=="
|
||||
elif param == "inequality":
|
||||
return "!="
|
||||
elif param == "less-than":
|
||||
return "<"
|
||||
elif param == "less-than-or-equal":
|
||||
return "<="
|
||||
elif param == "greater-than":
|
||||
return ">"
|
||||
elif param == "greater-than-or-equal":
|
||||
return ">="
|
||||
else:
|
||||
warnings.warn("Warning, unknown operator: " + param)
|
||||
return param
|
||||
|
||||
|
||||
class PythonUnparser(GazUnparser):
|
||||
def __init__(self, ast: ET.Element, debug=False):
|
||||
super().__init__(ast, debug)
|
||||
|
||||
def unparse_top_block(self, element_in: ET.Element):
|
||||
pass
|
||||
|
||||
def unparse_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
|
||||
|
@ -28,17 +83,34 @@ class PythonUnparser(GeneralUnparser):
|
|||
pass
|
||||
|
||||
def unparse_declaration(self, element_in: ET.Element):
|
||||
pass
|
||||
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):
|
||||
pass
|
||||
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_stream(self, element_in: ET.Element):
|
||||
pass
|
||||
|
||||
def unparse_assignment(self, element_in: ET.Element):
|
||||
pass
|
||||
|
||||
|
@ -52,11 +124,17 @@ class PythonUnparser(GeneralUnparser):
|
|||
pass
|
||||
|
||||
def unparse_return(self, element_in: ET.Element):
|
||||
pass
|
||||
self.source += "return "
|
||||
for child in element_in:
|
||||
self.unparse_node(child)
|
||||
self.source += "\n"
|
||||
|
||||
def unparse_literal(self, element_in: ET.Element):
|
||||
pass
|
||||
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)
|
||||
|
||||
def unparse_variable(self, element_in: ET.Element):
|
||||
pass
|
||||
self.source += f"{name}: {ty}"
|
||||
else:
|
||||
super().unparse_variable(element_in)
|
||||
|
||||
|
|
158
ast_parser/test/test_python_unparse.py
Normal file
158
ast_parser/test/test_python_unparse.py
Normal file
|
@ -0,0 +1,158 @@
|
|||
import unittest
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from ast_parser.python_unparser import PythonUnparser
|
||||
|
||||
|
||||
class TestPythonUnparseCode(unittest.TestCase):
|
||||
|
||||
def test_unparse_variable_regular(self):
|
||||
input = '<variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/>'
|
||||
parser = PythonUnparser(ET.fromstring(input), True)
|
||||
parser.source = ""
|
||||
parser.unparse_node(parser.xml)
|
||||
self.assertIsNotNone(parser.source)
|
||||
self.assertEqual("a", parser.source)
|
||||
|
||||
def test_unparse_variable_declaration(self):
|
||||
input = '<variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/>'
|
||||
parser = PythonUnparser(ET.fromstring(input), True)
|
||||
parser.source = ""
|
||||
parser.unparse_variable(parser.xml, True)
|
||||
self.assertIsNotNone(parser.source)
|
||||
self.assertEqual("a: int", parser.source)
|
||||
|
||||
|
||||
def test_unparse_rhs_single(self):
|
||||
input = '<rhs><literal type="int" value="1" /></rhs>'
|
||||
parser = PythonUnparser(ET.fromstring(input), True)
|
||||
parser.source = ""
|
||||
parser.unparse_node(parser.xml)
|
||||
self.assertIsNotNone(parser.source)
|
||||
self.assertEqual("1", parser.source)
|
||||
|
||||
def test_unparse_declaration(self):
|
||||
input = '<declaration><variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/><rhs><literal type="int" value="1" /></rhs></declaration>'
|
||||
parser = PythonUnparser(ET.fromstring(input), True)
|
||||
parser.source = ""
|
||||
parser.unparse_node(parser.xml)
|
||||
self.assertIsNotNone(parser.source)
|
||||
self.assertEqual("a: int = 1\n", parser.source)
|
||||
|
||||
def test_unparse_stream(self):
|
||||
input = ' <stream type="std_output"> <operator op="*" type="unset"> <lhs> <variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/> </lhs> <rhs> <literal type="int" value="42" /> </rhs> </operator></stream>'
|
||||
parser = PythonUnparser(ET.fromstring(input), True)
|
||||
parser.source = ""
|
||||
parser.unparse_node(parser.xml)
|
||||
self.assertIsNotNone(parser.source)
|
||||
self.assertEqual("print(a * 42, end='')\n", parser.source)
|
||||
|
||||
def test_unparse_block(self):
|
||||
input = '<block> <declaration> <variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/> <rhs> <literal type="int" value="1" /> </rhs> </declaration> <stream type="std_output"> <operator op="*" type="unset"> <lhs> <variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/> </lhs> <rhs> <literal type="int" value="42" /> </rhs> </operator> </stream> <return> <literal type="int" value="0" /> </return> </block>'
|
||||
parser = PythonUnparser(ET.fromstring(input), True)
|
||||
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)
|
||||
|
||||
def test_unparse_assignment(self):
|
||||
with open("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)
|
||||
|
||||
def test_unparse_conditional(self): # TODO test the else-if statements
|
||||
with open("xml/conditional.xml", "r") as f:
|
||||
input = f.read()
|
||||
|
||||
with open("xml/conditional.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)
|
||||
|
||||
def test_unparse_loop(self):
|
||||
with open("xml/loop.xml", "r") as f:
|
||||
input = f.read()
|
||||
|
||||
with open("xml/loop.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)
|
||||
|
||||
def test_unparse_operation_single(self):
|
||||
input = '<operator op="multiplication" type="unset"> <lhs> <variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/> </lhs> <rhs> <literal type="int" value="42" /> </rhs> </operator>'
|
||||
parser = PythonUnparser(ET.fromstring(input), True)
|
||||
parser.source = ""
|
||||
parser.unparse_node(parser.xml)
|
||||
self.assertIsNotNone(parser.source)
|
||||
self.assertEqual("a * 42", parser.source)
|
||||
|
||||
def test_unparse_return(self):
|
||||
input = '<return> <literal type="int" value="0" /> </return>'
|
||||
parser = PythonUnparser(ET.fromstring(input), True)
|
||||
parser.source = ""
|
||||
parser.unparse_node(parser.xml)
|
||||
self.assertIsNotNone(parser.source)
|
||||
self.assertEqual("return 0\n", parser.source)
|
||||
|
||||
def test_unparse_unary(self):
|
||||
with open("xml/unary.xml", "r") as f:
|
||||
input = f.read()
|
||||
|
||||
with open("xml/unary.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)
|
||||
|
||||
def test_unparse_routine(self):
|
||||
input = '<procedure name="main" ref_name="_jemrvvseyj" return_type="int" args="()" ><block><declaration><variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/><rhs><literal type="int" value="1" /></rhs></declaration><stream type="std_output"><operator op="*" type="unset"><lhs><variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/></lhs><rhs><literal type="int" value="42" /></rhs></operator></stream><return><literal type="int" value="0" /></return></block></procedure>'
|
||||
parser = PythonUnparser(ET.fromstring(input), True)
|
||||
parser.source = ""
|
||||
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)
|
||||
|
||||
def test_unparse_args(self):
|
||||
with open("xml/many_args.xml", 'r') as f:
|
||||
input = f.read()
|
||||
with open("xml/many_args.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)
|
||||
|
||||
|
||||
def test_unparse_code(self):
|
||||
with open("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:
|
||||
i = input.read()
|
||||
self.assertEqual(i, parser.source)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
Reference in a new issue