def p_factor(p): '''factor : cst_expression | '(' seen_lpar superexpression ')' seen_rpar ''' global instructions if instructions.topOperatorEquals('*') or instructions.topOperatorEquals('/'): op2 = instructions.popOperand() op1 = instructions.popOperand() operator = instructions.popOperator() if op1.Type is 'arr' and op2.Type is 'arr': op2.Type = arrayType.pop() op1.Type = arrayType.pop() resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) op1 = '(' + str(op1.Address) + ')' op2 = '(' + str(op2.Address) + ')' elif op1.Type is 'arr': op1.Type = arrayType.pop() resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) op1 = '(' + str(op1.Address) + ')' elif op2.Type is 'arr': op2.Type = arrayType.pop() resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) op2 = '(' + str(op2.Address) + ')' else: resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) if result: if operator is '*': operator = 'MUL' elif operator is '/': operator = 'DIV' instructions.generateQuadruple(operator, op1, op2, result) instructions.pushOperand(result) else: print ("FACTOR ERROR")
def p_seen_comp(p): '''seen_comp :''' global instructions op2 = instructions.popOperand() op1 = instructions.popOperand() operator = instructions.popOperator() if op1.Type is 'arr' and op2.Type is 'arr': op2.Type = arrayType.pop() op1.Type = arrayType.pop() resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) op1 = '(' + str(op1.Address) + ')' op2 = '(' + str(op2.Address) + ')' elif op1.Type is 'arr': op1.Type = arrayType.pop() resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) op1 = '(' + str(op1.Address) + ')' elif op2.Type is 'arr': op2.Type = arrayType.pop() resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) op2 = '(' + str(op2.Address) + ')' else: resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) if result: operator = {"==" : "CEQ", "!=" : "CNE", "<" : "CLT", ">" : "CGT", "<=" : "CLE", ">=" : "CGE"}[operator] instructions.generateQuadruple(operator, op1, op2, result) instructions.pushOperand(result) else: print ("SEEN_COMPARISON ERROR")
def p_seen_term(p): '''seen_term :''' global instructions if instructions.topOperatorEquals('+') or instructions.topOperatorEquals('-'): op2 = instructions.popOperand() op1 = instructions.popOperand() operator = instructions.popOperator() if op1.Type is 'arr' and op2.Type is 'arr': op2.Type = arrayType.pop() op1.Type = arrayType.pop() resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) op1 = '(' + str(op1.Address) + ')' op2 = '(' + str(op2.Address) + ')' elif op1.Type is 'arr': op1.Type = arrayType.pop() resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) op1 = '(' + str(op1.Address) + ')' elif op2.Type is 'arr': op2.Type = arrayType.pop() resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) op2 = '(' + str(op2.Address) + ')' else: resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) if result: if operator is '+': operator = 'ADD' elif operator is '-': operator = 'SUB' instructions.generateQuadruple(operator, op1, op2, result) instructions.pushOperand(result) else: print ("SEEN_TERM ERROR")
def p_seen_arg(p): '''seen_arg : ''' global instructions,currentDirectory,functionDirectory,parameterCounter, parameterCounterInt, parameterCounterDou, parameterCounterStr op1 = instructions.popOperand() if parameterCounter < len(functionDirectory.parameters): nextParam = functionDirectory.parameters[parameterCounter] variable = functionDirectory.get_variable(nextParam) compatibleType = getResultingType('=', variable.Type, op1.Type) if variable.Type is compatibleType: if variable.Type is int: instructions.generateQuadruple('EQU', op1, 0, Variable('Param{}'.format(parameterCounter), variable.Type, parameterCounterInt + 10000)) parameterCounterInt += 1 elif variable.Type is float: instructions.generateQuadruple('EQU', op1, 0, Variable('Param{}'.format(parameterCounter), variable.Type, parameterCounterDou + 11000)) parameterCounterDou += 1 elif variable.Type is str: instructions.generateQuadruple('EQU', op1, 0, Variable('Param{}'.format(parameterCounter), variable.Type, parameterCounterStr + 12000)) parameterCounterStr += 1 else: print ("ERROR: Incompatible arguments. Received '{}', expected '{}'!".format(op1.Type,functionDirectory.get_variable(nextParam).Type)) raise SystemExit parameterCounter += 1 else: print ("ERROR: Function '{}' received more arguments than expected!".format(functionDirectory.identifier)) raise SystemExit
def p_return(p): '''return : RETURN superexpression SEMICOLON''' global currentDirectory, instructions if currentDirectory.Type is not 'void': var = instructions.popOperand() compatibleType = getResultingType('=', currentDirectory.Type, var.Type) if compatibleType: instructions.generateQuadruple('RET',var,0,0) else: print ("ERROR: Incompatible return types! Received {}, expected {}!".format(var.Type, currentDirectory.Type)) raise SystemExit
def p_expression(p): '''expression : numeric_expression compare''' global instructions, currentDirectory if instructions.topOperatorEquals('&&') or instructions.topOperatorEquals('||') : op2 = instructions.popOperand() op1 = instructions.popOperand() operator = instructions.popOperator() resultingType = getResultingType(operator, op1.Type, op2.Type) if resultingType is None: print ("ERROR: Operation '{}' between '{}' and '{}' cannot be performed. Incompatible types!".format(operator, op1.Type, op2.Type)) raise SystemExit result = currentDirectory.add_temp(resultingType) if result: operator = {"&&" : "AND", "||" : "ORR"}[operator] instructions.generateQuadruple(operator, op1, op2, result) instructions.pushOperand(result) else: print ("EXPRESSION ERROR")
def p_variable_declarator3(p): '''variable_declarator3 : '=' superexpression | empty''' global instructions, currentDirectory if p[1]: variable = currentDirectory.get_variable(p[-3]) if variable and variable.Dimension == 0: op1 = instructions.popOperand() result = variable operator = p[1] validType = getResultingType(operator, result.Type, op1.Type) if validType: operator = 'EQU' instructions.generateQuadruple(operator, op1, 0, result) else: print ("ERROR: Invalid types in line {}. Variable '{}' of type '{}' cannot store '{}'!".format(p.lineno(1), currentDirectory.get_variable(result.Name).Name, currentDirectory.get_variable(result.Name).Type, currentDirectory.get_variable(op1.Name).Name)) raise SystemExit else: if variable.Dimension > 0: print("ERROR: Variable '{}' cannot be initialized since it is an array, in line {}!".format(p[-3], p.lineno(1))) else: print("ERROR: Variable '{}' not declared in this scope, in line {}!".format(p[-3], p.lineno(1))) raise SystemExit
def p_id_or_array(p): '''id_or_array : '=' superexpression | LSQUARE seen_LSQUARE superexpression RSQUARE seen_RSQUARE '=' superexpression''' global instructions, currentDirectory variable = currentDirectory.get_variable(p[-1]) if variable: if variable.Dimension > 0 and p[1] == '[': operator = p[6] op2 = variable.Dimension tempOp1 = instructions.popOperand() #value to be assigned. op1 = instructions.popOperand() #index of the array. if op1.Type is int: instructions.generateQuadruple('VER', op1, op2, variable.Address) result = currentDirectory.add_temp(int) result.Type = 'arr' arrayType.append(variable.Type) instructions.generateQuadruple('OFF', variable.Address, op1, result) instructions.pushOperand(result) op1 = tempOp1 result = instructions.popOperand() if op1.Type is 'arr' and result.Type is 'arr': result.Type = arrayType.pop() op1.Type = arrayType.pop() validType = getResultingType(operator, result.Type, op1.Type) if validType: op1 = '(' + str(op1.Address) + ')' result = '(' + str(result.Address) + ')' operator = 'EQU' instructions.generateQuadruple(operator, op1, 0, result) else: print ("ERROR: Invalid types! Variable '{}' cannot store '{}'!".format(currentDirectory.get_variable(result.Name), currentDirectory.get_variable(op1.Name))) raise SystemExit else: result.Type = arrayType.pop() validType = getResultingType(operator, result.Type, op1.Type) if validType: result = '(' + str(result.Address) + ')' operator = 'EQU' instructions.generateQuadruple(operator, op1, 0, result) else: print ("ERROR: Invalid types! Variable '{}' cannot store '{}'!".format(currentDirectory.get_variable(result.Name), currentDirectory.get_variable(op1.Name))) raise SystemExit else: print("ERROR: Type error. Array index must be of type int, found {} at line {}!".format(op1.Type, p.lineno(1))) raise SystemExit elif p[1] == '=' and variable.Dimension == 0: op1 = instructions.popOperand() result = variable operator = p[1] if op1.Type is 'arr': op1.Type = arrayType.pop() validType = getResultingType(operator, result.Type, op1.Type) if validType: op1 = '(' + str(op1.Address) + ')' operator = 'EQU' instructions.generateQuadruple(operator, op1, 0, result) else: print ("ERROR: Invalid types! Variable '{}' cannot store '{}'!".format(currentDirectory.get_variable(result.Name), currentDirectory.get_variable(op1.Name))) raise SystemExit else: validType = getResultingType(operator, result.Type, op1.Type) if validType: operator = 'EQU' instructions.generateQuadruple(operator, op1, 0, result) else: print ("ERROR: Invalid types! Variable '{}' cannot store '{}'!".format(currentDirectory.get_variable(result.Name), currentDirectory.get_variable(op1.Name))) raise SystemExit else: if p[1] == '=': print("ERROR: Variable '{}' is of type Array, must be accessed through an index, line {}!".format(p[-1], p.lineno(1))) raise SystemExit elif p[1] == '[': print("ERROR: Variable '{}' is not of type Array, line {}!".format(p[-1], p.lineno(1))) raise SystemExit else: print("ERROR: Variable '{}' not declared in this scope, line {}!".format(p[-1], p.lineno(1))) raise SystemExit