def check_variable(TreeNode): # return 2 values. first is the name for the variable, second is 0 if variable not found # TreeNode.print_node() # symbol_table.print_symbol_table() if TreeNode.isLvalue == 1: if TreeNode.data not in generated['temp']: name = symbol_table.search_identifier(TreeNode.data) if name == False: name = symbol_table.search_function(TreeNode.data) if name == False: print_error("Variable " + TreeNode.data + " is undefined") return TreeNode.data else: return name else: newNode = SymbolTableNode(name, TreeNode.input_type) symbol_table.add_var(newNode) if TreeNode.children == []: return name else: return name + '[' + TreeNode.children + ']' else: newNode = SymbolTableNode(TreeNode.data, TreeNode.input_type) symbol_table.add_var(newNode) return TreeNode.data else: if TreeNode.input_type != 'STRING': return TreeNode.data else: TreeNode.print_node() return TreeNode.data
def p_ExprSwitchStmt(p): '''ExprSwitchStmt : SWITCH SimpleStmt SEMICOLON LCURLY ScopeStart ExprCaseClauseList ScopeEnd RCURLY | SWITCH SimpleStmt SEMICOLON Expression LCURLY ScopeStart ExprCaseClauseList ScopeEnd RCURLY | SWITCH LCURLY ScopeStart ExprCaseClauseList ScopeEnd RCURLY | SWITCH Expression LCURLY ScopeStart ExprCaseClauseList ScopeEnd RCURLY ''' parsed.append(p.slice) if len(p) == 8: l1 = gen('label') l2 = gen('label') p[0] = TreeNode('ExprSwitchStmt', 0, 'INT') p[0].TAC.append_TAC(p[2].TAC) t1 = TreeNode('IDENTIFIER', gen('temp'), 'INT', 1) p[0].TAC.add_line(['=', check_variable(t1), check_variable(p[2]), '']) p[0].TAC.append_TAC(p[5].data) for i in range(len(p[5].children)): p[0].TAC.add_line([ 'ifgotoeq', check_variable(t1), p[5].children[i][0], p[5].children[i][1] ]) p[0].TAC.add_line(['goto', l2, '', '']) for i in range(p[5].TAC.length()): if i in p[5].TAC.leaders[1:]: p[0].TAC.add_line(['goto', l2, '', '']) p[0].TAC.add_line(p[5].TAC.code[i]) p[0].TAC.add_line(['label', l2, '', '']) return
def p_IdentifierList(p): '''IdentifierList : IDENTIFIER COMMA IdentifierBotList ''' parsed.append(p.slice) node = TreeNode('IDENTIFIER', p[1], 'INT', 1) p[0] = TreeNode('IdentifierList', 0, 'None', 0, [node] + p[3].children, p[3].TAC) return
def p_StatementList(p): '''StatementList : Statement SEMICOLON StatementList | empty ''' if len(p) == 4: p[0] = TreeNode('StatementList', 0, 'INT', 0, [p[1].data] + p[3].children, p[1].TAC) p[0].TAC.append_TAC(p[3].TAC) else: p[0] = TreeNode('StatementList', 0, 'INT')
def p_Result(p): '''Result : Parameters | Type ''' parsed.append(p.slice) if p[1].name == 'Type': p[0] = TreeNode('Result', 1, 'None', 0, [p[1]]) else: p[0] = p[1] p[0].name = 'Result' return
def p_IdentifierBotList(p): '''IdentifierBotList : IDENTIFIER COMMA IdentifierBotList | IDENTIFIER ''' if len(p) == 2: p[0] = TreeNode('IdentifierBotList', p[1], 'INT') return elif len(p) == 4: p[0] = TreeNode('IdentifierBotList', 0, 'INT', 0, [p[1]] + p[3].children) return
def p_Parameters(p): '''Parameters : LROUND RROUND | LROUND ParameterList RROUND ''' parsed.append(p.slice) if len(p) == 3: p[0] = TreeNode('Parameters', 0, 'None') else: p[0] = p[2] p[0].name = 'Parameters' return
def p_ExprSwitchCase(p): '''ExprSwitchCase : CASE ExpressionList | DEFAULT | CASE Expression ''' p[0] = TreeNode('ExprSwitchCase', 0, 'INT') if len(p) == 3: p[0].data = p[2].data p[0].TAC = p[2].TAC parsed.append(p.slice)
def p_PrintIntStmt(p): '''PrintIntStmt : PRINTLN LROUND IDENTIFIER RROUND | PRINTLN LROUND int_lit RROUND ''' if hasattr(p[3], 'name') and p[3].name == 'int_lit': p[0] = p[3] # p[0].isLvalue = 0 else: p[0] = TreeNode('IDENTIFIER', p[3], 'INT', 1, []) p[0].TAC.add_line(['print_int', check_variable(p[0]), '', '']) p[0].name = 'PrintIntStmt' return
def p_ExpressionBotList(p): '''ExpressionBotList : Expression COMMA ExpressionBotList | Expression ''' parsed.append(p.slice) if len(p) == 2: p[0] = TreeNode('ExpressionBotList', 0, 'INT', 0, [p[1]], p[1].TAC) elif len(p) == 4: p[0] = TreeNode('ExpressionBotList', 0, 'INT', 0, [p[1]] + p[3].children, p[1].TAC) p[0].TAC.append_TAC(p[3].TAC) return
def p_TopLevelDeclList(p): '''TopLevelDeclList : TopLevelDecl SEMICOLON TopLevelDeclList | empty ''' if len(p) == 4: if p[3] != None: p[0] = TreeNode('TopLevelDeclList', 0, 'INT', 0, [p[1]] + p[3].children, p[1].TAC) p[0].TAC.append_TAC(p[3].TAC) else: p[0] = TreeNode('TopLevelDeclList', 0, 'INT', 0, [p[1]], p[1].TAC) return
def p_ExprCaseClause(p): '''ExprCaseClause : ExprSwitchCase COLON StatementList ''' l1 = labelGen() p[0] = TreeNode('ExprCaseClause', 0, 'INT') # p[0].TAC.append_TAC(p[1].TAC) p[0].TAC.add_line([l1]) # p[0].TAC.add_line(['ifgotoneq', p[1].children, p[1].children, l1]) p[0].TAC.append_TAC(p[3].TAC) p[0].children = [[p[1].data, l1]] p[0].data = p[1].TAC return
def p_ExpressionBotList(p): '''ExpressionBotList : Expression COMMA ExpressionBotList | Expression ''' if len(p) == 2: p[0] = TreeNode('ExpressionBotList', 0, 'INT', [p[1].isLvalue], [p[1]], p[1].TAC) return elif len(p) == 4: p[0] = TreeNode('ExpressionBotList', 0, 'INT', [p[1].isLvalue] + p[3].isLvalue, [p[1]] + p[3].children, p[1].TAC) p[0].TAC.append_TAC(p[3].TAC) return
def p_ExprCaseClause(p): '''ExprCaseClause : ExprSwitchCase COLON StatementList ''' parsed.append(p.slice) l1 = gen('label') p[0] = TreeNode('ExprCaseClause', 0, 'INT') # p[0].TAC.append_TAC(p[1].TAC) p[0].TAC.add_line(['label', l1, '', '']) # p[0].TAC.add_line(['ifgotoneq', p[1].children, p[1].children, l1]) p[0].TAC.append_TAC(p[3].TAC) p[0].children = [[p[1].data, l1]] p[0].data = p[1].TAC return
def p_VarSpec(p): '''VarSpec : IDENTIFIER Type | IDENTIFIER EQ Expression | IDENTIFIER Type EQ Expression | IdentifierList Type | IdentifierList EQ ExpressionList | IdentifierList Type EQ ExpressionList ''' # Insert into symbol table p[0] = TreeNode('VarSpec', 0, 'NONE') if hasattr(p[1], 'name') and p[1].name == 'IdentifierList': zero_val = TreeNode('decimal_lit', 0, 'INT') # l1 = len(p[1].children) # if len(p) == 3: # expr_list = TreeNode('Expr_List', 0, 'NONE', 0, [zero_val] * l1) # elif len(p) == 4: # expr_list = p[3] # elif len(p) == 5: # expr_list = p[4] # l2 = len(expr_list.children) # p[0].TAC.append_TAC(expr_list.TAC) # p[0].TAC.append_TAC(p[1].TAC) # if l1 == l2: # for i in range(l1): # p[0].TAC.add_line(['=', p[1].children[i], expr_list.children[i].data, '']) # else: # print_error("Variable Declaration mismatch: " + str(l1) + " identifier(s) but " + str(l2) + " value(s)") else: p[1] = TreeNode('IDENTIFIER', p[1], 'INT', 1) if p[2].input_type != 'NONE': # array case # p[2].print_node() if symbol_table.add_identifier(p[1], size=p[2].data) == False: print_error("Unable to add to SymbolTable") return name = symbol_table.search_identifier(p[1].data) newNode = SymbolTableNode(name, p[1].input_type, size=p[2].data) symbol_table.add_var(newNode) p[0] = TreeNode('VarSpec', p[1].data, 'INT') # expr = TreeNode('Expr', 0, 'NONE') # if len(p) == 4: # expr = p[3] # p[0].TAC.append_TAC(p[3].TAC) # p[0].TAC.add_line(['=', check_variable(p[1]), check_variable(expr), '']) # elif len(p) == 5: # expr = p[4] # p[0].TAC.append_TAC(p[4].TAC) # p[0].TAC.add_line(['=', check_variable(p[1]), check_variable(expr), '']) return
def p_Expression(p): '''Expression : UnaryExpr | Expression OR_OR Expression | Expression AMP_AMP Expression | Expression EQ_EQ Expression | Expression NOT_EQ Expression | Expression LT Expression | Expression LT_EQ Expression | Expression GT Expression | Expression GT_EQ Expression | Expression PLUS Expression | Expression MINUS Expression | Expression OR Expression | Expression CARET Expression | Expression STAR Expression | Expression DIVIDE Expression | Expression MODULO Expression | Expression LS Expression | Expression RS Expression | Expression AMP Expression | Expression AND_OR Expression ''' global current_scope if len(p) == 2: p[0] = p[1] elif len(p) == 4: expression = p[1].data + p[2] + p[3].data expr_node = SymbolTable.search_expr(expression) if not expr_node: temp = tempGen() node = symboltable_node() node.name = temp node.value = p[1].data + p[2] + p[3].data node.expr = p[1].data + p[2] + p[3].data node.type = p[1].input_type node.scope = current_scope SymbolTable.add_node(node) #print(f"Evaluating expression {node.value}") node.value = evalExpr(p[1], p[2], p[3]) #SymbolTable.print_symbol_table() #print(node.value, node.name) p[0] = TreeNode('IDENTIFIER', temp, 'INT', 1, [], p[1].TAC) node.exprnode = p[0] p[0].TAC.append_TAC(p[3].TAC) p[0].TAC.add_line([p[2], p[0].data, p[1].data, p[3].data]) else: p[0] = expr_node.exprnode p[0].name = 'Expression' return
def p_ReturnStmt(p): '''ReturnStmt : RETURN | RETURN Expression | RETURN ExpressionList ''' parsed.append(p.slice) if len(p) == 2: p[0] = TreeNode('ReturnStmt', 0, 'None') p[0].TAC.add_line(['return', '', '', '']) if len(p) == 3: if p[2].name == 'Expression': p[0] = p[2] p[0].name = 'ReturnStmt' p[0].TAC.add_line(['return', check_variable(p[2]), '', '']) return
def p_StandardType(p): '''StandardType : PREDEF_TYPE ''' parsed.append(p.slice) #print("PREDEF_TYPE", p[1]) p[0] = TreeNode('StandardTypes', p[1], 'NONE') return
def p_ExprSwitchStmt(p): '''ExprSwitchStmt : SWITCH SimpleStmt SEMICOLON LCURLY ExprCaseClauseList RCURLY | SWITCH SimpleStmt SEMICOLON Expression LCURLY ExprCaseClauseList RCURLY | SWITCH LCURLY ExprCaseClauseList RCURLY | SWITCH Expression LCURLY ExprCaseClauseList RCURLY ''' global current_scope if len(p) == 6: l1 = labelGen() l2 = labelGen() p[0] = TreeNode('ExprSwitchStmt', 0, 'INT') p[0].TAC.append_TAC(p[2].TAC) t1 = tempGen() node = symboltable_node() node.name = t1 node.scope = current_scope node.value = p[2].data node.type = insertType(p[2].data) SymbolTable.add_node(node) p[0].TAC.add_line(['=', t1, p[2].data, '']) p[0].TAC.append_TAC(p[4].data) for i in range(len(p[4].children)): p[0].TAC.add_line( ['ifgotoeq', t1, p[4].children[i][0], p[4].children[i][1]]) for i in range(p[4].TAC.length()): if i in p[4].TAC.leaders[1:]: p[0].TAC.add_line(['goto', l2, '', '']) p[0].TAC.add_line(p[4].TAC.code[i]) p[0].TAC.add_line([l2]) return
def p_ScopeStart(p): '''ScopeStart : empty ''' parsed.append(p.slice) symbol_table.add_scope(gen('scope')) p[0] = TreeNode('ScopeStart', symbol_table.current_scope, 'None') return
def p_UnaryExpr(p): '''UnaryExpr : PrimaryExpr | unary_op UnaryExpr ''' parsed.append(p.slice) if len(p) == 2: p[0] = p[1] elif len(p) == 3: p[0] = TreeNode('IDENTIFIER', gen('temp'), 'INT', 1) p[0].TAC.add_line([ check_variable(p[1]), check_variable(p[0]), check_variable(p[2]), '' ]) p[0].name = 'UnaryExpr' return
def p_ExpressionList(p): '''ExpressionList : Expression COMMA ExpressionBotList ''' p[0] = TreeNode('ExpressionList', 0, 'INT', [p[1].isLvalue] + p[3].isLvalue, [p[1]] + p[3].children, p[1].TAC) p[0].TAC.append_TAC(p[3].TAC) return
def p_PrimaryExpr(p): '''PrimaryExpr : Operand | IDENTIFIER | PrimaryExpr Selector | PrimaryExpr Index | PrimaryExpr Arguments ''' if len(p) == 2: if p.slice[1].type == 'IDENTIFIER': p[0] = TreeNode('IDENTIFIER', p[1], 'INT', 1, []) elif p[1].name == 'Operand': p[0] = p[1] elif len(p) == 3: if p[2].name == 'Arguments': p[0] = p[1] p[0].TAC.add_line(['call', p[1].data, '', '']) p[0].name = 'PrimaryExpr' return
def p_UnaryExpr(p): '''UnaryExpr : PrimaryExpr | unary_op UnaryExpr ''' global current_scope if len(p) == 2: p[0] = p[1] elif len(p) == 3: temp = tempGen() node = symboltable_node() node.name = temp node.value = p[2].data node.scope = current_scope SymbolTable.add_node(node) p[0] = TreeNode('IDENTIFIER', temp, 'INT', 1) p[0].TAC.add_line([p[1].data, p[0].data, p[2].data]) p[0].name = 'UnaryExpr' return
def p_ExprCaseClauseList(p): '''ExprCaseClauseList : empty | ExprCaseClauseList ExprCaseClause ''' TAC1 = ThreeAddressCode() TAC2 = ThreeAddressCode() if len(p) == 3: TAC1 = p[1].data TAC2 = p[2].data p[0] = TreeNode('ExprCaseClauseList', TAC1, 'INT', 0, p[1].children + p[2].children, p[1].TAC) p[0].TAC.add_leader(p[0].TAC.length()) p[0].TAC.append_TAC(p[2].TAC) p[0].data.append_TAC(TAC2) else: p[0] = TreeNode('ExprCaseClauseList', TAC1, 'INT') return
def p_unary_op(p): '''unary_op : PLUS | MINUS | NOT | CARET | STAR | AMP | LT_MINUS ''' p[0] = TreeNode('unary_op', p[1], 'OPERATOR') return
def p_ParameterDecl(p): '''ParameterDecl : IdentifierList Type | IDENTIFIER Type | Type ''' parsed.append(p.slice) p[0] = TreeNode('ParameterDecl', 0, 'None') if len(p) == 3: if hasattr(p[1], 'name') and p[1].name == 'IdentifierList': for node in p[1].children: p[0].data += 1 node.input_type = p[2].data p[0].children += [node] else: node = TreeNode('IDENTIFIER', p[1], p[2].data, 1) p[0].data += 1 p[0].children += [node] else: p[0].data += 1 p[0].children += [p[1]] return
def p_FunctionDecl(p): '''FunctionDecl : FUNC FunctionName Type Signature | FUNC FunctionName Signature | FUNC FunctionName Type Signature FunctionBody | FUNC FunctionName Signature FunctionBody ''' p[0] = TreeNode('FunctionDecl', 0, 'INT') p[0].TAC.add_line(['func', p[2].data, '', '']) if len(p) == 5: p[0].TAC.append_TAC(p[4].TAC) # p[0].print_node() return
def p_ParameterList(p): '''ParameterList : ParameterDecl | ParameterList COMMA ParameterDecl ''' parsed.append(p.slice) if len(p) == 2: p[0] = p[1] p[0].name = 'ParameterList' elif len(p) == 4: p[0] = TreeNode('ParameterList', p[1].data + p[3].data, 'None', 0, p[1].children + p[3].children, p[1].TAC) p[0].TAC.append_TAC(p[3].TAC) return
def p_VarSpec(p): '''VarSpec : IDENTIFIER Type | IDENTIFIER EQ Expression | IDENTIFIER Type EQ Expression | IdentifierList Type | IdentifierList EQ ExpressionList | IdentifierList Type EQ ExpressionList ''' # Insert into symbol table p[0] = TreeNode('VarSpec', 0, 'NONE') if hasattr(p[1], 'name') and p[1].name == 'IdentifierList': zero_val = TreeNode('decimal_lit', 0, 'INT') else: p[1] = TreeNode('IDENTIFIER', p[1], 'INT', 1) if p[2].input_type != 'NONE': node = symboltable_node() node.name = p[1].data node.value = None node.scope = current_scope node.type = p[1].input_type SymbolTable.add_node(node) p[0] = TreeNode('VarSpec', p[1].data, 'INT') return