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_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_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_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_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_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_StandardType(p): '''StandardType : PREDEF_TYPE ''' parsed.append(p.slice) #print("PREDEF_TYPE", p[1]) p[0] = TreeNode('StandardTypes', p[1], 'NONE') 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 ''' parsed.append(p.slice) 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 == 'Index': p[0] = TreeNode('IDENTIFIER', p[1].data, 'INT', 1, p[2].data) elif p[2].name == 'Arguments': p[0] = TreeNode('IDENTIFIER', gen('temp'), 'INT', 1) p[0].TAC.append_TAC(p[1].TAC) p[0].TAC.append_TAC(p[2].TAC) # p[1].print_node() func = check_variable(p[1]).split("_") scope, funcName = "_".join(func[:2]), "_".join(func[2:]) temp = 0 for f in symbol_table.symbol_table[scope]['functions']: if f.name == funcName: temp = len(f.parameters) # p[2].print_node() for child in p[2].children: p[0].TAC.add_line(['putparam', check_variable(child), '', '']) if temp != p[2].data: print_error('Function ' + funcName + ' requires ' + str(temp) + ' parameters but ' + str(p[2].data) + ' supplied') p[0].TAC.add_line( ['call', check_variable(p[1]), str(p[2].data), '']) p[0].TAC.add_line(['return_value', check_variable(p[0]), '', '']) p[0].name = 'PrimaryExpr' 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_Arguments(p): '''Arguments : LROUND RROUND | LROUND ExpressionList RROUND | LROUND Expression RROUND | LROUND Type RROUND | LROUND Type COMMA ExpressionList RROUND | LROUND Type COMMA Expression RROUND ''' # print p.slice parsed.append(p.slice) if len(p) == 3: p[0] = TreeNode('Arguments', 0, 'None') if len(p) == 4: if p[2].name == 'Expression': p[0] = TreeNode('Arguments', 1, 'None', 0, [p[2]], p[2].TAC) if p[2].name == 'ExpressionList': p[0] = p[2] p[0].name = 'Arguments' p[0].data = len(p[2].children) 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_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_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_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_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_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_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_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_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_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_Arguments(p): '''Arguments : LROUND RROUND | LROUND ExpressionList DDD RROUND | LROUND Expression DDD RROUND | LROUND ExpressionList RROUND | LROUND Expression RROUND | LROUND Type DDD RROUND | LROUND Type RROUND | LROUND Type COMMA ExpressionList DDD RROUND | LROUND Type COMMA ExpressionList RROUND | LROUND Type COMMA Expression DDD RROUND | LROUND Type COMMA Expression RROUND | LROUND IDENTIFIER DDD RROUND | LROUND IDENTIFIER RROUND %prec LROUND | LROUND IDENTIFIER COMMA ExpressionList DDD RROUND | LROUND IDENTIFIER COMMA ExpressionList RROUND | LROUND IDENTIFIER COMMA Expression DDD RROUND | LROUND IDENTIFIER COMMA Expression RROUND | LROUND IDENTIFIER DOT IDENTIFIER DDD RROUND | LROUND IDENTIFIER DOT IDENTIFIER RROUND | LROUND IDENTIFIER DOT IDENTIFIER COMMA ExpressionList DDD RROUND | LROUND IDENTIFIER DOT IDENTIFIER COMMA ExpressionList RROUND | LROUND IDENTIFIER DOT IDENTIFIER COMMA Expression DDD RROUND | LROUND IDENTIFIER DOT IDENTIFIER COMMA Expression RROUND | LROUND ExpressionList DDD COMMA RROUND | LROUND Expression DDD COMMA RROUND | LROUND ExpressionList COMMA RROUND | LROUND Expression COMMA RROUND | LROUND Type DDD COMMA RROUND | LROUND Type COMMA RROUND | LROUND Type COMMA ExpressionList DDD COMMA RROUND | LROUND Type COMMA ExpressionList COMMA RROUND | LROUND Type COMMA Expression DDD COMMA RROUND | LROUND Type COMMA Expression COMMA RROUND | LROUND IDENTIFIER DDD COMMA RROUND | LROUND IDENTIFIER COMMA RROUND | LROUND IDENTIFIER COMMA ExpressionList DDD COMMA RROUND | LROUND IDENTIFIER COMMA ExpressionList COMMA RROUND | LROUND IDENTIFIER COMMA Expression DDD COMMA RROUND | LROUND IDENTIFIER COMMA Expression COMMA RROUND | LROUND IDENTIFIER DOT IDENTIFIER DDD COMMA RROUND | LROUND IDENTIFIER DOT IDENTIFIER COMMA RROUND | LROUND IDENTIFIER DOT IDENTIFIER COMMA ExpressionList DDD COMMA RROUND | LROUND IDENTIFIER DOT IDENTIFIER COMMA ExpressionList COMMA RROUND | LROUND IDENTIFIER DOT IDENTIFIER COMMA Expression DDD COMMA RROUND | LROUND IDENTIFIER DOT IDENTIFIER COMMA Expression COMMA RROUND ''' if len(p) == 3: p[0] = TreeNode('Arguments', 0, 'INT') 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
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_IfStmt(p): '''IfStmt : IF Expression Block | IF Expression Block ELSE elseTail ''' parsed.append(p.slice) if len(p) == 4: l1 = gen('label') p[0] = TreeNode('IfStmt', 0, 'INT') p[0].TAC.append_TAC(p[2].TAC) p[0].TAC.add_line(['ifgotoeq', check_variable(p[2]), '0', l1]) p[0].TAC.append_TAC(p[3].TAC) p[0].TAC.add_line(['label', l1, '', '']) if len(p) == 6: l1 = gen('label') l2 = gen('label') p[0] = TreeNode('IfStmt', 0, 'INT') p[0].TAC.append_TAC(p[2].TAC) p[0].TAC.add_line(['ifgotoeq', check_variable(p[2]), '0', l1]) p[0].TAC.append_TAC(p[3].TAC) p[0].TAC.add_line(['goto', l2, '', '']) p[0].TAC.add_line(['label', l1, '', '']) p[0].TAC.append_TAC(p[5].TAC) p[0].TAC.add_line(['label', l2, '', '']) return