166 lines
5.1 KiB
Python
166 lines
5.1 KiB
Python
|
import os
|
||
|
import shutil
|
||
|
import xml.etree.ElementTree as ET
|
||
|
|
||
|
|
||
|
def to_gazprea_type(ty: str):
|
||
|
if ty == "int":
|
||
|
return "integer"
|
||
|
elif ty == "bool":
|
||
|
return "boolean"
|
||
|
elif ty == "string":
|
||
|
return "string"
|
||
|
elif ty == 'void':
|
||
|
return 'void'
|
||
|
else:
|
||
|
raise Exception("Unknown type: " + ty)
|
||
|
|
||
|
|
||
|
class AstParser:
|
||
|
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 parse(self):
|
||
|
if os.path.isdir("/home/stormblessed/Code/gazprea_fuzzer_v0.2/ast_parser/test/.tmp"):
|
||
|
os.system("rm -rf /home/stormblessed/Code/gazprea_fuzzer_v0.2/ast_parser/test/.tmp")
|
||
|
os.mkdir("/home/stormblessed/Code/gazprea_fuzzer_v0.2/ast_parser/test/.tmp")
|
||
|
else:
|
||
|
os.mkdir("/home/stormblessed/Code/gazprea_fuzzer_v0.2/ast_parser/test/.tmp")
|
||
|
with open("/home/stormblessed/Code/gazprea_fuzzer_v0.2/ast_parser/test/.tmp/input.in", "x") as f:
|
||
|
f.write(self.input)
|
||
|
os.system("/home/stormblessed/.local/bin/gazc "
|
||
|
"/home/stormblessed/Code/gazprea_fuzzer_v0.2/ast_parser/test/.tmp/input.in "
|
||
|
"/home/stormblessed/Code/gazprea_fuzzer_v0.2/ast_parser/test/.tmp/output.out "
|
||
|
"/home/stormblessed/Code/gazprea_fuzzer_v0.2/ast_parser/test/.tmp/xml.xml")
|
||
|
self.xml = ET.parse(".tmp/xml.xml")
|
||
|
|
||
|
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 ["variable", "rhs", "lhs", "literal", "operator"]:
|
||
|
self.input += " " * self.indentation
|
||
|
|
||
|
if node.tag == "block":
|
||
|
self._block_unparse(node)
|
||
|
elif node.tag == "declaration":
|
||
|
self._declaration_unparse(node)
|
||
|
elif node.tag == "return":
|
||
|
self._return_unparse(node)
|
||
|
elif node.tag == "operator":
|
||
|
self._operator_unparse(node)
|
||
|
elif node.tag == "stream":
|
||
|
self._stream_unparse(node)
|
||
|
elif node.tag == "literal":
|
||
|
self._literal_unparse(node)
|
||
|
elif node.tag == "procedure" or node.tag == "function":
|
||
|
self._routine_unparse(node)
|
||
|
elif node.tag == "variable":
|
||
|
self._variable_unparse(node)
|
||
|
elif node.tag == "rhs" or node.tag == "lhs":
|
||
|
self._xhs_unparse(node)
|
||
|
elif node.tag == "literal":
|
||
|
self._literal_unparse(node)
|
||
|
else:
|
||
|
raise Exception("Unknown tag: " + node.tag)
|
||
|
|
||
|
def _block_unparse(self, node):
|
||
|
self.input += "{\n"
|
||
|
self.indentation += 4
|
||
|
for child in node:
|
||
|
self._unparse_node(child)
|
||
|
self.indentation -= 4
|
||
|
self.input += "}\n\n"
|
||
|
|
||
|
def _declaration_unparse(self, node):
|
||
|
variable = node.find("variable")
|
||
|
rhs = node.find("rhs")
|
||
|
self._variable_unparse(variable, True)
|
||
|
self.input += "="
|
||
|
self._unparse_node(rhs)
|
||
|
self.input += ";\n"
|
||
|
|
||
|
def _variable_unparse(self, node, is_declaration = False):
|
||
|
if is_declaration:
|
||
|
mut = node.get("mut")
|
||
|
type = to_gazprea_type(node.get("type"))
|
||
|
name = node.get("name")
|
||
|
|
||
|
self.input += "{} {} {} ".format(mut, type, name)
|
||
|
else:
|
||
|
self.input += " {} ".format(node.get("name"))
|
||
|
|
||
|
def _stream_unparse(self, node):
|
||
|
for child in node:
|
||
|
self._unparse_node(child)
|
||
|
|
||
|
self.input += "-> {};\n".format(node.get("type"))
|
||
|
|
||
|
def _literal_unparse(self, node):
|
||
|
self.input += " {} ".format(node.get("value"))
|
||
|
|
||
|
def _xhs_unparse(self, node):
|
||
|
for child in node:
|
||
|
self._unparse_node(child)
|
||
|
|
||
|
def _operator_unparse(self, node):
|
||
|
self._xhs_unparse(node.find("lhs"))
|
||
|
self.input += "{}".format(node.get("op"))
|
||
|
self._xhs_unparse(node.find("rhs"))
|
||
|
|
||
|
def _return_unparse(self, node):
|
||
|
self.input += "return"
|
||
|
for child in node:
|
||
|
self._unparse_node(child)
|
||
|
self.input += ";\n"
|
||
|
|
||
|
def _routine_unparse(self, node):
|
||
|
return_type = ""
|
||
|
if node.get("return_type") != "":
|
||
|
return_type = "returns " + to_gazprea_type(node.get("return_type"))
|
||
|
|
||
|
self.input += "{} {}{} {} ".format(
|
||
|
node.tag,
|
||
|
node.get("name"),
|
||
|
node.get("args"),
|
||
|
return_type,
|
||
|
)
|
||
|
|
||
|
for child in node:
|
||
|
self._unparse_node(child)
|
||
|
|
||
|
# self.input += "}\n\n" #blocks are already there
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
input = """
|
||
|
function art() returns integer {
|
||
|
return 3;
|
||
|
}
|
||
|
procedure main() returns integer {
|
||
|
integer b = art();
|
||
|
integer a = 1;
|
||
|
a * 42 -> std_output;
|
||
|
return 0;
|
||
|
}
|
||
|
"""
|
||
|
|
||
|
parser = AstParser(input)
|
||
|
parser.parse()
|
||
|
|