277 lines
8.3 KiB
Python
277 lines
8.3 KiB
Python
import os
|
|
import shutil
|
|
import warnings
|
|
import xml.etree.ElementTree as ET
|
|
|
|
from ast_parser.general_unparser import GeneralUnparser
|
|
from constants import *
|
|
|
|
|
|
def to_gazprea_type(ty: str): #TODO implement the compound types
|
|
if ty == GAZ_INT_KEY:
|
|
return "integer"
|
|
elif ty == GAZ_BOOL_KEY:
|
|
return "boolean"
|
|
elif ty == GAZ_FLOAT_KEY:
|
|
return "real"
|
|
elif ty == GAZ_CHAR_KEY:
|
|
return "character"
|
|
elif ty == GAZ_STRING_KEY:
|
|
return "string[*]"
|
|
else:
|
|
raise Exception("Unknown type: " + ty)
|
|
|
|
|
|
def _unparse_arg(node):
|
|
return "{} {}".format(to_gazprea_type(node.get(GAZ_TY_KEY)), node.get(GAZ_NAME_KEY))
|
|
|
|
|
|
def to_gaz_value(val):
|
|
if val in ["True", "False"]:
|
|
return val.lower()
|
|
else:
|
|
return str(val)
|
|
|
|
|
|
def to_gaz_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 AstParser(GeneralUnparser):
|
|
def __init__(self, input: str or ET.Element, from_xml: bool = False):
|
|
if from_xml:
|
|
self.xml = input
|
|
self.input = None
|
|
else:
|
|
self.input = input
|
|
self.xml = None
|
|
|
|
self.indentation = 0
|
|
|
|
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:
|
|
raise Exception("Unknown tag: " + node.tag)
|
|
|
|
def unparse_block(self, node):
|
|
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 unparse_declaration(self, node):
|
|
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 unparse_variable(self, node, is_declaration = False):
|
|
if is_declaration:
|
|
mut = node.get(GAZ_QUALIFIER_KEY)
|
|
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,
|
|
return_type,
|
|
)
|
|
|
|
for child in node:
|
|
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
|