Compare commits
No commits in common. "4ee1770092263389bda696320d2b69138a0d0f31" and "ac146b459508859173e658bde975efccf19ccdc9" have entirely different histories.
4ee1770092
...
ac146b4595
|
@ -186,10 +186,7 @@ class AstGenerator:
|
||||||
i = 0
|
i = 0
|
||||||
for i in range(len(cutoffs) - 1):
|
for i in range(len(cutoffs) - 1):
|
||||||
if cutoffs[i] < a < cutoffs[i + 1]:
|
if cutoffs[i] < a < cutoffs[i + 1]:
|
||||||
try:
|
options[i]()
|
||||||
options[i]()
|
|
||||||
except ValueError:
|
|
||||||
break
|
|
||||||
break
|
break
|
||||||
|
|
||||||
def generate_int_real_expr(self):
|
def generate_int_real_expr(self):
|
||||||
|
@ -232,7 +229,7 @@ class AstGenerator:
|
||||||
7: "or",
|
7: "or",
|
||||||
8: "xor",
|
8: "xor",
|
||||||
9: "not",
|
9: "not",
|
||||||
}
|
} # FIXME sometimes this will return a "" op, need to figure out why
|
||||||
|
|
||||||
unary = ["not"]
|
unary = ["not"]
|
||||||
|
|
||||||
|
@ -252,14 +249,10 @@ class AstGenerator:
|
||||||
return
|
return
|
||||||
|
|
||||||
op = ""
|
op = ""
|
||||||
a = random.randint(0, number_line - 1)
|
a = random.randint(0, number_line)
|
||||||
i = 0
|
i = 0
|
||||||
for i in range(len(cutoffs) - 1):
|
for i in range(len(cutoffs) - 1):
|
||||||
if i == 0:
|
if cutoffs[i] < a < cutoffs[i + 1]:
|
||||||
if a < cutoffs[i]:
|
|
||||||
op = options[i]
|
|
||||||
break
|
|
||||||
if cutoffs[i] <= a < cutoffs[i + 1]:
|
|
||||||
op = options[i]
|
op = options[i]
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -271,7 +264,7 @@ class AstGenerator:
|
||||||
self.current_nesting_depth -= 1
|
self.current_nesting_depth -= 1
|
||||||
self.current_ast_element = parent
|
self.current_ast_element = parent
|
||||||
|
|
||||||
def generate_declaration(self, mut=None):
|
def generate_declaration(self):
|
||||||
parent = self.current_ast_element
|
parent = self.current_ast_element
|
||||||
decl_type = self.get_type(GAZ_VAR_TAG)
|
decl_type = self.get_type(GAZ_VAR_TAG)
|
||||||
decl_args = [
|
decl_args = [
|
||||||
|
@ -281,7 +274,7 @@ class AstGenerator:
|
||||||
self.current_ast_element.append(element)
|
self.current_ast_element.append(element)
|
||||||
self.current_ast_element = element
|
self.current_ast_element = element
|
||||||
|
|
||||||
variable = self.generate_variable(decl_type, mut=mut)
|
variable = self.generate_variable(decl_type)
|
||||||
self.current_ast_element.append(variable.xml)
|
self.current_ast_element.append(variable.xml)
|
||||||
self.current_scope.append(variable.name, variable)
|
self.current_scope.append(variable.name, variable)
|
||||||
|
|
||||||
|
@ -290,8 +283,6 @@ class AstGenerator:
|
||||||
|
|
||||||
def generate_binary(self, op, op_type):
|
def generate_binary(self, op, op_type):
|
||||||
parent = self.current_ast_element
|
parent = self.current_ast_element
|
||||||
if op == "":
|
|
||||||
raise ValueError("op is empty!")
|
|
||||||
args = [
|
args = [
|
||||||
("op", op),
|
("op", op),
|
||||||
("type", op_type),
|
("type", op_type),
|
||||||
|
@ -377,10 +368,6 @@ class AstGenerator:
|
||||||
|
|
||||||
|
|
||||||
def generate_assignment(self):
|
def generate_assignment(self):
|
||||||
possible_vars = self.current_scope.get_all_defined_mutable_vars()
|
|
||||||
if len(possible_vars) == 0:
|
|
||||||
raise ValueError("No possible variables to assign to!")
|
|
||||||
|
|
||||||
# same structure as a declaration
|
# same structure as a declaration
|
||||||
parent = self.current_ast_element
|
parent = self.current_ast_element
|
||||||
|
|
||||||
|
@ -388,7 +375,12 @@ class AstGenerator:
|
||||||
self.current_ast_element.append(element)
|
self.current_ast_element.append(element)
|
||||||
self.current_ast_element = element
|
self.current_ast_element = element
|
||||||
|
|
||||||
|
possible_vars = self.current_scope.get_all_defined_mutable_vars()
|
||||||
|
if len(possible_vars) == 0:
|
||||||
|
self.generate_global()
|
||||||
|
possible_vars = self.current_scope.get_all_defined_mutable_vars()
|
||||||
|
|
||||||
|
assert len(possible_vars) > 0
|
||||||
variable = random.choice(possible_vars)
|
variable = random.choice(possible_vars)
|
||||||
|
|
||||||
self.current_ast_element.append(variable.xml)
|
self.current_ast_element.append(variable.xml)
|
||||||
|
@ -415,12 +407,8 @@ class AstGenerator:
|
||||||
|
|
||||||
self.current_ast_element = parent
|
self.current_ast_element = parent
|
||||||
|
|
||||||
def generate_variable(self, var_type: str, mut=None):
|
def generate_variable(self, var_type: str):
|
||||||
if mut is None:
|
return Variable(self.get_name(GAZ_VAR_TAG), var_type, self.get_qualifier())
|
||||||
return Variable(self.get_name(GAZ_VAR_TAG), var_type, self.get_qualifier())
|
|
||||||
else:
|
|
||||||
return Variable(self.get_name(GAZ_VAR_TAG), var_type, mut)
|
|
||||||
|
|
||||||
|
|
||||||
def generate_literal(self, var_type: str):
|
def generate_literal(self, var_type: str):
|
||||||
args = [
|
args = [
|
||||||
|
|
|
@ -126,7 +126,7 @@ class TestGeneration(unittest.TestCase):
|
||||||
self.ast_gen.current_ast_element = self.ast_gen.ast
|
self.ast_gen.current_ast_element = self.ast_gen.ast
|
||||||
self.ast_gen.generate_conditional()
|
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"))
|
self.assertIsNotNone(self.ast_gen.current_ast_element.find("conditional"))
|
||||||
conditional = self.ast_gen.ast.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"))
|
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")
|
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("block"))
|
||||||
self.assertIsNotNone(routine.find("argument"))
|
self.assertIsNotNone(routine.find("argument"))
|
||||||
|
@ -175,15 +175,15 @@ class TestGeneration(unittest.TestCase):
|
||||||
self.assertIsNotNone(self.ast_gen.ast.find("function"))
|
self.assertIsNotNone(self.ast_gen.ast.find("function"))
|
||||||
routine = 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("block"))
|
||||||
self.assertIsNotNone(routine.find("argument"))
|
self.assertIsNotNone(routine.find("argument"))
|
||||||
|
|
||||||
block = routine.find("block")
|
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")
|
rets = block.find("return")
|
||||||
# print(rets)
|
print(rets)
|
||||||
self.assertLess(0, len(rets))
|
self.assertLess(0, len(rets))
|
||||||
self.assertTrue(reachable_return(block))
|
self.assertTrue(reachable_return(block))
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ class TestGeneration(unittest.TestCase):
|
||||||
self.assertIsNotNone(self.ast_gen.ast.find("procedure"))
|
self.assertIsNotNone(self.ast_gen.ast.find("procedure"))
|
||||||
out = 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("main", out.get("name"))
|
||||||
self.assertEqual("int", out.get("return_type"))
|
self.assertEqual("int", out.get("return_type"))
|
||||||
|
@ -212,7 +212,7 @@ class TestGeneration(unittest.TestCase):
|
||||||
|
|
||||||
self.assertIsNotNone(self.ast_gen.ast)
|
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")
|
procedures = self.ast_gen.ast.findall("procedure")
|
||||||
self.assertLess(0, len(procedures))
|
self.assertLess(0, len(procedures))
|
||||||
|
@ -223,93 +223,6 @@ class TestGeneration(unittest.TestCase):
|
||||||
main = True
|
main = True
|
||||||
self.assertTrue(main)
|
self.assertTrue(main)
|
||||||
|
|
||||||
def test_no_op_operation(self):
|
|
||||||
for l in range(1000):
|
|
||||||
# print("iteration: " + str(l))
|
|
||||||
self.ast_gen.ast = ET.Element("block")
|
|
||||||
self.ast_gen.current_ast_element = self.ast_gen.ast
|
|
||||||
self.ast_gen.generate_int_real_expr()
|
|
||||||
# self.write_ast()
|
|
||||||
|
|
||||||
if self.ast_gen.ast.find("operator") is None:
|
|
||||||
l -= 1
|
|
||||||
continue
|
|
||||||
operator = self.ast_gen.ast.find("operator")
|
|
||||||
self.assertFalse(self.is_no_op(operator))
|
|
||||||
|
|
||||||
def test_create_global(self):
|
|
||||||
self.ast_gen.ast = ET.Element("block")
|
|
||||||
self.ast_gen.current_ast_element = self.ast_gen.ast
|
|
||||||
self.ast_gen.generate_main()
|
|
||||||
|
|
||||||
global_block = self.ast_gen.current_ast_element
|
|
||||||
global_scope = self.ast_gen.current_scope
|
|
||||||
|
|
||||||
self.assertIsNotNone(self.ast_gen.ast.find("procedure"))
|
|
||||||
self.ast_gen.current_ast_element = self.ast_gen.ast.find("procedure")
|
|
||||||
self.ast_gen.generate_global()
|
|
||||||
|
|
||||||
self.assertGreater(len(global_scope.symbols), 0)
|
|
||||||
self.assertIsNotNone(global_block.find("declaration"))
|
|
||||||
|
|
||||||
def test_generate_assignment_no_declaration(self):
|
|
||||||
for l in range(1000):
|
|
||||||
self.ast_gen.ast = ET.Element("block")
|
|
||||||
self.ast_gen.current_ast_element = self.ast_gen.ast
|
|
||||||
self.ast_gen.generate_declaration(mut='var')
|
|
||||||
self.ast_gen.generate_assignment()
|
|
||||||
|
|
||||||
self.assertIsNotNone(self.ast_gen.ast.find("assignment"))
|
|
||||||
|
|
||||||
decl = self.ast_gen.ast.find("assignment")
|
|
||||||
self.assertIsNone(decl.find("declaration"))
|
|
||||||
|
|
||||||
def test_failing_assignment(self):
|
|
||||||
self.ast_gen.ast = ET.Element("block")
|
|
||||||
self.ast_gen.current_ast_element = self.ast_gen.ast
|
|
||||||
self.ast_gen.generate_main()
|
|
||||||
with self.assertRaises(ValueError):
|
|
||||||
self.ast_gen.generate_assignment()
|
|
||||||
|
|
||||||
self.assertIsNone(self.ast_gen.ast.find("assignment"))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def is_no_op(self, operator):
|
|
||||||
"""
|
|
||||||
recursively check if operator is a no-op
|
|
||||||
@param operator:
|
|
||||||
@return:
|
|
||||||
"""
|
|
||||||
res = False
|
|
||||||
if operator.get("op") == '':
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
lhs = operator.find("lhs")
|
|
||||||
rhs = operator.find("rhs")
|
|
||||||
if lhs.find("operator") is not None:
|
|
||||||
res = self.is_no_op(lhs.find("operator"))
|
|
||||||
elif lhs.find("unary") is not None:
|
|
||||||
res = self.is_no_op(lhs.find("unary"))
|
|
||||||
elif rhs.find("operator") is not None:
|
|
||||||
res = self.is_no_op(rhs.find("operator"))
|
|
||||||
elif rhs.find("unary") is not None:
|
|
||||||
res = self.is_no_op(lhs.find("unary"))
|
|
||||||
|
|
||||||
return res
|
|
||||||
|
|
||||||
def write_ast(self):
|
|
||||||
dom = xml.dom.minidom.parseString(ET.tostring(self.ast_gen.ast).decode('utf-8'))
|
|
||||||
pretty: str = dom.toprettyxml()
|
|
||||||
|
|
||||||
randint = random.randint(0, 1000)
|
|
||||||
print(randint)
|
|
||||||
with open("debug/ast/debug_{}.xml".format(randint), 'w') as f:
|
|
||||||
f.write(pretty)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
with open("config.yaml", 'r') as stream:
|
with open("config.yaml", 'r') as stream:
|
||||||
|
|
|
@ -3,7 +3,7 @@ import unittest
|
||||||
|
|
||||||
class MyTestCase(unittest.TestCase):
|
class MyTestCase(unittest.TestCase):
|
||||||
def test_something(self):
|
def test_something(self):
|
||||||
pass
|
self.assertEqual(True, False) # add assertion here
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -7,7 +7,7 @@ from ast_parser.general_unparser import GeneralUnparser
|
||||||
from constants import *
|
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:
|
if ty == GAZ_INT_KEY:
|
||||||
return "integer"
|
return "integer"
|
||||||
elif ty == GAZ_BOOL_KEY:
|
elif ty == GAZ_BOOL_KEY:
|
||||||
|
@ -63,38 +63,214 @@ def to_gaz_op(param):
|
||||||
return param
|
return param
|
||||||
|
|
||||||
|
|
||||||
class GazUnparser(GeneralUnparser):
|
class AstParser(GeneralUnparser):
|
||||||
def __init__(self, input_ast, from_xml: bool = False):
|
def __init__(self, input: str or ET.Element, from_xml: bool = False):
|
||||||
super().__init__(input=input_ast, from_xml=from_xml,
|
if from_xml:
|
||||||
endline=";\n",
|
self.xml = input
|
||||||
instream_end_delimiter=" <- std_input",
|
self.input = None
|
||||||
outstream_end_delimiter=" -> std_output", )
|
|
||||||
|
|
||||||
def format_variable(self, mut, ty, name, declaration: bool = False):
|
|
||||||
if declaration:
|
|
||||||
return "{} {} {}".format(mut, ty, name)
|
|
||||||
else:
|
else:
|
||||||
return "{}".format(name)
|
self.input = input
|
||||||
|
self.xml = None
|
||||||
|
|
||||||
def translate_value(self, val):
|
self.indentation = 0
|
||||||
if val in ["True", "False"]:
|
|
||||||
return val.lower()
|
def unparse(self):
|
||||||
|
"""
|
||||||
|
@brief unparses the xml into valid gazprea code
|
||||||
|
|
||||||
|
:return: a string of valid gazprea code
|
||||||
|
"""
|
||||||
|
self.input = ""
|
||||||
|
for node in self.xml:
|
||||||
|
self.unparse_node(node)
|
||||||
|
|
||||||
|
def unparse_node(self, node):
|
||||||
|
if node.tag not in [GAZ_VAR_TAG, GAZ_RHS_TAG, GAZ_LHS_TAG, GAZ_LIT_TAG, GAZ_OPERATOR_TAG]:
|
||||||
|
self.input += " " * self.indentation
|
||||||
|
|
||||||
|
if node.tag == GAZ_BLOCK_TAG:
|
||||||
|
self.unparse_block(node)
|
||||||
|
elif node.tag == GAZ_DECLARATION_TAG:
|
||||||
|
self.unparse_declaration(node)
|
||||||
|
elif node.tag == GAZ_RETURN_TAG:
|
||||||
|
self.unparse_return(node)
|
||||||
|
elif node.tag == GAZ_OPERATOR_TAG:
|
||||||
|
self.unparse_operator(node)
|
||||||
|
elif node.tag == GAZ_UNARY_OPERATOR_TAG:
|
||||||
|
self.unparse_unary(node)
|
||||||
|
elif node.tag == GAZ_STREAM_TAG:
|
||||||
|
self.unparse_stream(node)
|
||||||
|
elif node.tag == GAZ_LIT_TAG:
|
||||||
|
self.unparse_literal(node)
|
||||||
|
elif node.tag == GAZ_PROCEDURE_TAG or node.tag == GAZ_FUNCTION_TAG:
|
||||||
|
self.unparse_routine(node)
|
||||||
|
elif node.tag == GAZ_VAR_TAG:
|
||||||
|
self.unparse_variable(node)
|
||||||
|
elif node.tag == GAZ_RHS_TAG or node.tag == GAZ_LHS_TAG:
|
||||||
|
self._xhs_unparse(node)
|
||||||
|
elif node.tag == GAZ_LIT_TAG:
|
||||||
|
self.unparse_literal(node)
|
||||||
|
elif node.tag == GAZ_ASSIGNMENT_TAG:
|
||||||
|
self.unparse_assignment(node)
|
||||||
|
elif node.tag == GAZ_IF_TAG:
|
||||||
|
self.unparse_conditional(node)
|
||||||
|
elif node.tag == GAZ_LOOP_TAG:
|
||||||
|
self.unparse_loop(node)
|
||||||
else:
|
else:
|
||||||
return str(val)
|
raise Exception("Unknown tag: " + node.tag)
|
||||||
|
|
||||||
def translate_op(self, param):
|
def unparse_block(self, node):
|
||||||
return to_gaz_op(param)
|
self.input += "{\n"
|
||||||
|
self.indentation += 4
|
||||||
|
for child in node:
|
||||||
|
self.unparse_node(child)
|
||||||
|
self.indentation -= 4
|
||||||
|
if node.get(GAZ_TY_KEY) is None:
|
||||||
|
self.input += "}\n\n"
|
||||||
|
elif node.get(GAZ_TY_KEY) in [GAZ_TRUE_BLOCK_TAG, GAZ_FALSE_BLOCK_TAG]:
|
||||||
|
self.input += "}"
|
||||||
|
|
||||||
def translate_type(self, ty):
|
def unparse_declaration(self, node):
|
||||||
return to_gazprea_type(ty)
|
variable = node.find(GAZ_VAR_TAG)
|
||||||
|
rhs = node.find(GAZ_RHS_TAG)
|
||||||
|
self.unparse_variable(variable, True)
|
||||||
|
self.input += " = "
|
||||||
|
self.unparse_node(rhs)
|
||||||
|
self.input += ";\n"
|
||||||
|
|
||||||
def function_declaration(self, xml_tag, args, name, return_type):
|
def unparse_variable(self, node, is_declaration = False):
|
||||||
return "{} {}{} {} ".format(
|
if is_declaration:
|
||||||
xml_tag,
|
mut = node.get(GAZ_QUALIFIER_KEY)
|
||||||
name,
|
type = to_gazprea_type(node.get(GAZ_TY_KEY))
|
||||||
|
name = node.get(GAZ_NAME_KEY)
|
||||||
|
|
||||||
|
self.input += "{} {} {}".format(mut, type, name)
|
||||||
|
else:
|
||||||
|
self.input += "{}".format(node.get(GAZ_NAME_KEY))
|
||||||
|
|
||||||
|
def unparse_stream(self, node):
|
||||||
|
if node.get(GAZ_TY_KEY) == GAZ_OUT_STREAM:
|
||||||
|
self.unparse_outstream(node)
|
||||||
|
elif node.get(GAZ_TY_KEY) == GAZ_IN_STREAM:
|
||||||
|
self.unparse_instream(node)
|
||||||
|
|
||||||
|
def unparse_instream(self, node):
|
||||||
|
for child in node:
|
||||||
|
self.unparse_node(child)
|
||||||
|
|
||||||
|
self.input += "<- {};\n".format(GAZ_IN_STREAM)
|
||||||
|
|
||||||
|
def unparse_outstream(self, node):
|
||||||
|
for child in node:
|
||||||
|
self.unparse_node(child)
|
||||||
|
|
||||||
|
self.input += " -> {};\n".format(GAZ_OUT_STREAM)
|
||||||
|
|
||||||
|
def unparse_literal(self, node):
|
||||||
|
self.input += "{}".format(to_gaz_value(node.get(GAZ_VAL_KEY)))
|
||||||
|
|
||||||
|
def _xhs_unparse(self, node):
|
||||||
|
for child in node:
|
||||||
|
self.unparse_node(child)
|
||||||
|
|
||||||
|
def unparse_operator(self, node):
|
||||||
|
self._xhs_unparse(node.find(GAZ_LHS_TAG))
|
||||||
|
self.input += " {} ".format(to_gaz_op(node.get("op")))
|
||||||
|
self._xhs_unparse(node.find(GAZ_RHS_TAG))
|
||||||
|
|
||||||
|
def unparse_return(self, node):
|
||||||
|
self.input += "return "
|
||||||
|
for child in node:
|
||||||
|
self.unparse_node(child)
|
||||||
|
self.input += ";\n"
|
||||||
|
|
||||||
|
def unparse_routine(self, node):
|
||||||
|
return_type = ""
|
||||||
|
if node.get(GAZ_RETURN_KEY) not in [None, GAZ_VOID_TYPE, ""]:
|
||||||
|
return_type = "returns " + to_gazprea_type(node.get(GAZ_RETURN_KEY))
|
||||||
|
|
||||||
|
args = []
|
||||||
|
for child in node:
|
||||||
|
if child.tag == GAZ_ARG_TAG:
|
||||||
|
args.append(child)
|
||||||
|
|
||||||
|
args = self.unparse_argument(args)
|
||||||
|
|
||||||
|
self.input += "{} {}{} {} ".format(
|
||||||
|
node.tag,
|
||||||
|
node.get(GAZ_NAME_KEY),
|
||||||
args,
|
args,
|
||||||
return_type,
|
return_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
def format_single_arg(self, ty, name):
|
for child in node:
|
||||||
return "{} {}".format(ty, name)
|
if child.tag == GAZ_ARG_TAG:
|
||||||
|
continue
|
||||||
|
self.unparse_node(child)
|
||||||
|
|
||||||
|
# cls.input += "}\n\n" #blocks are already there
|
||||||
|
|
||||||
|
def unparse_argument(self, nodes):
|
||||||
|
if len(nodes) == 0:
|
||||||
|
return "()"
|
||||||
|
args = "("
|
||||||
|
for i in range(len(nodes)):
|
||||||
|
args += _unparse_arg(nodes[i])
|
||||||
|
if i < len(nodes) - 1:
|
||||||
|
args += ", "
|
||||||
|
|
||||||
|
args += ")"
|
||||||
|
return args
|
||||||
|
|
||||||
|
def unparse_assignment(self, element_in: ET.Element):
|
||||||
|
self.unparse_variable(element_in.find(GAZ_VAR_TAG), False)
|
||||||
|
self.input += " = "
|
||||||
|
self.unparse_node(element_in.find(GAZ_RHS_TAG))
|
||||||
|
self.input += ";\n"
|
||||||
|
|
||||||
|
def unparse_conditional(self, element_in: ET.Element):
|
||||||
|
self.input += "if ("
|
||||||
|
i = 0
|
||||||
|
for node in element_in:
|
||||||
|
if node.tag == GAZ_IF_TAG:
|
||||||
|
self.input += " else "
|
||||||
|
self.unparse_conditional(node)
|
||||||
|
elif node.tag != GAZ_BLOCK_TAG:
|
||||||
|
self.unparse_node(node)
|
||||||
|
self.input += ") "
|
||||||
|
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.input += " else "
|
||||||
|
self.unparse_node(node)
|
||||||
|
else:
|
||||||
|
self.unparse_node(node)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
def unparse_loop(self, element_in: ET.Element):
|
||||||
|
self.input += "loop ("
|
||||||
|
i = 0
|
||||||
|
for node in element_in:
|
||||||
|
if node.tag != GAZ_BLOCK_TAG:
|
||||||
|
self.unparse_node(node)
|
||||||
|
self.input += ") "
|
||||||
|
elif node.tag == GAZ_BLOCK_TAG:
|
||||||
|
self.unparse_node(node)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
def unparse_routine_call(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def unparse_statement(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def unparse_top_block(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def unparse_unary(self, element_in: ET.Element):
|
||||||
|
self.input += " {}".format(to_gaz_op(element_in.get("op")))
|
||||||
|
self._xhs_unparse(element_in.find(GAZ_RHS_TAG))
|
||||||
|
|
||||||
|
def unparse_expression(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
|
@ -1,303 +1,82 @@
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
from constants import *
|
|
||||||
|
|
||||||
|
class GeneralUnparser(ABC):
|
||||||
class GeneralUnparser:
|
@abstractmethod
|
||||||
def __init__(self, input: str or ET.Element,
|
def unparse(self, element_in: ET.Element):
|
||||||
from_xml: bool = False,
|
|
||||||
indentation_character: str = " ",
|
|
||||||
endline: str = "\n",
|
|
||||||
instream_begin_delimiter: str = "",
|
|
||||||
instream_end_delimiter: str = "",
|
|
||||||
outstream_begin_delimiter: str = "",
|
|
||||||
outstream_end_delimiter: str = "",
|
|
||||||
return_string: str = "return",
|
|
||||||
function_return_type_indicator_predicate: str = "returns",
|
|
||||||
arg_start_delimiter: str = "(",
|
|
||||||
arg_end_delimiter: str = ")",
|
|
||||||
arg_separator: str = ",",
|
|
||||||
loop_start_delimiter: str = "loop (",
|
|
||||||
loop_end_delimiter: str = ")",
|
|
||||||
assignment_character: str = '=',
|
|
||||||
conditional_start_delimiter: str = "if (",
|
|
||||||
conditional_end_delimiter: str = ")",
|
|
||||||
conditional_case_delimiter: str = "else if (",
|
|
||||||
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
|
|
||||||
self.indentation = 0
|
|
||||||
|
|
||||||
self.stream_delimiters = {
|
|
||||||
"instream_begin": instream_begin_delimiter,
|
|
||||||
"instream_end": instream_end_delimiter,
|
|
||||||
"outstream_begin": outstream_begin_delimiter,
|
|
||||||
"outstream_end": outstream_end_delimiter
|
|
||||||
}
|
|
||||||
|
|
||||||
self.arg_delimiters = (arg_start_delimiter, arg_end_delimiter, arg_separator)
|
|
||||||
self.loop_delimiters = (loop_start_delimiter, loop_end_delimiter)
|
|
||||||
self.conditional_delimiters = (conditional_start_delimiter,
|
|
||||||
conditional_end_delimiter,
|
|
||||||
conditional_case_delimiter,
|
|
||||||
conditional_else_delimiter)
|
|
||||||
|
|
||||||
self.return_string = return_string
|
|
||||||
self.return_indicator = function_return_type_indicator_predicate
|
|
||||||
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
|
|
||||||
else:
|
|
||||||
self.source = input
|
|
||||||
self.xml = None
|
|
||||||
|
|
||||||
def unparse(self):
|
|
||||||
"""
|
|
||||||
@brief unparses the xml into valid gazprea code
|
|
||||||
|
|
||||||
:return: a string of valid gazprea code
|
|
||||||
"""
|
|
||||||
self.source = ""
|
|
||||||
for node in self.xml:
|
|
||||||
self.unparse_node(node)
|
|
||||||
|
|
||||||
def unparse_node(self, node):
|
|
||||||
if node.tag not in [GAZ_VAR_TAG, GAZ_RHS_TAG, GAZ_LHS_TAG, GAZ_LIT_TAG, GAZ_OPERATOR_TAG]:
|
|
||||||
self.source += self.indentation_character * self.indentation
|
|
||||||
|
|
||||||
if node.tag == GAZ_BLOCK_TAG:
|
|
||||||
self.unparse_block(node)
|
|
||||||
elif node.tag == GAZ_DECLARATION_TAG:
|
|
||||||
self.unparse_declaration(node)
|
|
||||||
elif node.tag == GAZ_RETURN_TAG:
|
|
||||||
self.unparse_return(node)
|
|
||||||
elif node.tag == GAZ_OPERATOR_TAG:
|
|
||||||
self.unparse_operator(node)
|
|
||||||
elif node.tag == GAZ_UNARY_OPERATOR_TAG:
|
|
||||||
self.unparse_unary(node)
|
|
||||||
elif node.tag == GAZ_STREAM_TAG:
|
|
||||||
self.unparse_stream(node)
|
|
||||||
elif node.tag == GAZ_LIT_TAG:
|
|
||||||
self.unparse_literal(node)
|
|
||||||
elif node.tag == GAZ_PROCEDURE_TAG or node.tag == GAZ_FUNCTION_TAG:
|
|
||||||
self.unparse_routine(node)
|
|
||||||
elif node.tag == GAZ_VAR_TAG:
|
|
||||||
self.unparse_variable(node)
|
|
||||||
elif node.tag == GAZ_RHS_TAG or node.tag == GAZ_LHS_TAG:
|
|
||||||
self.unparse_xhs(node)
|
|
||||||
elif node.tag == GAZ_LIT_TAG:
|
|
||||||
self.unparse_literal(node)
|
|
||||||
elif node.tag == GAZ_ASSIGNMENT_TAG:
|
|
||||||
self.unparse_assignment(node)
|
|
||||||
elif node.tag == GAZ_IF_TAG:
|
|
||||||
self.unparse_conditional(node)
|
|
||||||
elif node.tag == GAZ_LOOP_TAG:
|
|
||||||
self.unparse_loop(node)
|
|
||||||
else:
|
|
||||||
raise Exception("Unknown tag: " + node.tag)
|
|
||||||
|
|
||||||
def unparse_block(self, node):
|
|
||||||
self.source += f"{self.block_delimiters[0]}\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 += f"{self.block_delimiters[1]}\n\n"
|
|
||||||
elif node.get(GAZ_TY_KEY) in [GAZ_TRUE_BLOCK_TAG, GAZ_FALSE_BLOCK_TAG]:
|
|
||||||
self.source += f"{self.block_delimiters[1]}"
|
|
||||||
|
|
||||||
def unparse_declaration(self, node, declaration_op: str = '='):
|
|
||||||
variable = node.find(GAZ_VAR_TAG)
|
|
||||||
rhs = node.find(GAZ_RHS_TAG)
|
|
||||||
self.unparse_variable(variable, True)
|
|
||||||
self.source += f" {declaration_op} "
|
|
||||||
self.unparse_node(rhs)
|
|
||||||
self.source += self.endline
|
|
||||||
|
|
||||||
def unparse_variable(self, node, is_declaration: bool = False):
|
|
||||||
if node is None:
|
|
||||||
raise ValueError("Node is None")
|
|
||||||
mut = node.get(GAZ_QUALIFIER_KEY)
|
|
||||||
type = node.get(GAZ_TY_KEY)
|
|
||||||
name = node.get(GAZ_NAME_KEY)
|
|
||||||
|
|
||||||
self.source += self.format_variable(mut, self.translate_type(type), name, is_declaration)
|
|
||||||
|
|
||||||
def unparse_stream(self, node):
|
|
||||||
if node.get(GAZ_TY_KEY) == GAZ_OUT_STREAM:
|
|
||||||
self.unparse_outstream(node)
|
|
||||||
elif node.get(GAZ_TY_KEY) == GAZ_IN_STREAM:
|
|
||||||
self.unparse_instream(node)
|
|
||||||
|
|
||||||
def unparse_instream(self, node):
|
|
||||||
self.source += self.stream_delimiters["instream_begin"]
|
|
||||||
for child in node:
|
|
||||||
self.unparse_node(child)
|
|
||||||
|
|
||||||
self.source += self.stream_delimiters["instream_end"]
|
|
||||||
self.source += self.endline
|
|
||||||
|
|
||||||
def unparse_outstream(self, node):
|
|
||||||
self.source += self.stream_delimiters["outstream_begin"]
|
|
||||||
for child in node:
|
|
||||||
self.unparse_node(child)
|
|
||||||
|
|
||||||
self.source += self.stream_delimiters["outstream_end"]
|
|
||||||
self.source += self.endline
|
|
||||||
|
|
||||||
def unparse_literal(self, node):
|
|
||||||
self.source += "{}".format(self.translate_value(node.get(GAZ_VAL_KEY)))
|
|
||||||
|
|
||||||
def unparse_xhs(self, node):
|
|
||||||
for child in node:
|
|
||||||
self.unparse_node(child)
|
|
||||||
|
|
||||||
def unparse_operator(self, node):
|
|
||||||
self.unparse_xhs(node.find(GAZ_LHS_TAG))
|
|
||||||
self.source += " {} ".format(self.translate_op(node.get("op")))
|
|
||||||
self.unparse_xhs(node.find(GAZ_RHS_TAG))
|
|
||||||
|
|
||||||
def unparse_return(self, node):
|
|
||||||
self.source += self.return_string + " "
|
|
||||||
for child in node:
|
|
||||||
self.unparse_node(child)
|
|
||||||
self.source += self.endline
|
|
||||||
|
|
||||||
def unparse_routine(self, node):
|
|
||||||
return_type = ""
|
|
||||||
if node.get(GAZ_RETURN_KEY) not in [None, GAZ_VOID_TYPE, ""]:
|
|
||||||
return_type = self.return_indicator + " " + self.translate_type(node.get(GAZ_RETURN_KEY))
|
|
||||||
|
|
||||||
args = []
|
|
||||||
for child in node:
|
|
||||||
if child.tag == GAZ_ARG_TAG:
|
|
||||||
args.append(child)
|
|
||||||
|
|
||||||
args = self.unparse_argument(args)
|
|
||||||
|
|
||||||
name = node.get(GAZ_NAME_KEY)
|
|
||||||
|
|
||||||
self.source += self.function_declaration(node.tag, args, name, return_type)
|
|
||||||
|
|
||||||
for child in node:
|
|
||||||
if child.tag == GAZ_ARG_TAG:
|
|
||||||
continue
|
|
||||||
self.unparse_node(child)
|
|
||||||
|
|
||||||
# cls.source += "}\n\n" #blocks are already there
|
|
||||||
|
|
||||||
def function_declaration(self, xml_tag, args, name, return_type):
|
|
||||||
return "{} {}{} {} ".format(
|
|
||||||
xml_tag,
|
|
||||||
name,
|
|
||||||
args,
|
|
||||||
return_type,
|
|
||||||
)
|
|
||||||
|
|
||||||
def unparse_argument(self, nodes):
|
|
||||||
if len(nodes) == 0:
|
|
||||||
return self.arg_delimiters[0] + self.arg_delimiters[1]
|
|
||||||
args = self.arg_delimiters[0]
|
|
||||||
for i in range(len(nodes)):
|
|
||||||
args += self.unparse_single_arg(nodes[i])
|
|
||||||
if i < len(nodes) - 1:
|
|
||||||
args += self.arg_delimiters[2] + " "
|
|
||||||
|
|
||||||
args += self.arg_delimiters[1]
|
|
||||||
return args
|
|
||||||
|
|
||||||
def unparse_assignment(self, element_in: ET.Element):
|
|
||||||
self.unparse_variable(element_in.find(GAZ_VAR_TAG), False)
|
|
||||||
self.source += " {} ".format(self.assignment_character)
|
|
||||||
self.unparse_node(element_in.find(GAZ_RHS_TAG))
|
|
||||||
self.source += self.endline
|
|
||||||
|
|
||||||
def unparse_conditional(self, element_in: ET.Element):
|
|
||||||
self.source += self.conditional_delimiters[0]
|
|
||||||
i = 0
|
|
||||||
for node in element_in:
|
|
||||||
if node.tag == GAZ_IF_TAG:
|
|
||||||
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)
|
|
||||||
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:
|
|
||||||
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)
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
def unparse_loop(self, element_in: ET.Element):
|
|
||||||
self.source += self.loop_delimiters[0]
|
|
||||||
i = 0
|
|
||||||
for node in element_in:
|
|
||||||
if node.tag != GAZ_BLOCK_TAG:
|
|
||||||
self.unparse_node(node)
|
|
||||||
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
|
|
||||||
|
|
||||||
def unparse_unary(self, element_in: ET.Element):
|
|
||||||
self.source += " {}".format(self.translate_op(element_in.get("op")))
|
|
||||||
self.unparse_xhs(element_in.find(GAZ_RHS_TAG))
|
|
||||||
|
|
||||||
def unparse_single_arg(self, param):
|
|
||||||
return self.format_single_arg(self.translate_type(param.get(GAZ_TY_KEY)), param.get(GAZ_NAME_KEY))
|
|
||||||
|
|
||||||
def unparse_routine_call(self, element_in: ET.Element):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def unparse_statement(self, element_in: ET.Element):
|
@abstractmethod
|
||||||
|
def unparse_node(self, element_in: ET.Element):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def unparse_top_block(self, element_in: ET.Element):
|
def unparse_top_block(self, element_in: ET.Element):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def unparse_block(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def unparse_routine(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def unparse_argument(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def unparse_statement(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def unparse_expression(self, element_in: ET.Element):
|
def unparse_expression(self, element_in: ET.Element):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def format_variable(self, mut, name, value, declaration: bool = False):
|
@abstractmethod
|
||||||
raise NotImplementedError
|
def unparse_declaration(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
def translate_value(self, val):
|
@abstractmethod
|
||||||
raise NotImplementedError
|
def unparse_operator(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
def translate_op(self, param):
|
@abstractmethod
|
||||||
raise NotImplementedError
|
def unparse_unary(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
def translate_type(self, ty):
|
@abstractmethod
|
||||||
raise NotImplementedError
|
def unparse_stream(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
def format_single_arg(self, param, param1):
|
@abstractmethod
|
||||||
raise NotImplementedError
|
def unparse_assignment(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def unparse_conditional(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def unparse_loop(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def unparse_routine_call(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def unparse_return(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def unparse_literal(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def unparse_variable(self, element_in: ET.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
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 *
|
|
||||||
|
|
||||||
|
|
||||||
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 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(GeneralUnparser):
|
|
||||||
def __init__(self, ast: ET.Element, debug=False):
|
|
||||||
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 format_variable(self, mut, ty, name, declaration: bool = False):
|
|
||||||
if declaration:
|
|
||||||
return "{}: {}".format(name, ty)
|
|
||||||
else:
|
|
||||||
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)
|
|
|
@ -1,158 +0,0 @@
|
||||||
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(parser.source, "\n a: int = 1\n print(a * 42, end='')\n return 0\n\n\n")
|
|
||||||
|
|
||||||
def test_unparse_assignment(self):
|
|
||||||
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)
|
|
||||||
|
|
||||||
def test_unparse_conditional(self): # TODO test the else-if statements
|
|
||||||
with open("ast_parser/test/xml/conditional.xml", "r") as f:
|
|
||||||
input = f.read()
|
|
||||||
|
|
||||||
with open("ast_parser/test/xml/conditional_py.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(parser.source, output)
|
|
||||||
|
|
||||||
def test_unparse_loop(self):
|
|
||||||
with open("ast_parser/test/xml/loop.xml", "r") as f:
|
|
||||||
input = f.read()
|
|
||||||
|
|
||||||
with open("ast_parser/test/xml/loop_py.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("ast_parser/test/xml/unary.xml", "r") as f:
|
|
||||||
input = f.read()
|
|
||||||
|
|
||||||
with open("ast_parser/test/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("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("ast_parser/test/xml/many_args.xml", 'r') as f:
|
|
||||||
input = f.read()
|
|
||||||
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(parser.source, output)
|
|
||||||
|
|
||||||
|
|
||||||
def test_unparse_code(self):
|
|
||||||
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("ast_parser/test/xml/input_py.in", "r") as input:
|
|
||||||
i = input.read()
|
|
||||||
self.assertEqual(i, parser.source)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
|
@ -1,6 +1,6 @@
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from ast_parser.gaz_unparser import GazUnparser
|
from ast_parser.gaz_unparser import AstParser
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,149 +8,149 @@ class TestParseCode(unittest.TestCase):
|
||||||
|
|
||||||
def test_unparse_variable_regular(self):
|
def test_unparse_variable_regular(self):
|
||||||
input = '<variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/>'
|
input = '<variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/>'
|
||||||
parser = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual("a", parser.source)
|
self.assertEqual("a", parser.input)
|
||||||
|
|
||||||
def test_unparse_variable_declaration(self):
|
def test_unparse_variable_declaration(self):
|
||||||
input = '<variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/>'
|
input = '<variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/>'
|
||||||
parser = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_variable(parser.xml, True)
|
parser.unparse_variable(parser.xml, True)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual("var integer a", parser.source)
|
self.assertEqual("var integer a", parser.input)
|
||||||
|
|
||||||
|
|
||||||
def test_unparse_rhs_single(self):
|
def test_unparse_rhs_single(self):
|
||||||
input = '<rhs><literal type="int" value="1" /></rhs>'
|
input = '<rhs><literal type="int" value="1" /></rhs>'
|
||||||
parser = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual("1", parser.source)
|
self.assertEqual("1", parser.input)
|
||||||
|
|
||||||
def test_unparse_declaration(self):
|
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>'
|
input = '<declaration><variable mut="var" type="int" name="a" ref_name="_lsiyjvtbvnpmlml"/><rhs><literal type="int" value="1" /></rhs></declaration>'
|
||||||
parser = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual("var integer a = 1;\n", parser.source)
|
self.assertEqual("var integer a = 1;\n", parser.input)
|
||||||
|
|
||||||
def test_unparse_stream(self):
|
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>'
|
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 = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual("a * 42 -> std_output;\n", parser.source)
|
self.assertEqual("a * 42 -> std_output;\n", parser.input)
|
||||||
|
|
||||||
def test_unparse_block(self):
|
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>'
|
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 = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual("{\n var integer a = 1;\n a * 42 -> std_output;\n return 0;\n}\n\n", parser.source)
|
self.assertEqual("{\n var integer a = 1;\n a * 42 -> std_output;\n return 0;\n}\n\n", parser.input)
|
||||||
|
|
||||||
def test_unparse_assignment(self):
|
def test_unparse_assignment(self):
|
||||||
with open("ast_parser/test/xml/assignment.xml", "r") as f:
|
with open("xml/assignment.xml", "r") as f:
|
||||||
input = f.read()
|
input = f.read()
|
||||||
parser = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual("C = 30;\n", parser.source)
|
self.assertEqual("C = 30;\n", parser.input)
|
||||||
|
|
||||||
def test_unparse_conditional(self): # TODO test the else-if statements
|
def test_unparse_conditional(self): # TODO test the else-if statements
|
||||||
with open("ast_parser/test/xml/conditional.xml", "r") as f:
|
with open("xml/conditional.xml", "r") as f:
|
||||||
input = f.read()
|
input = f.read()
|
||||||
|
|
||||||
with open("ast_parser/test/xml/conditional.out", "r") as f:
|
with open("xml/conditional.out", "r") as f:
|
||||||
output = f.read()
|
output = f.read()
|
||||||
|
|
||||||
parser = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
|
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
|
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual(output, parser.source)
|
self.assertEqual(output, parser.input)
|
||||||
|
|
||||||
def test_unparse_loop(self):
|
def test_unparse_loop(self):
|
||||||
with open("ast_parser/test/xml/loop.xml", "r") as f:
|
with open("xml/loop.xml", "r") as f:
|
||||||
input = f.read()
|
input = f.read()
|
||||||
|
|
||||||
with open("ast_parser/test/xml/loop.out", "r") as f:
|
with open("xml/loop.out", "r") as f:
|
||||||
output = f.read()
|
output = f.read()
|
||||||
|
|
||||||
parser = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual(output, parser.source)
|
self.assertEqual(output, parser.input)
|
||||||
|
|
||||||
def test_unparse_operation_single(self):
|
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>'
|
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 = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual("a * 42", parser.source)
|
self.assertEqual("a * 42", parser.input)
|
||||||
|
|
||||||
def test_unparse_return(self):
|
def test_unparse_return(self):
|
||||||
input = '<return> <literal type="int" value="0" /> </return>'
|
input = '<return> <literal type="int" value="0" /> </return>'
|
||||||
parser = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual("return 0;\n", parser.source)
|
self.assertEqual("return 0;\n", parser.input)
|
||||||
|
|
||||||
def test_unparse_unary(self):
|
def test_unparse_unary(self):
|
||||||
with open("ast_parser/test/xml/unary.xml", "r") as f:
|
with open("xml/unary.xml", "r") as f:
|
||||||
input = f.read()
|
input = f.read()
|
||||||
|
|
||||||
with open("ast_parser/test/xml/unary.out", "r") as f:
|
with open("xml/unary.out", "r") as f:
|
||||||
output = f.read()
|
output = f.read()
|
||||||
|
|
||||||
parser = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual(output, parser.source)
|
self.assertEqual(output, parser.input)
|
||||||
|
|
||||||
def test_unparse_routine(self):
|
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>'
|
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 = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
i = ' ' * parser.indentation
|
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("procedure main() returns integer {\n var integer a = 1;\n a * 42 -> std_output;\n return 0;\n}\n\n", parser.input)
|
||||||
|
|
||||||
def test_unparse_args(self):
|
def test_unparse_args(self):
|
||||||
with open("ast_parser/test/xml/many_args.xml", 'r') as f:
|
with open("xml/many_args.xml", 'r') as f:
|
||||||
input = f.read()
|
input = f.read()
|
||||||
with open("ast_parser/test/xml/many_args.out", 'r') as f:
|
with open("xml/many_args.out", 'r') as f:
|
||||||
output = f.read()
|
output = f.read()
|
||||||
parser = GazUnparser(ET.fromstring(input), True)
|
parser = AstParser(ET.fromstring(input), True)
|
||||||
parser.source = ""
|
parser.input = ""
|
||||||
parser.unparse_node(parser.xml)
|
parser.unparse_node(parser.xml)
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
self.assertEqual(output, parser.source)
|
self.assertEqual(output, parser.input)
|
||||||
|
|
||||||
|
|
||||||
def test_unparse_code(self):
|
def test_unparse_code(self):
|
||||||
with open("ast_parser/test/xml/test.xml", "r") as input:
|
with open("xml/test.xml", "r") as input:
|
||||||
parser = GazUnparser(ET.fromstring(input.read()), True)
|
parser = AstParser(ET.fromstring(input.read()), True)
|
||||||
parser.unparse()
|
parser.unparse()
|
||||||
self.assertIsNotNone(parser.source)
|
self.assertIsNotNone(parser.input)
|
||||||
|
|
||||||
with open("ast_parser/test/xml/input.in", "r") as input:
|
with open("input.in", "r") as input:
|
||||||
i = input.read()
|
i = input.read()
|
||||||
self.assertEqual(i, parser.source)
|
self.assertEqual(i, parser.input)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
if False:
|
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
return 1
|
|
|
@ -1,6 +0,0 @@
|
||||||
def main() -> int:
|
|
||||||
a: int = 1
|
|
||||||
print(a * 42, end='')
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
while True:
|
|
||||||
print(a * 42, end='')
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
def beeeeees(a: int, b: int, bb: int, bbb: int, bbbb: int, bbbbb: int, bbbbbb: int, bbbbbbb: int, bbbbbbbb: int) -> int:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
35
fuzzer.py
35
fuzzer.py
|
@ -1,13 +1,7 @@
|
||||||
import sys
|
|
||||||
from io import StringIO
|
|
||||||
import xml
|
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
import ast_parser
|
import ast_parser
|
||||||
from ast_generator.ast_generator import *
|
from ast_generator.ast_generator import *
|
||||||
from ast_parser.gaz_unparser import *
|
from ast_parser.gaz_unparser import *
|
||||||
from ast_parser.python_unparser import PythonUnparser
|
|
||||||
import inspect
|
|
||||||
|
|
||||||
|
|
||||||
class GazpreaFuzzer:
|
class GazpreaFuzzer:
|
||||||
|
@ -18,38 +12,17 @@ class GazpreaFuzzer:
|
||||||
settings: dict = yaml.safe_load(yaml_file)
|
settings: dict = yaml.safe_load(yaml_file)
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
|
|
||||||
self.gaz_source_gen = None
|
self.parser = None
|
||||||
self.generator = AstGenerator(settings)
|
self.generator = AstGenerator(settings)
|
||||||
|
|
||||||
self.ast = None
|
self.ast = None
|
||||||
self.source = None
|
self.source = None
|
||||||
self.ground_truth = None
|
|
||||||
self.out = None
|
self.out = None
|
||||||
|
|
||||||
def fuzz(self):
|
def fuzz(self):
|
||||||
self.generator.generate_ast()
|
self.generator.generate_ast()
|
||||||
self.write_ast()
|
self.parser = AstParser(self.generator.ast, True)
|
||||||
|
self.parser.unparse()
|
||||||
self.gaz_source_gen = GazUnparser(self.generator.ast, True)
|
|
||||||
self.gaz_source_gen.unparse()
|
|
||||||
|
|
||||||
self.ast = self.generator.ast
|
self.ast = self.generator.ast
|
||||||
self.source = self.gaz_source_gen.source
|
self.source = self.parser.input
|
||||||
|
|
||||||
self.python_source_gen = PythonUnparser(self.generator.ast, True)
|
|
||||||
self.python_source_gen.unparse()
|
|
||||||
|
|
||||||
self.ground_truth = self.python_source_gen.source
|
|
||||||
output = StringIO()
|
|
||||||
sys.stdout = output
|
|
||||||
exec(self.ground_truth)
|
|
||||||
self.out = output.getvalue()
|
|
||||||
|
|
||||||
def write_ast(self):
|
|
||||||
dom = xml.dom.minidom.parseString(ET.tostring(self.generator.ast).decode('utf-8'))
|
|
||||||
pretty: str = dom.toprettyxml()
|
|
||||||
|
|
||||||
randint = random.randint(0, 1000)
|
|
||||||
print(randint)
|
|
||||||
with open("debug/ast/debug_{}.xml".format(randint), 'w') as f:
|
|
||||||
f.write(pretty)
|
|
||||||
|
|
29
fuzzer/input/name9.in
Normal file
29
fuzzer/input/name9.in
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
procedure main() returns integer {
|
||||||
|
var integer lQnOqNtVPW = 698.7344103570729 * -606.7195181938484 + 1182583819 / 338469442 -132074245 237434130 * -708692944 / 530298228 / 228341377 * -1043540342 / 338.5382125746569 - -1560602812 2034076062 -677.2384366071922 * -1396288472 / -294.03910951537273 / 280.6003642162291 * 686277004 + -733.108807335117 - 1914739986 + -758706778 815.5612439852075 - 730843697 / -2035135312 761.468341780042 - 829972738;
|
||||||
|
529.6931700408081 * -53.71572853074235 - 731650703 263042418 * 1435010036 * -737.690803185421 - -395.5236453408153 / 1196211792 * -863.1836123458379 * -749.2669025070672 / 233.51151490705547 * -51.0686729564427 + -621.939364952389 / -361.3032921336703 - 1199853509 + 907542641 - 305.66149149183957 - -969.8710268189419 + 740.6073234896774 * 1719139590 - -243.75739859831253 - 1996675237 -> std_output;
|
||||||
|
var integer HWk = 1069696775;
|
||||||
|
var integer MIk = 1514360961;
|
||||||
|
var integer HE = -649.8393258588937 * -420.15021805874414 * 1761285701 -1667293001 / 29.5677167859983 * -844.2501263700528 / 1501314800 -1162542243 - -1217599986 + 1615995882 -1764940899 + -1917325853 + 835.4795594258562 * 590.6099641194992 - 472.7184791317236 * 1344256840 * 62.679409268019754 - 484.02060330123754 * 777.5221533723766 330.52965727523974 -380.69699980042685 * -760070929 * -949.6644980763808 - -447.8157902650353 * 464.1790468792867;
|
||||||
|
MIk = 953967969 + -268.8694010427613 / 791.5413559693457 + -7.679861742818616 / 1437831656 + 403.979481098871 * -456304863 - 2091190143 * 737295943 -1039468631 / -681.5757290664048 + -971.7430559091156 * -445.84393937984385 * -222.0375737233644 1070575402 -999.5935819561656 - -173.41289931519555 -1190366598 / 613.2734677906551 -531818545;
|
||||||
|
-397.7646630448985 - 1809763600 -982.6387961874157 + 256902008 * 425.58253894287964 / -718.3862648199979 -429.5886775058759 * 158.12171431595698 * -599.7405849078852 -733.8460310316564 * -742.5867261833964 * 2086150131 - 703.2177962216272 -> std_output;
|
||||||
|
lQnOqNtVPW = -680.8890396739438;
|
||||||
|
HWk = -254718851 / 264.0381140059085 * 996.2297492346818 - -77.96516420152841;
|
||||||
|
2100864484 - 2007894240 * -212.01378334488163 * 1379091426 -412243492 / -317390514 1229512655 / 1726566479 / 1747747042 764692152 + 624951054 + -1324352806 + 399.1702565288206 + -893.8711860029409 + -711.4400942267645 + 179.0145034263055 - -723.3632700757751 -2079239194 * -729.6073740027866 + -629.3818640065572 * 142789298 / -489.50899343461106 - 561691654 + -1414809862 * 222.37308869516414 / 857.1114294659471 549.7759000995088 + -666.6748642112184 * 385.38510100490385 -> std_output;
|
||||||
|
return 0;
|
||||||
|
HWk = 2059289556 + -403.9892396676721 / 1653655432 - -588.6575838596884 * -467.74405479942334 -789.6678603205703 - -2079730883 * -206.976327703003 - -99.23168409674201 -368.21174081123957 -2125902669 * 721.014283295284 * 684.9390791239739 * -336.9272218346822 / -549.8949978968651 / 31.821007498567496 / -386544376 36.406643230034206 -979.8695533308437 - -405.3890042820476 + -241343604 * 947.4009884595018 * -741574263;
|
||||||
|
}
|
||||||
|
|
||||||
|
procedure DzeIKcCNqh(integer rejZppcSMv, integer LkOieFctp, integer r, integer fGPZCKaJ, integer wLK, integer AeUntf, integer MWsHdvBSR, integer OuXoynGm, integer VPVOgzU, integer SMxhab) returns integer {
|
||||||
|
NAsBez = 807.1145861289976;
|
||||||
|
-1046538300 -> std_output;
|
||||||
|
return -211048078;
|
||||||
|
}
|
||||||
|
|
||||||
|
function UkU(integer ImmgbVHS, integer LfvBpxnRq) returns integer {
|
||||||
|
NAsBez = 961878732;
|
||||||
|
return -1293956197 / -773.5583114264432 / 759992758 - 324.6814914711299 / -773.3733374415364 * -823.4158348051863 * -1178415147 / 749.7213693296735 - -131.4240459218521 - -607197268 * -71900919 768.0290042747429 * 1529150661 * -657.5023412274927 / -201.66669058694868 / 692.9818240317327 / -1241350558 / -652.1792880359916 * 673.9253031170642 -61.25909942165197 * -2037670958 -1400547457 - 588219524 / -539.7564210381759 * 1856853047 / -1654156060 + -648756285;
|
||||||
|
NAsBez = 186.7935151585625 + 439669401 / 545.2783919286676 - -53306996 -9214657 - 184.5664265585533 / 291945719 * -443885835 + -566896102 - -346.630385606735 / 990.8304675995412 1582261953 - -1818951954 - -80664147 - 466.8821342017786 / 459.0521603737384 249.74968247519246;
|
||||||
|
var integer xtoZPgYmq = 810.2648762093065 / 482.261574544076 * 1927906771 / 630.1087104660135 -860.8294002903949 / 1932738597 + 1967595112 + -1136874252 * 580228054 -344.98371454114204 * -528.4467764471448 * 1842148455 + -166.07081934179928 / 90.4861524809719 / -177909614 / 2014149666;
|
||||||
|
var integer MmXWOxIXst = -135150791 / -842.279867288959 -873.3805968639836 + 137.73347301182048 + -668.6167365403119 - -531.4895607809302 - -486203036 / 1163466657 / -1996539944 * 908219867 * 684.3378150732071 - -351.83526537527894 / 569.8408814272439 * 1560698923;
|
||||||
|
}
|
||||||
|
|
|
@ -10,36 +10,31 @@ import xml.dom.minidom
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
class Fuzzer():
|
class Fuzzer():
|
||||||
def __init__(self, config: str, batch: int, seed: str, file_name: str = "fuzz"):
|
def __init__(self, config: str, batch: int, seed: str):
|
||||||
with open(config) as yaml_file:
|
with open(config) as yaml_file:
|
||||||
settings: dict = yaml.safe_load(yaml_file)
|
settings: dict = yaml.safe_load(yaml_file)
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
self.batch = batch
|
self.batch = batch
|
||||||
random.seed(seed)
|
random.seed(seed)
|
||||||
self.file_name = file_name
|
|
||||||
|
|
||||||
self.fuzzer = fz.GazpreaFuzzer(config)
|
self.fuzzer = fz.GazpreaFuzzer(config)
|
||||||
|
self.fuzzer.fuzz()
|
||||||
|
|
||||||
def fuzz(self):
|
def fuzz(self):
|
||||||
os.system("rm -rf fuzzer")
|
|
||||||
os.mkdir("fuzzer")
|
|
||||||
os.mkdir("fuzzer/input")
|
|
||||||
os.mkdir("fuzzer/debug")
|
|
||||||
os.mkdir("fuzzer/instream")
|
|
||||||
os.mkdir("fuzzer/outputs")
|
|
||||||
os.mkdir("fuzzer/ground_truth")
|
|
||||||
for i in range(self.batch):
|
for i in range(self.batch):
|
||||||
self.fuzzer.fuzz()
|
self.fuzzer.fuzz()
|
||||||
dom = xml.dom.minidom.parseString(ET.tostring(self.fuzzer.ast).decode('utf-8'))
|
dom = xml.dom.minidom.parseString(ET.tostring(self.fuzzer.ast).decode('utf-8'))
|
||||||
pretty: str = dom.toprettyxml()
|
pretty: str = dom.toprettyxml()
|
||||||
with open("fuzzer/input/{}_{}.in".format(self.file_name, i), 'w') as f:
|
os.system("rm -rf fuzzer")
|
||||||
|
os.mkdir("fuzzer")
|
||||||
|
os.mkdir("fuzzer/input")
|
||||||
|
os.mkdir("fuzzer/debug")
|
||||||
|
os.mkdir("fuzzer/instream")
|
||||||
|
os.mkdir("fuzzer/outputs")
|
||||||
|
with open("fuzzer/input/name{}.in".format(i), 'w') as f:
|
||||||
f.write(self.fuzzer.source)
|
f.write(self.fuzzer.source)
|
||||||
with open("fuzzer/debug/{}_{}.out".format(self.file_name, i), 'w') as f:
|
with open("fuzzer/debug/name{}.out".format(i), 'w') as f:
|
||||||
f.write(pretty)
|
f.write(pretty)
|
||||||
with open("fuzzer/outputs/{}_{}.out".format(self.file_name, i), 'w') as f:
|
|
||||||
f.write(self.fuzzer.out)
|
|
||||||
with open("fuzzer/ground_truth/{}_{}.py".format(self.file_name, i), 'w') as f:
|
|
||||||
f.write(self.fuzzer.ground_truth)
|
|
||||||
# with open("fuzzer/instream/{}.in".format(i), 'w') as f:
|
# with open("fuzzer/instream/{}.in".format(i), 'w') as f:
|
||||||
# f.write(self.fuzzer.source)
|
# f.write(self.fuzzer.source)
|
||||||
# with open("fuzzer/outputs/{}.out".format(i), 'w') as f:
|
# with open("fuzzer/outputs/{}.out".format(i), 'w') as f:
|
||||||
|
@ -51,13 +46,11 @@ if __name__ == '__main__':
|
||||||
description='Procedurally generate a test case for Gazprea'
|
description='Procedurally generate a test case for Gazprea'
|
||||||
)
|
)
|
||||||
parser.add_argument('-b', '--batch_size', type=int, required=False,
|
parser.add_argument('-b', '--batch_size', type=int, required=False,
|
||||||
help="generate BATCH cases (fuzzer/source/nameX.in, /instream/..., /outputs/...)")
|
help="generate BATCH cases (fuzzer/input/nameX.in, /instream/..., /outputs/...)")
|
||||||
parser.add_argument('--seed', type=int, required=False, action="store",
|
parser.add_argument('--seed', type=int, required=False, action="store",
|
||||||
help="rng seed")
|
help="rng seed")
|
||||||
parser.add_argument('config_file', type=str, action="store",
|
parser.add_argument('config_file', type=str, action="store",
|
||||||
help="path to your configuration file")
|
help="path to your configuration file")
|
||||||
parser.add_argument('file_name', type=str, action="store",
|
|
||||||
help="name for the generated files")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
fuzzer = Fuzzer(config=args.config_file, batch=args.batch_size, seed=args.seed)
|
fuzzer = Fuzzer(config=args.config_file, batch=args.batch_size, seed=args.seed)
|
||||||
|
|
Loading…
Reference in a new issue