gazprea-fuzzer-python/ast_parser/gaz_unparser.py
2023-11-18 12:21:52 -07:00

167 lines
5 KiB
Python

import os
import shutil
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)
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_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)
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
self.input += "}\n\n"
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.tag == GAZ_OUT_STREAM:
self.unparse_outstream(node)
elif node.tag == 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(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(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 = self.unparse_argument(node.findall(GAZ_ARG_TAG))
self.input += "{} {}{} {} ".format(
node.tag,
node.get(GAZ_NAME_KEY),
args,
return_type,
)
for child in node:
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 += self._unparse_arg(nodes[i])
if i < len(nodes) - 1:
args += ", "
args += ")"
return args
def _unparse_arg(self, node):
return "{} {}".format(to_gazprea_type(node.get(GAZ_TY_KEY)), node.get(GAZ_NAME_KEY))