def isVar(self, soft=False): """ Function check if current argument is variable If argument is not var and soft is set to True function return false, else exit interpret with correct exit code """ retval = True if (self.Type != ArgumentType.STACK and self.Type != ArgumentType.GF and self.Type != ArgumentType.TF and self.Type != ArgumentType.LF): retval = False if self.Value is not None: if isinstance(self.Value, str) and len(self.Value) > 0: reResult = re.search(r"[a-zA-Z\_\-\$\&\%\*\!\?]", self.Value[0]) if (reResult is None): retval = False if retval == False: if soft == True: return False else: print(self.Type, self.Value, file=sys.stderr) ErrorHandler.printError("Expected variable", ErrorHandler.ERROR_UNEXPECTED_XML) return True
def InterpretStri2Int(self,instruction): self.CheckArgumentCount(instruction.getArgCount(), 3, "STRI2CHAR") arg1 = instruction.getArg(1) arg1.isVar() arg2 = instruction.getArg(2) arg2.isSymb() arg3 = instruction.getArg(3) arg3.isSymb() arg2Value = self.GetValue(arg2) arg3Value = self.GetValue(arg3) if arg2Value["type"] != ArgumentType.STRING: self.TypeErrorWithVariableOrNot(arg2,arg3,"STRI2INT, Second urgument expected string") if arg3Value["type"] != ArgumentType.INT: self.TypeErrorWithVariableOrNot(arg2,arg3,"STRI2INT, Third argument expected int") try: position = arg3Value["value"] if len(arg2Value["value"]) -1 < position or position < 0: ErrorHandler.printError("STRI2INT, Indexing error", ErrorHandler.ERROR_WORK_WITH_STRING) value = ord(arg2Value["value"][position]) self.SetVariable(arg1.Type,arg1.Value,{"type" : ArgumentType.INT, "value": value}) except IndexError: ErrorHandler.printError("STRI2INT, Indexing error", ErrorHandler.ERROR_WORK_WITH_STRING)
def InterpretSetChar(self,instruction): self.CheckArgumentCount(instruction.getArgCount(), 3, "SETCHAR") arg1 = instruction.getArg(1) arg1.isVar() arg2 = instruction.getArg(2) arg2.isSymb() arg3 = instruction.getArg(3) arg3.isSymb() arg2Value = self.GetValue(arg2) arg3Value = self.GetValue(arg3) if arg2Value["type"] != ArgumentType.INT: self.TypeErrorWithVariableOrNot(arg2,arg3,"SETCHAR, Second urgument expected int") if arg3Value["type"] != ArgumentType.STRING: self.TypeErrorWithVariableOrNot(arg2,arg3,"SETCHAR, Third argument expected string") try: value = self.GetVariable(arg1.Type,arg1.Value) if value["type"] != ArgumentType.STRING: self.TypeErrorWithVariableOrNot(arg1,arg2,"SETCHAR, First argument expected string variable") position = arg2Value["value"] if len(value["value"]) -1 < position or position < 0: ErrorHandler.printError("SETCHAR, Indexing error", ErrorHandler.ERROR_WORK_WITH_STRING) value["value"] = value["value"][:position] + arg3Value["value"][0] + value["value"][position + 1 : ] self.SetVariable(arg1.Type,arg1.Value,value) except IndexError: ErrorHandler.printError("SETCHAR, Indexing error", ErrorHandler.ERROR_WORK_WITH_STRING)
def isSymb(self): """ Function check if current argument is Symbol If argument is not Symbol exit interpret with correct exit code """ if self.isVar(True): return True if self.Type == ArgumentType.NIL: if self.Value != None: ErrorHandler.printError("Unexpected value for type nil") elif self.Type == ArgumentType.BOOL: if not isinstance(self.Value, bool): ErrorHandler.printError("Unexpected value for type bool") elif self.Type == ArgumentType.INT: if not isinstance(self.Value, int): ErrorHandler.printError("Unexpected value for type int") elif self.Type == ArgumentType.FLOAT: if not isinstance(self.Value, float): ErrorHandler.printError("Unexpected value for type int") elif self.Type == ArgumentType.UNSET: print("Value: ", self.Value, file=sys.stderr) ErrorHandler.printError("Unexpected symbol type", ErrorHandler.ERROR_UNEXPECTED_XML)
def InterpretPopFrame(self,instruction): self.CheckArgumentCount(instruction.getArgCount(), 0, "POPFRAME") try: self.TF = self.LF self.LF = self.StackLF.pop() except IndexError: ErrorHandler.printError("Poping non existing frame",ErrorHandler.ERROR_RUNTIME_NOEXIST_FRAME)
def replace(match): try: match = match.group() return chr(int(match[1:])) except: ErrorHandler.printError( "Error while escaping special sequences in string", ErrorHandler.ERROR_RUNTIME_WRONG_OPERAND_TYPE)
def __init__(self, inputFile): try: if (inputFile == ""): self.tree = ET.parse(sys.stdin) else: self.tree = ET.parse(inputFile) except ET.ParseError: ErrorHandler.printError("Input xml file is not well formed", ErrorHandler.ERROR_NOT_WELL_FORM)
def InterpretPops(self,instruction): self.CheckArgumentCount(instruction.getArgCount(), 1, "POPS") arg1 = instruction.getArg(1) arg1.isVar() try: self.SetVariable(arg1.Type,arg1.Value,self.DataStack.pop()) except IndexError: ErrorHandler.printError("Try to pop from empty data stack",ErrorHandler.ERROR_RUNTIME_MISSING_VALUE)
def isLabel(self): """ Check if current argument is label If it's not a label exit interpreter """ if self.Type != ArgumentType.LABEL: ErrorHandler.printError("Label require Label argument", ErrorHandler.ERROR_UNEXPECTED_XML)
def InterpretPushFrame(self,instruction): self.CheckArgumentCount(instruction.getArgCount(), 0, "PUSHFRAME") if(self.TFisCreated == False): ErrorHandler.printError("Pushing non existing frame",ErrorHandler.ERROR_RUNTIME_NOEXIST_FRAME) self.StackLF.append(self.LF) self.LF = self.TF self.TF = None self.TFisCreated = False
def isType(self): """ Check if current argument is Type If it's not a type exit interpreter """ if (self.Value != "int" and self.Value != "bool" and self.Value != "string" and self.Value != "float"): ErrorHandler.printError("Expected type", ErrorHandler.ERROR_UNEXPECTED_XML) return True
def setOrder(self, order): try: self.Order = int(order) if (self.Order < 0): ErrorHandler.printError( "Instruction order must be positive number", ErrorHandler.ERROR_UNEXPECTED_XML) except: ErrorHandler.printError("Instruction order must be number", ErrorHandler.ERROR_UNEXPECTED_XML)
def InterpretExit(self,instruction): self.CheckArgumentCount(instruction.getArgCount(), 1, "EXIT") arg1 = instruction.getArg(1) arg1.isSymb() arg1Value = self.GetValue(arg1) if arg1Value["type"] != ArgumentType.INT: self.TypeErrorWithVariableOrNot(arg1,arg1,"EXIT, expected integer argument") if arg1Value["value"] not in range(0,50): ErrorHandler.printError("EXIT, wrong exit code",ErrorHandler.ERROR_WRONG_OPERAND_VALUE) exit(arg1Value["value"])
def checkHeader(self): """ Check header of XML source code if is syntax correct """ root = self.getRoot() if root.tag != "program": ErrorHandler.printError("Missing root tag program", ErrorHandler.ERROR_UNEXPECTED_XML) #strip remove whitespace if (root.text != None and root.text.strip() != ""): print(root.text) ErrorHandler.printError("Root tag program contains text", ErrorHandler.ERROR_UNEXPECTED_XML) for attr in root.attrib: if attr == "language": if root.attrib["language"] != "IPPcode21": ErrorHandler.printError( "Unsuported language, expected IPPcode21", ErrorHandler.ERROR_UNEXPECTED_XML) elif attr != "name" and attr != "description": ErrorHandler.printError( "Unknown attribut " + attr + " for program element", ErrorHandler.ERROR_UNEXPECTED_XML)
def setArg(self, index, arg): try: index = int(index) if index > self.ArgCount: self.ArgCount = index self.Args[index - 1] = arg except ValueError: ErrorHandler.printError("Argument index must be number", ErrorHandler.ERROR_UNEXPECTED_XML) except: ErrorHandler.printError("Argument index must be in range (1..3)", ErrorHandler.ERROR_UNEXPECTED_XML)
def InterpretStackInstructionWith3Arguments(self,instruction): self.CheckArgumentCount(instruction.getArgCount(), 1, instruction.Opcode) try: arg2 = self.DataStack.pop() arg1 = self.DataStack.pop() inst = Instruction() inst.setArg(1, instruction.getArg(1)) inst.setArg(2, Argument(arg1["type"], arg1["value"])) inst.setArg(3, Argument(arg2["type"], arg2["value"])) inst.Opcode = instruction.Opcode[:-1] #remove last char self.InstructionMapper(inst) except IndexError: ErrorHandler.printError("Try to pop from empty data stack",ErrorHandler.ERROR_RUNTIME_MISSING_VALUE)
def InterpretFloat2Int(self, instruction): self.CheckArgumentCount(instruction.getArgCount(), 2, "FLOAT2INT") arg1 = instruction.getArg(1) arg1.isVar() arg2 = instruction.getArg(2) arg2.isSymb() arg2Value = self.GetValue(arg2) if arg2Value["type"] != ArgumentType.FLOAT: self.TypeErrorWithVariableOrNot(arg2,arg2,"FLOAT2INT, Second urgument expected float") try: value = int(arg2Value["value"]) self.SetVariable(arg1.Type,arg1.Value,{"type" : ArgumentType.INT, "value": value}) except ValueError: ErrorHandler.printError("FLOAT2INT, error", ErrorHandler.ERROR_RUNTIME_MISSING_VALUE)
def InterpretDiv(self,instruction): self.CheckArgumentCount(instruction.getArgCount(), 3, "DIV") arg1 = instruction.getArg(1) arg1.isVar() arg2 = instruction.getArg(2) arg2.isSymb() arg3 = instruction.getArg(3) arg3.isSymb() arg2Value = self.GetValue(arg2) arg3Value = self.GetValue(arg3) if (arg2Value["type"] != ArgumentType.FLOAT or arg3Value["type"] != ArgumentType.FLOAT): self.TypeErrorWithVariableOrNot(arg2,arg3, "Operation DIV, only floats can be divided") if self.isClose(arg3Value["value"], 0): ErrorHandler.printError("Operation DIV, Dividing by zero",ErrorHandler.ERROR_WRONG_OPERAND_VALUE) self.SetVariable(arg1.Type, arg1.Value,{"type" : ArgumentType.FLOAT, "value": arg2Value["value"] / arg3Value["value"]})
def ParseArguments(): parser = argparse.ArgumentParser(description='Handle arguments') parser.add_argument('--source', dest='source', type = str, help='Source file with xml') parser.add_argument('--input', dest='input', type = str, help='Input file with inputs for interpretation') parser.add_argument('--stats', dest='stats', type = str, help='') parser.add_argument('--insts', dest='insts', help='', action='store_true') parser.add_argument('--hot', dest='hot', help='', action='store_true') parser.add_argument('--vars', dest='vars', help='', action='store_true') global args try: args = parser.parse_args() except SystemExit: if len(sys.argv) == 2 and (sys.argv[1] == "-h" or sys.argv[1] == "--help"): exit(0) ErrorHandler.printError("Invalid argument, --help for help",ErrorHandler.ERROR_ARGUMENTS) if args.input is None and args.source is None: ErrorHandler.printError("source or input parameter must be inserter, type --help for help",ErrorHandler.ERROR_INPUT_FILE) elif args.source is None: args.source = sys.stdin if args.insts or args.hot or args.vars: if not args.stats: ErrorHandler.printError("Statistic argument without --stats, type --help for help",ErrorHandler.ERROR_ARGUMENTS)
def InterpretInt2Char(self,instruction): self.CheckArgumentCount(instruction.getArgCount(), 2, "INT2CHAR") arg1 = instruction.getArg(1) arg1.isVar() arg2 = instruction.getArg(2) arg2.isSymb() arg2Value = self.GetValue(arg2) try: if arg2Value["type"] != ArgumentType.INT: self.TypeErrorWithVariableOrNot(arg2,arg2,"INT2CHAR, Invalid unicode value, expected number in range(0 to 1,114,111)") value = int(arg2Value["value"]) if value not in range(0,1_114_112): ErrorHandler.printError("INT2CHAR, Invalid unicode value, expected number in range(0 to 1,114,111)",ErrorHandler.ERROR_WORK_WITH_STRING) value = chr(value) self.SetVariable(arg1.Type, arg1.Value,{"type" : ArgumentType.STRING, "value": value})
def __init__(self,file): """ If file is specified, load data into array arguments --------- file - name of file used for standard input for interpreting """ if file is not None: self.isStdin = False try: fp = open(file,"r") self.lines = [] for line in fp: line = line.replace("\n",'') self.lines.append(line) fp.close() except: ErrorHandler.printError("Error with opening file",ErrorHandler.ERROR_INPUT_FILE) else: self.isStdin = True
def __init__(self, _type, value): """ Initialization of argument, setting Type and casting value to specific type """ self.Type = _type self.Value = value if isinstance(_type, str): self.Type = self._setType(_type) self.Value = "" if value is None else value else: return #Its from stack if self.Type == ArgumentType.VAR: value = value.split("@") if len(value) != 2: ErrorHandler.printError( "Wrong format of variable " + self.Value, ErrorHandler.ERROR_SEMANTIC_REDEFINITION) self.Type = self._setType(value[0]) self.Value = value[1] elif self.Type == ArgumentType.STRING: def replace(match): try: match = match.group() return chr(int(match[1:])) except: ErrorHandler.printError( "Error while escaping special sequences in string", ErrorHandler.ERROR_RUNTIME_WRONG_OPERAND_TYPE) self.Value = re.sub(r'\\\d{3}', replace, self.Value) elif self.Type == ArgumentType.BOOL: self.Value = True if value == "true" else False elif self.Type == ArgumentType.NIL: self.Value = None elif self.Type == ArgumentType.INT: try: self.Value = int(value) except: ErrorHandler.printError( "Unexpected value for int", ErrorHandler.ERROR_RUNTIME_WRONG_OPERAND_TYPE) elif self.Type == ArgumentType.FLOAT: self.Value = float.fromhex(value) if not isinstance(self.Value, float): ErrorHandler.printError( "Unexpected value for float", ErrorHandler.ERROR_RUNTIME_WRONG_OPERAND_TYPE)
def GetVariable(self,frame,name,isType = False): try: var = None if frame == ArgumentType.GF: var = self.GF[name] elif frame == ArgumentType.LF: var = self.LF[name] elif frame == ArgumentType.TF: var = self.TF[name] if var["type"] == ArgumentType.UNSET and isType == False: ErrorHandler.printError("Getting uninitialized variable", ErrorHandler.ERROR_RUNTIME_MISSING_VALUE) return var except KeyError: #Undefined variable if (frame == ArgumentType.TF and self.TF == None) or (frame == ArgumentType.LF and self.LF == None): ErrorHandler.printError("Reading from nonexisting frame",ErrorHandler.ERROR_RUNTIME_NOEXIST_FRAME) else: ErrorHandler.printError("Undefined variable "+str(name)+ " on "+str(frame), ErrorHandler.ERROR_UNDEFINED_VARIABLE) except TypeError: #Frame is None ErrorHandler.printError("Access to undefined frame", ErrorHandler.ERROR_RUNTIME_NOEXIST_FRAME)
def getInstructions(self): root = self.getRoot() instructions_arr = [] for instruction in root: if instruction.tag != "instruction": ErrorHandler.printError("Unknown element in program", ErrorHandler.ERROR_UNEXPECTED_XML) inst = Instruction() try: inst.setOpcode(instruction.attrib["opcode"]) except: ErrorHandler.printError( "Missing opcode attribute for instruction", ErrorHandler.ERROR_UNEXPECTED_XML) try: inst.setOrder(instruction.attrib["order"]) except: ErrorHandler.printError( "Missing order attribute for instruction", ErrorHandler.ERROR_UNEXPECTED_XML) for arg in instruction: reResult = re.findall(r"^arg\d$", arg.tag) if (reResult): argIndex = arg.tag[3] else: ErrorHandler.printError( "Unknown child for instruction" + inst.getOpcode(), ErrorHandler.ERROR_UNEXPECTED_XML) try: argument = Argument(arg.attrib["type"], arg.text) except: ErrorHandler.printError( "Missing type attribute for instruction " + inst.getOpcode() + " argument", ErrorHandler.ERROR_UNEXPECTED_XML) inst.setArg(argIndex, argument) #check if exist instruction with same order if any(x.Order == inst.Order for x in instructions_arr): ErrorHandler.printError("Duplicity in order attribute", ErrorHandler.ERROR_UNEXPECTED_XML) if inst.Order < 1: ErrorHandler.printError( "Order attribute must be positive number", ErrorHandler.ERROR_UNEXPECTED_XML) instructions_arr.append(inst) instructions_arr = sorted(instructions_arr, key=lambda x: x.Order) return instructions_arr
def CheckArgumentCount(self,count,expected, opcode): if count != expected: ErrorHandler.printError("Wrong format of "+opcode+" instruction",ErrorHandler.ERROR_UNEXPECTED_XML)
def InterpretReturn(self,instruction): self.CheckArgumentCount(instruction.getArgCount(), 0, "RETURN") try: self.ProgramCounter = self.CallStack.pop() except: ErrorHandler.printError("Return with empty call stack",ErrorHandler.ERROR_RUNTIME_MISSING_VALUE)
def InstructionMapper(self, instruction): func = self.mapper.get(instruction.Opcode) if func is not None: return func(self,instruction) else: ErrorHandler.printError("Unknown instruction "+instruction.Opcode,ErrorHandler.ERROR_UNEXPECTED_XML)
def TypeErrorWithVariableOrNot(self,arg1,arg2, message): if not arg1.isVar(soft=True) and not arg2.isVar(soft=True): ErrorHandler.printError(message,ErrorHandler.ERROR_UNEXPECTED_XML) else: ErrorHandler.printError(message,ErrorHandler.ERROR_RUNTIME_WRONG_OPERAND_TYPE)
def checkLabel(self, labelName): if labelName not in self.LABELS.keys(): ErrorHandler.printError("Jump to undefined label",ErrorHandler.ERROR_SEMANTIC_REDEFINITION)
def SetVariable(self,varFrame,varName,toStore, Access = True): argValue = toStore["value"] argType = toStore["type"] if varFrame == ArgumentType.STACK: self.DataStack.append({"type" : argType, "value": argValue}) elif varFrame == ArgumentType.GF: if Access and (varName not in self.GF.keys()): ErrorHandler.printError("Access to undefined variable "+str(varName)+" on "+str(varFrame)+" frame", ErrorHandler.ERROR_UNDEFINED_VARIABLE) elif not Access and (varName in self.GF.keys()): ErrorHandler.printError("Redeclaring variable "+str(varName)+" on "+str(varFrame)+" frame",ErrorHandler.ERROR_SEMANTIC_REDEFINITION) self.GF[varName] = toStore elif varFrame == ArgumentType.LF: if self.LF == None: ErrorHandler.printError("Access to undefined frame", ErrorHandler.ERROR_RUNTIME_NOEXIST_FRAME) elif Access and (varName not in self.LF.keys()): ErrorHandler.printError("Access to undefined variable "+str(varName)+" on "+str(varFrame)+" frame",ErrorHandler.ERROR_UNDEFINED_VARIABLE) elif not Access and (varName in self.LF.keys()): ErrorHandler.printError("Redeclaring variable "+str(varName)+" on "+str(varFrame)+" frame",ErrorHandler.ERROR_SEMANTIC_REDEFINITION) self.LF[varName] = toStore elif varFrame == ArgumentType.TF: if self.TF == None: ErrorHandler.printError("Access to undefined frame", ErrorHandler.ERROR_RUNTIME_NOEXIST_FRAME) elif Access and (varName not in self.TF.keys()): ErrorHandler.printError("Access to undefined variable "+str(varName)+" on "+str(varFrame)+" frame",ErrorHandler.ERROR_UNDEFINED_VARIABLE) elif not Access and (varName in self.TF.keys()): ErrorHandler.printError("Redeclaring variable "+str(varName)+" on "+str(varFrame)+" frame",ErrorHandler.ERROR_SEMANTIC_REDEFINITION) self.TF[varName] = toStore