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