def p_assignment_redefinition(p): 'assignment : IDENTIFIER OP_ASSIGNMENT expression' # To store information p[0] = {} identifierEntry = ST.exists(p[1]) if identifierEntry == True: ST.addAttribute(p[1], 'type', p[3]['type']) # Check if the function is in the current scope or parent one if ST.existsInCurrentScope(p[1]): place = ST.getAttribute(p[1], ST.getCurrentScope()) else: # store the address into the address descriptor displayValue, offset = ST.getAttribute( p[1], 'scopeLevel'), ST.getAttribute(p[1], 'offset') place = ST.newTemp((displayValue, offset), variable=p[1]) ST.addAttribute(p[1], ST.getCurrentScope(), place) TAC.emit(place, p[3]['place'], '', '=') else: debug.printError('Undefined Variable "%s"' % p[1]) raise SyntaxError # print the name of the statement debug.printStatement("ASSIGNMENT of %s" % p[1])
def p_insertArgs(p): 'M_insertArgs : empty' # Add identifiers to local scope for argument in p[-2]: # Any callback is stored as a CALLBACK which is a different type if ST.existsInCurrentScope(argument['name']): debug.printError("Redefinition of argument '%s'" % argument['name']) raise SyntaxError else: if argument['type'] == 'FUNCTION': ST.addIdentifier(argument['name'], 'CALLBACK') else: ST.addIdentifier(argument['name'], argument['type']) # store the address into the address descriptor # The parameters have to loaded in form memory displayValue, offset = ST.getAttribute( argument['name'], 'scopeLevel'), ST.getAttribute(argument['name'], 'offset') place = ST.newTemp((displayValue, offset), variable=argument['name'], loadFromMemory=True) ST.addAttribute(argument['name'], ST.getCurrentScope(), place) debug.printStatementBlock("Argument '%s' of type '%s'" % (argument['name'], argument['type'])) # Now we store the number of parameters in the function ST.addAttributeToCurrentScope('numParam', len(p[-2]))
def p_insertArgs(p): 'M_insertArgs : empty' # Add identifiers to local scope for argument in p[-2]: # Any callback is stored as a CALLBACK which is a different type if ST.existsInCurrentScope(argument['name']): debug.printError("Redefinition of argument '%s'" %argument['name']) raise SyntaxError else: if argument['type'] == 'FUNCTION': ST.addIdentifier(argument['name'], 'CALLBACK') else: ST.addIdentifier(argument['name'], argument['type']) # store the address into the address descriptor # The parameters have to loaded in form memory displayValue, offset = ST.getAttribute(argument['name'], 'scopeLevel'), ST.getAttribute(argument['name'], 'offset') place = ST.newTemp((displayValue, offset), variable=argument['name'], loadFromMemory=True) ST.addAttribute(argument['name'], ST.getCurrentScope(), place) debug.printStatementBlock("Argument '%s' of type '%s'" %(argument['name'], argument['type'])) # Now we store the number of parameters in the function ST.addAttributeToCurrentScope('numParam', len(p[-2]))
def p_assignment(p): 'assignment : VAR assignList' # In case the var is not present p[0] = {'type': 'VOID'} # Now we add all of these statements for identifier in p[2]: if not ST.existsInCurrentScope(identifier['name']): # Store information about the identifier ST.addIdentifier(identifier['name'], identifier['type']) # This is a new variable, so we link the temporary to our variable displayValue, offset = ST.getAttribute( identifier['name'], 'scopeLevel'), ST.getAttribute(identifier['name'], 'offset') ST.changeMemoryLocationOfTemp(identifier['place'], (displayValue, offset), variable=identifier['name']) ST.addAttribute(identifier['name'], ST.getCurrentScope(), identifier['place']) ST.addAttribute(identifier['name'], 'reference', identifier['reference']) # print the name of the statement debug.printStatement("ASSIGNMENT of %s" % identifier['name']) else: debug.printError('Redefined Variable "%s"' % identifier['name']) raise SyntaxError
def p_expression_identifier(p): 'expression : IDENTIFIER' # Type rules p[0] = {} # We have to check if the identifier exists in the current scope or not, and # accordingly load it in if ST.exists(p[1]): p[0]['type'] = ST.getAttribute(p[1], 'type') # Here we have to load in the value of the variable if not ST.existsInCurrentScope(p[1]): # If an identifier is used, we assume that it is present in memory displayValue, offset = ST.getAttribute( p[1], 'scopeLevel'), ST.getAttribute(p[1], 'offset') p[0]['place'] = ST.newTemp((displayValue, offset), variable=p[1], loadFromMemory=True) ST.addAttribute(p[1], ST.getCurrentScope(), p[0]['place']) else: p[0]['place'] = ST.getAttribute(p[1], ST.getCurrentScope()) else: p[0]['type'] = 'REFERENCE_ERROR' debug.printError('Undefined Variable "%s"' % p[1]) raise SyntaxError
def p_expression_unary(p): '''expression : OP_MINUS expression %prec UMINUS | OP_TYPEOF expression''' # Type rules expType = 'UNDEFINED' # Emit code p[0] = {} p[0]['place'] = ST.newTemp() # Conditional branch to figure out what code to emit and check types if p[1] == '-': if p[2]['type'] == 'NUMBER': expType = 'NUMBER' TAC.emit(p[0]['place'], p[2]['place'], '', 'uni-') else: expType = 'TYPE_ERROR' debug.printError('Type Mismatch in expression') raise SyntaxError else: expType = 'STRING' TAC.emit(p[0]['place'], p[2]['type'], '', '=') # Return type of the statment p[0]['type'] = expType
def p_returnStatement(p): 'returnStatement : RETURN expression' # Type rules p[0] = { 'type' : p[2]['type'] } # Get the current returnType from function returnType = ST.getAttributeFromCurrentScope('returnType') # If the function has not been assigned a return type as of yet if returnType == 'UNDEFINED': # Assign a returnType to the function if p[2]['type'] == 'FUNCTION': ST.addAttributeToCurrentScope('returnType', 'CALLBACK') debug.printStatement("Return statement of type 'CALLBACK'") else: ST.addAttributeToCurrentScope('returnType', p[2]['type']) debug.printStatement("Return statement of type '%s'" %p[2]['type']) elif p[2]['type'] != returnType: p[0]['type'] = 'TYPE_ERROR' debug.printError('Return Types dont match') raise SyntaxError else: # In this case, the return types match, so we needn't do anything pass # Emit code for the return type TAC.emit(p[2]['place'], '' ,'', 'RETURN')
def p_assignment_redefinition(p): 'assignment : IDENTIFIER OP_ASSIGNMENT expression' # To store information p[0] = {} identifierEntry = ST.exists(p[1]) if identifierEntry == True: ST.addAttribute(p[1], 'type', p[3]['type']) # Check if the function is in the current scope or parent one if ST.existsInCurrentScope(p[1]): place = ST.getAttribute(p[1], ST.getCurrentScope()) else: # store the address into the address descriptor displayValue, offset = ST.getAttribute(p[1], 'scopeLevel'), ST.getAttribute(p[1], 'offset') place = ST.newTemp((displayValue, offset), variable=p[1]) ST.addAttribute(p[1], ST.getCurrentScope(), place) TAC.emit(place, p[3]['place'], '', '=') else: debug.printError('Undefined Variable "%s"' %p[1]) raise SyntaxError # print the name of the statement debug.printStatement("ASSIGNMENT of %s" %p[1])
def p_expression_unary(p): '''expression : OP_MINUS expression %prec UMINUS | OP_TYPEOF expression''' # Type rules expType = 'UNDEFINED' # Emit code p[0] = {} p[0]['place'] = ST.newTemp() # Conditional branch to figure out what code to emit and check types if p[1] == '-': if p[2]['type'] == 'NUMBER': expType = 'NUMBER' TAC.emit(p[0]['place'], p[2]['place'] , '' , 'uni-') else: expType = 'TYPE_ERROR' debug.printError('Type Mismatch in expression') raise SyntaxError else: expType = 'STRING' TAC.emit(p[0]['place'], p[2]['type'] , '' , '=') # Return type of the statment p[0]['type'] = expType
def p_returnStatement(p): 'returnStatement : RETURN expression' # Type rules p[0] = {'type': p[2]['type']} # Get the current returnType from function returnType = ST.getAttributeFromCurrentScope('returnType') # If the function has not been assigned a return type as of yet if returnType == 'UNDEFINED': # Assign a returnType to the function if p[2]['type'] == 'FUNCTION': ST.addAttributeToCurrentScope('returnType', 'CALLBACK') debug.printStatement("Return statement of type 'CALLBACK'") else: ST.addAttributeToCurrentScope('returnType', p[2]['type']) debug.printStatement("Return statement of type '%s'" % p[2]['type']) elif p[2]['type'] != returnType: p[0]['type'] = 'TYPE_ERROR' debug.printError('Return Types dont match') raise SyntaxError else: # In this case, the return types match, so we needn't do anything pass # Emit code for the return type TAC.emit(p[2]['place'], '', '', 'RETURN')
def p_hint_error(p): 'hint : IDENTIFIER' # Pass in any empty object p[0] = {'name': p[1]} debug.printError("No hint provided for variable '%s'" % p[1]) raise SyntaxError
def p_hint_error(p): 'hint : IDENTIFIER' # Pass in any empty object p[0] = {'name': p[1]} debug.printError("No hint provided for variable '%s'" %p[1]) raise SyntaxError
def p_block_empty(p): 'block : SEP_OPEN_BRACE empty SEP_CLOSE_BRACE' # Emit code p[0] = {} # Empty blocks are not allowed, this points out this mistake debug.printError('Empty blocks are not allowed') raise SyntaxError
def p_block_empty(p): 'block : SEP_OPEN_BRACE empty SEP_CLOSE_BRACE' # Emit code p[0] = {} # Empty blocks are not allowed, this points out this mistake debug.printError('Empty blocks are not allowed') raise SyntaxError
def p_arrayList(p): 'arrayList : expression SEP_COMMA arrayList' print p[3] if p[3]['type'] == 'UNDEFINED': p[0] = {'value': p[1]['place'], 'type': p[1]['type']} elif p[1]['type'] == p[3]['type']: p[0] = {'value': [p[1]['place']] + p[3]['value'], 'type': p[1]['type']} else: debug.printError('Elements of an array must be of the same type')
def p_arrayList(p): 'arrayList : expression SEP_COMMA arrayList' print p[3] if p[3]['type'] == 'UNDEFINED': p[0] = {'value': p[1]['place'], 'type' : p[1]['type']} elif p[1]['type'] == p[3]['type']: p[0] = {'value': [p[1]['place']] + p[3]['value'], 'type' : p[1]['type']} else: debug.printError('Elements of an array must be of the same type')
def p_functionCall(p): 'functionCall : IDENTIFIER SEP_OPEN_PARENTHESIS actualParameters SEP_CLOSE_PARENTHESIS' p[0] = {} # If the identifier does not exist then we output error if not ST.exists(p[1]): p[0]['type'] = 'REFERENCE_ERROR' debug.printError("Function '%s' is not defined" % p[1]) raise SyntaxError else: identifierType = ST.getAttribute(p[1], 'type') # If the function exists in the current scope if identifierType in ['FUNCTION', 'CALLBACK']: if not ST.existsInCurrentScope(p[1]): # The definition of the function has to be loaded in from memory displayValue, offset = ST.getAttribute( p[1], 'scopeLevel'), ST.getAttribute(p[1], 'offset') place = ST.newTemp((displayValue, offset), variable=p[1], loadFromMemory=True) ST.addAttribute(p[1], ST.getCurrentScope(), place) else: place = ST.getAttribute(p[1], ST.getCurrentScope()) # Now we print the param statements for param in p[3]: TAC.emit(param, '', '', 'PARAM') # The name of the function debug.printStatementBlock("Function call to '%s'" % p[1]) # We jump to the function TAC.emit('', '', place, 'JUMPLABEL') # In case the function call is used in an expression # The type of the statment is dependent on the input condition if identifierType != 'CALLBACK': reference = ST.getAttribute(p[1], 'reference') p[0]['type'] = ST.getAttributeFromFunctionList( reference, 'returnType') if p[0]['type'] != 'CALLBACK': returnPlace = ST.newTemp() TAC.emit(returnPlace, '', '', 'FUNCTION_RETURN') p[0]['place'] = returnPlace else: p[0]['type'] = 'CALLBACK' else: p[0]['type'] = 'REFERENCE_ERROR' debug.printError('Not a function "%s"' % p[1]) raise SyntaxError
def p_error(p): debug.printError("Whoa. You are seriously hosed.") # Read ahead looking for a closing '}' tok = parser.token() if not tok: while 1: if not tok or tok.type in ['SEP_SEMICOLON', 'SEP_OPEN_BRACE', 'SEP_CLOSE_BRACE']: break tok = parser.token() # Get the next token parser.restart()
def p_error(p): debug.printError("Whoa. You are seriously hosed.") # Read ahead looking for a closing '}' tok = parser.token() if not tok: while 1: if not tok or tok.type in ['SEP_SEMICOLON', 'SEP_OPEN_BRACE', 'SEP_CLOSE_BRACE']: break tok = parser.token() # Get the next token parser.restart()
def p_expression_functionCall(p): 'expression : functionCall' # Return the value of the function p[0] = {} p[0]['type'] = p[1]['type'] if p[1]['type'] == 'CALLBACK': debug.printError('Callback functions cannot be used as expressions') raise SyntaxError else: p[0]['place'] = p[1]['place']
def p_expression_functionCall(p): 'expression : functionCall' # Return the value of the function p[0] = {} p[0]['type'] = p[1]['type'] if p[1]['type'] == 'CALLBACK': debug.printError('Callback functions cannot be used as expressions') raise SyntaxError else: p[0]['place'] = p[1]['place']
def p_printStatement(p): 'printStatement : CONSOLE OP_DOT LOG SEP_OPEN_PARENTHESIS printList SEP_CLOSE_PARENTHESIS' p[0] = {} for printIterator in p[5]: # Check if the given expression is printable or not expType = printIterator.get('type') if expType in ['STRING', 'NUMBER', 'BOOLEAN', 'UNDEFINED']: TAC.emit(printIterator['place'], '', printIterator['type'], 'PRINT') debug.printStatement("Print Statement of type %s" %printIterator['type']) else: debug.printError('Given expression is not a printable type') raise SyntaxError
def p_ifThen(p): 'ifThen : IF SEP_OPEN_PARENTHESIS expression SEP_CLOSE_PARENTHESIS M_ifBranch block' # Type rules if p[3]['type'] != 'BOOLEAN': debug.printError('If condition must be a boolean') raise SyntaxError p[0] = {} # For break statement and next waiting functions p[0]['nextList'] = TAC.merge(p[5].get('falseList', []), p[6].get('nextList', [])) p[0]['loopEndList'] = p[6].get('loopEndList', []) p[0]['loopBeginList'] = p[6].get('loopBeginList',[])
def p_ifThen(p): 'ifThen : IF SEP_OPEN_PARENTHESIS expression SEP_CLOSE_PARENTHESIS M_ifBranch block' # Type rules if p[3]['type'] != 'BOOLEAN': debug.printError('If condition must be a boolean') raise SyntaxError p[0] = {} # For break statement and next waiting functions p[0]['nextList'] = TAC.merge(p[5].get('falseList', []), p[6].get('nextList', [])) p[0]['loopEndList'] = p[6].get('loopEndList', []) p[0]['loopBeginList'] = p[6].get('loopBeginList',[])
def p_functionCall(p): 'functionCall : IDENTIFIER SEP_OPEN_PARENTHESIS actualParameters SEP_CLOSE_PARENTHESIS' p[0] = {} # If the identifier does not exist then we output error if not ST.exists(p[1]): p[0]['type'] = 'REFERENCE_ERROR' debug.printError("Function '%s' is not defined" %p[1]) raise SyntaxError else: identifierType = ST.getAttribute(p[1], 'type') # If the function exists in the current scope if identifierType in [ 'FUNCTION', 'CALLBACK' ]: if not ST.existsInCurrentScope(p[1]): # The definition of the function has to be loaded in from memory displayValue, offset = ST.getAttribute(p[1], 'scopeLevel'), ST.getAttribute(p[1], 'offset') place = ST.newTemp((displayValue, offset),variable=p[1], loadFromMemory=True) ST.addAttribute(p[1], ST.getCurrentScope(), place) else: place = ST.getAttribute(p[1], ST.getCurrentScope()) # Now we print the param statements for param in p[3]: TAC.emit(param, '', '', 'PARAM') # The name of the function debug.printStatementBlock("Function call to '%s'" %p[1]) # We jump to the function TAC.emit('', '', place, 'JUMPLABEL') # In case the function call is used in an expression # The type of the statment is dependent on the input condition if identifierType != 'CALLBACK': reference = ST.getAttribute(p[1], 'reference') p[0]['type'] = ST.getAttributeFromFunctionList(reference, 'returnType') if p[0]['type'] != 'CALLBACK': returnPlace = ST.newTemp() TAC.emit(returnPlace, '', '', 'FUNCTION_RETURN') p[0]['place'] = returnPlace else: p[0]['type'] = 'CALLBACK' else: p[0]['type'] = 'REFERENCE_ERROR' debug.printError('Not a function "%s"' %p[1]) raise SyntaxError
def p_printStatement(p): 'printStatement : CONSOLE OP_DOT LOG SEP_OPEN_PARENTHESIS printList SEP_CLOSE_PARENTHESIS' p[0] = {} for printIterator in p[5]: # Check if the given expression is printable or not expType = printIterator.get('type') if expType in ['STRING', 'NUMBER', 'BOOLEAN', 'UNDEFINED']: TAC.emit(printIterator['place'], '', printIterator['type'], 'PRINT') debug.printStatement("Print Statement of type %s" %printIterator['type']) else: debug.printError('Given expression is not a printable type') raise SyntaxError
def p_ifThenElse(p): 'ifThenElse : IF SEP_OPEN_PARENTHESIS expression SEP_CLOSE_PARENTHESIS M_ifBranch block ELSE M_elseBranch block' # Type rules if p[3]['type'] != 'BOOLEAN': debug.printError('If condition must be a boolean') raise SyntaxError p[0] = {} # backPatch the if branch TAC.backPatch(p[5]['falseList'], p[8]['quad']) p[0]['nextList'] = p[8]['nextList'] # For break statement p[0]['loopEndList'] = TAC.merge(p[9].get('loopEndList', []), p[6].get('loopEndList', [])) p[0]['loopBeginList'] = TAC.merge(p[9].get('loopBeginList', []), p[6].get('loopBeginList', []))
def p_ifThenElse(p): 'ifThenElse : IF SEP_OPEN_PARENTHESIS expression SEP_CLOSE_PARENTHESIS M_ifBranch block ELSE M_elseBranch block' # Type rules if p[3]['type'] != 'BOOLEAN': debug.printError('If condition must be a boolean') raise SyntaxError p[0] = {} # backPatch the if branch TAC.backPatch(p[5]['falseList'], p[8]['quad']) p[0]['nextList'] = p[8]['nextList'] # For break statement p[0]['loopEndList'] = TAC.merge(p[9].get('loopEndList', []), p[6].get('loopEndList', [])) p[0]['loopBeginList'] = TAC.merge(p[9].get('loopBeginList', []), p[6].get('loopBeginList', []))
def p_expression_logical_not(p): 'expression : OP_NOT expression' # Type rules expType = 'BOOLEAN' # Backpatching code p[0] = {} p[0]['place'] = ST.newTemp() if p[2]['type'] != 'BOOLEAN': expType = 'TYPE_ERROR' debug.printError('Operands to logical expressions must be integers') raise SyntaxError else: TAC.emit(p[0]['place'], p[2]['place'], '', p[1]) # Type of the expression p[0]['type'] = expType
def p_expression_logical_not(p): 'expression : OP_NOT expression' # Type rules expType = 'BOOLEAN' # Backpatching code p[0] = {} p[0]['place'] = ST.newTemp() if p[2]['type'] != 'BOOLEAN': expType = 'TYPE_ERROR' debug.printError('Operands to logical expressions must be integers') raise SyntaxError else: TAC.emit(p[0]['place'], p[2]['place'], '' , p[1]) # Type of the expression p[0]['type'] = expType
def p_expression_logical_or(p): 'expression : expression OP_OR M_quad expression' # Type rules expType = 'UNDEFINED' # Backpatching code p[0] = {} p[0]['place'] = ST.newTemp() if p[1]['type'] == p[4]['type'] == 'BOOLEAN': expType = 'BOOLEAN' TAC.emit(p[0]['place'], p[1]['place'], p[4]['place'], p[2]) else: expType = 'TYPE_ERROR' debug.printError('Operands to logical expressions must be integers') raise SyntaxError # Type of the expression p[0]['type'] = expType
def p_expression_logical_or(p): 'expression : expression OP_OR M_quad expression' # Type rules expType = 'UNDEFINED' # Backpatching code p[0] = {} p[0]['place'] = ST.newTemp() if p[1]['type'] == p[4]['type'] == 'BOOLEAN': expType = 'BOOLEAN' TAC.emit(p[0]['place'], p[1]['place'], p[4]['place'] , p[2]) else: expType = 'TYPE_ERROR' debug.printError('Operands to logical expressions must be integers') raise SyntaxError # Type of the expression p[0]['type'] = expType
def p_while(p): 'whileStatement : WHILE M_quad SEP_OPEN_PARENTHESIS expression SEP_CLOSE_PARENTHESIS M_whileBranch block' # Emit code p[0] = {} p[0]['nextList'] = [] # Backpatch if p[4]['type'] == 'BOOLEAN': # Backpatch continue statements and break statements TAC.backPatch(p[7]['loopBeginList'], p[2]['quad']) p[0]['nextList'] = TAC.merge(p[7].get('loopEndList', []), p[7].get('nextList', [])) p[0]['nextList'] = TAC.merge(p[6].get('falseList', []), p[0].get('nextList', [])) # Loop around TAC.emit('', '', p[2]['quad'], 'GOTO') else: debug.printError('The condition of while should be a boolean') raise SyntaxError p[0]['type'] = 'VOID'
def p_while(p): 'whileStatement : WHILE M_quad SEP_OPEN_PARENTHESIS expression SEP_CLOSE_PARENTHESIS M_whileBranch block' # Emit code p[0] = {} p[0]['nextList'] = [] # Backpatch if p[4]['type'] == 'BOOLEAN': # Backpatch continue statements and break statements TAC.backPatch(p[7]['loopBeginList'], p[2]['quad']) p[0]['nextList'] = TAC.merge(p[7].get('loopEndList', []), p[7].get('nextList', [])) p[0]['nextList'] = TAC.merge(p[6].get('falseList', []), p[0].get('nextList', [])) # Loop around TAC.emit('', '', p[2]['quad'], 'GOTO') else: debug.printError('The condition of while should be a boolean') raise SyntaxError p[0]['type'] = 'VOID'
def p_statement_error(p): '''statement : assignment M_quad | breakStatement M_quad | returnStatement M_quad | continueStatement M_quad | printStatement M_quad | functionCall M_quad''' # Emit code p[0] = {} # Statements waiting for the next list get backpatched nextList = p[1].get('nextList', []) TAC.backPatch(nextList, p[2]['quad']) # break statements and continue statements need to pushed up p[0]['loopEndList'] = p[1].get('loopEndList', []) p[0]['loopBeginList'] = p[1].get('loopBeginList', []) # Raise an error debug.printError('Semicolon missing') raise SyntaxError
def p_declaration(p): 'declaration : VAR decList' # Add identifiers to local scope for identifierName in p[2]: # Put the identifier into the symbolTable identifierEntry = ST.existsInCurrentScope(identifierName) if identifierEntry == False: ST.addIdentifier(identifierName, 'UNDEFINED') # Create a temporary for the current scope displayValue, offset = ST.getAttribute(identifierName, 'scopeLevel'), ST.getAttribute(identifierName, 'offset') place = ST.newTemp((displayValue, offset), variable=identifierName) ST.addAttribute(identifierName, ST.getCurrentScope(), place) else: debug.printError('Redefined Variable "%s"' %identifierName) raise SyntaxError debug.printStatement("Declaration '%s'" %identifierName) # Type rules p[0] = {}
def p_statement_error(p): '''statement : assignment M_quad | breakStatement M_quad | returnStatement M_quad | continueStatement M_quad | printStatement M_quad | functionCall M_quad''' # Emit code p[0] = {} # Statements waiting for the next list get backpatched nextList = p[1].get('nextList', []) TAC.backPatch(nextList, p[2]['quad']) # break statements and continue statements need to pushed up p[0]['loopEndList'] = p[1].get('loopEndList', []) p[0]['loopBeginList'] = p[1].get('loopBeginList', []) # Raise an error debug.printError('Semicolon missing') raise SyntaxError
def p_declaration(p): 'declaration : VAR decList' # Add identifiers to local scope for identifierName in p[2]: # Put the identifier into the symbolTable identifierEntry = ST.existsInCurrentScope(identifierName) if identifierEntry == False: ST.addIdentifier(identifierName, 'UNDEFINED') # Create a temporary for the current scope displayValue, offset = ST.getAttribute(identifierName, 'scopeLevel'), ST.getAttribute(identifierName, 'offset') place = ST.newTemp((displayValue, offset), variable=identifierName) ST.addAttribute(identifierName, ST.getCurrentScope(), place) else: debug.printError('Redefined Variable "%s"' %identifierName) raise SyntaxError debug.printStatement("Declaration '%s'" %identifierName) # Type rules p[0] = {}
def p_scope(p): 'M_scope : empty' p[0] = {} # Name the function p[0]['reference'] = ST.nameAnon() # Now add the identifier as a function reference if p[-1] != None: # Check for anon function # Check if the function exists or not if ST.existsInCurrentScope(p[-1]): debug.printError("Redefinition of function '%s'" % p[-1]) raise SyntaxError else: # Print to console debug.printStatementBlock("Definition of function '%s'" % p[-1]) # Create a new variable to hold the function ST.addIdentifier(p[-1], 'FUNCTION') # Create a new temporary for the function and store it in the addressList displayValue, offset = ST.getAttribute( p[-1], 'scopeLevel'), ST.getAttribute(p[-1], 'offset') place = ST.newTemp((displayValue, offset), variable=p[-1]) ST.addAttribute(p[-1], ST.getCurrentScope(), place) ST.addAttribute(p[-1], 'reference', p[0]['reference']) # Emit the location of the function reference TAC.emit(place, p[0]['reference'], '', '=REF') else: # Print to console debug.printStatementBlock('Function Definition "%s"' % p[0]['reference']) # Create a function scope ST.addScope(p[0]['reference']) TAC.createFunctionCode(p[0]['reference'])
def p_expression_identifier(p): 'expression : IDENTIFIER' # Type rules p[0] = {} # We have to check if the identifier exists in the current scope or not, and # accordingly load it in if ST.exists(p[1]): p[0]['type'] = ST.getAttribute(p[1], 'type') # Here we have to load in the value of the variable if not ST.existsInCurrentScope(p[1]): # If an identifier is used, we assume that it is present in memory displayValue, offset = ST.getAttribute(p[1], 'scopeLevel'), ST.getAttribute(p[1], 'offset') p[0]['place'] = ST.newTemp((displayValue, offset), variable=p[1], loadFromMemory=True) ST.addAttribute(p[1], ST.getCurrentScope(), p[0]['place']) else: p[0]['place'] = ST.getAttribute(p[1], ST.getCurrentScope()) else: p[0]['type'] = 'REFERENCE_ERROR' debug.printError('Undefined Variable "%s"' %p[1]) raise SyntaxError
def p_expression_relational(p): '''expression : expression OP_GREATER_THEN expression | expression OP_GREATER_THEN_E expression | expression OP_LESS_THEN expression | expression OP_LESS_THEN_E expression | expression OP_EQUALS expression | expression OP_NOT_EQUALS expression''' # Type rules expType = 'UNDEFINED' if p[1]['type'] == p[3]['type'] == 'NUMBER': expType = 'BOOLEAN' else: expType = 'TYPE_ERROR' debug.printError('Operands to relational expressions must be numbers') raise SyntaxError p[0] = {'type': expType} p[0]['place'] = ST.newTemp() # Emit code TAC.emit(p[0]['place'], p[1]['place'], p[3]['place'], p[2])
def p_assignment(p): 'assignment : VAR assignList' # In case the var is not present p[0] = { 'type' : 'VOID' } # Now we add all of these statements for identifier in p[2]: if not ST.existsInCurrentScope(identifier['name']): # Store information about the identifier ST.addIdentifier(identifier['name'], identifier['type']) # This is a new variable, so we link the temporary to our variable displayValue, offset = ST.getAttribute(identifier['name'], 'scopeLevel'), ST.getAttribute(identifier['name'], 'offset') ST.changeMemoryLocationOfTemp(identifier['place'], (displayValue, offset), variable=identifier['name']) ST.addAttribute(identifier['name'], ST.getCurrentScope(), identifier['place']) ST.addAttribute(identifier['name'], 'reference', identifier['reference']) # print the name of the statement debug.printStatement("ASSIGNMENT of %s" %identifier['name']) else: debug.printError('Redefined Variable "%s"' %identifier['name']) raise SyntaxError
def p_expression_relational(p): '''expression : expression OP_GREATER_THEN expression | expression OP_GREATER_THEN_E expression | expression OP_LESS_THEN expression | expression OP_LESS_THEN_E expression | expression OP_EQUALS expression | expression OP_NOT_EQUALS expression''' # Type rules expType = 'UNDEFINED' if p[1]['type'] == p[3]['type'] == 'NUMBER': expType = 'BOOLEAN' else: expType = 'TYPE_ERROR' debug.printError('Operands to relational expressions must be numbers') raise SyntaxError p[0] = { 'type' : expType } p[0]['place'] = ST.newTemp() # Emit code TAC.emit(p[0]['place'], p[1]['place'], p[3]['place'], p[2])
def p_expression_binop(p): '''expression : expression OP_PLUS expression | expression OP_MINUS expression | expression OP_MULTIPLICATION expression | expression OP_DIVISION expression | expression OP_MODULUS expression''' # Type rules expType = 'UNDEFINED' # To store information p[0] = {} p[0]['place'] = ST.newTemp() # To emit codes if p[1]['type'] == 'NUMBER' and p[3]['type'] == 'NUMBER': expType = 'NUMBER' TAC.emit(p[0]['place'], p[1]['place'], p[3]['place'], p[2]) else: expType = 'TYPE_ERROR' debug.printError('Type Mismatch in Arithematic Expression') raise SyntaxError p[0]['type'] = expType
def p_expression_binop(p): '''expression : expression OP_PLUS expression | expression OP_MINUS expression | expression OP_MULTIPLICATION expression | expression OP_DIVISION expression | expression OP_MODULUS expression''' # Type rules expType = 'UNDEFINED' # To store information p[0] = {} p[0]['place'] = ST.newTemp() # To emit codes if p[1]['type'] == 'NUMBER' and p[3]['type'] == 'NUMBER': expType = 'NUMBER' TAC.emit(p[0]['place'], p[1]['place'], p[3]['place'], p[2]) else: expType = 'TYPE_ERROR' debug.printError('Type Mismatch in Arithematic Expression') raise SyntaxError p[0]['type'] = expType
def p_scope(p): 'M_scope : empty' p[0] = {} # Name the function p[0]['reference'] = ST.nameAnon() # Now add the identifier as a function reference if p[-1] != None: # Check for anon function # Check if the function exists or not if ST.existsInCurrentScope(p[-1]): debug.printError("Redefinition of function '%s'" %p[-1]) raise SyntaxError else: # Print to console debug.printStatementBlock("Definition of function '%s'" %p[-1]) # Create a new variable to hold the function ST.addIdentifier(p[-1], 'FUNCTION') # Create a new temporary for the function and store it in the addressList displayValue, offset = ST.getAttribute(p[-1], 'scopeLevel'), ST.getAttribute(p[-1], 'offset') place = ST.newTemp((displayValue, offset), variable=p[-1]) ST.addAttribute(p[-1], ST.getCurrentScope(), place) ST.addAttribute(p[-1], 'reference', p[0]['reference']) # Emit the location of the function reference TAC.emit(place, p[0]['reference'], '', '=REF') else: # Print to console debug.printStatementBlock('Function Definition "%s"' %p[0]['reference']) # Create a function scope ST.addScope(p[0]['reference']) TAC.createFunctionCode(p[0]['reference'])