From 5bb7c5320ff1e8ec83bcfa02baade4ba2d94927d Mon Sep 17 00:00:00 2001 From: Pranshul Date: Wed, 15 Jul 2020 22:16:18 +0530 Subject: [PATCH] Added functionality for pointers --- compiler.py | 37 +++++++++++++++++++++ lexical_analyzer.py | 5 +++ op_code.py | 3 ++ simc_parser.py | 80 +++++++++++++++++++++++++++++++++++++-------- test.c | 21 +++++------- test.simc | 18 +++++----- 6 files changed, 130 insertions(+), 34 deletions(-) diff --git a/compiler.py b/compiler.py index 720f60e..ba82e5c 100644 --- a/compiler.py +++ b/compiler.py @@ -116,6 +116,25 @@ def compile(opcodes, c_filename, table): code += '", ' + str(val[0]) + ");\n" else: code += '", &' + str(val[0]) + ");\n" + #If opcode is of type ptr_assign then generate a declarative statement + elif opcode.type == "ptr_assign": + code = "" + + # val contains - ------, split that into a list + val = opcode.val.split("---") + + # Get the datatye of the variable + _, dtype, _ = table.get_by_id(table.get_by_symbol(val[0])) + + # Helper Dictionaries + get_data_type = {"i": "int", "s": "char*", "f": "float", "d": "double"} + get_placeholder = {"i": "d", "s": "s", "f": "f", "d": "lf"} + + # If it is of string type then change it to char [] + if dtype == "string": + dtype = "char*" + code += "\t" + dtype +" " + "*"*int(val[2]) + str(val[0]) + " = " + str(val[1]) + ";\n" + # If opcode is of type var_no_assign then generate a declaration statement elif opcode.type == "var_no_assign": @@ -128,6 +147,18 @@ def compile(opcodes, c_filename, table): opcode.dtype = str(dtype) if dtype is not None else "not_known" code += "\t" + opcode.dtype + " " + str(opcode.val) + ";\n" + + #If opcode is of type ptr_no_assign then generate declaration statement + elif opcode.type == "ptr_no_assign": + val = opcode.val.split("---") + # Get the datatye of the variable + _, dtype, _ = table.get_by_id(table.get_by_symbol(val[0])) + # Check if dtype could be inferred or not + opcode.dtype = str(dtype) if dtype is not None else "not_known" + if opcode.dtype == 'string': + opcode.dtype = 'char' + code += "\t" + opcode.dtype + " *" + str(opcode.val) + ";\n" + # If opcode is of type assign then generate an assignment statement elif opcode.type == "assign": # val contains - ---, split that into a list @@ -147,6 +178,12 @@ def compile(opcodes, c_filename, table): code += "\t" + 'printf("' + str(val[1]) + '");\n' code += "\t" + 'scanf("%' + placeholder + '", &' + str(val[0]) + ");\n" + # If opcode is of type ptr_only_assign then generate an assignment statement + elif opcode.type == "ptr_only_assign": + # val contains - ------, split that into a list + val = opcode.val.split("---") + code += "\t" + int(val[2])*'*'+val[0] + " = " + val[1] + ";\n" + # If opcode is of type unary then generate an uanry statement elif opcode.type == "unary": # val contains - ---, split that into a list diff --git a/lexical_analyzer.py b/lexical_analyzer.py index 28e0075..9d1b168 100644 --- a/lexical_analyzer.py +++ b/lexical_analyzer.py @@ -307,6 +307,11 @@ def lexical_analyze(filename, table): tokens.append(Token("multiply", "", line_num)) i += 1 + #Identifying 'address of' token + elif source_code[i] == '&': + tokens.append(Token("address_of", "", line_num)) + i += 1 + # Identifying divide_equal or divide token elif source_code[i] == "/": if source_code[i + 1] == "=": diff --git a/op_code.py b/op_code.py index 6dee016..8ced567 100644 --- a/op_code.py +++ b/op_code.py @@ -59,5 +59,8 @@ def opcode2dig(self, str_type): "while": 6, "if": 7, "exit": 8, + "ptr_no_assign": 9, + "ptr_assign" :10, + "ptr_only_assign" :11, } return dic.get(str_type, 0) diff --git a/simc_parser.py b/simc_parser.py index f5ed3b6..0fc98bf 100644 --- a/simc_parser.py +++ b/simc_parser.py @@ -161,7 +161,8 @@ def expression( "exit", "right_paren", "newline", - "call_end" + "call_end", + "address_of" ]: # Check for function call if tokens[i].type == 'id' and tokens[i+1].type == 'left_paren': @@ -271,7 +272,8 @@ def expression( "or": " || ", "comma": ",", "left_paren": "(", - "right_paren": ")" + "right_paren": ")", + "address_of": "&" } if(expect_paren and tokens[i].type == 'right_paren' and tokens[i+1].type in ['newline', 'left_brace']): @@ -375,6 +377,23 @@ def print_statement(tokens, i, table, func_ret_type): return OpCode("print", op_value), i + 1, func_ret_type +def check_ptr(tokens,i): + #Check if a pointer is being declared + is_ptr = False + #Count the depth of pointer + count_ast = 0 + if(tokens[i].type == "multiply"): + j = 0 + while(tokens[i+j].type == "multiply"): + j += 1 + i += j + count_ast = j + is_ptr = True + return is_ptr, count_ast, i + else: + return False, 0, i + + def var_statement(tokens, i, table, func_ret_type): """ Parse variable declaration [/initialization] statement @@ -401,9 +420,11 @@ def var_statement(tokens, i, table, func_ret_type): operator -> + | - | * | / """ + is_ptr, count_ast, i = check_ptr(tokens,i) # Check if identifier is present after var check_if(tokens[i].type, "id", "Expected id after var keyword", tokens[i].line_num) + # Check if variable is also initialized if i + 1 < len(tokens) and tokens[i + 1].type == "assignment": # Store the index of identifier @@ -427,16 +448,27 @@ def var_statement(tokens, i, table, func_ret_type): # Modify datatype of the identifier table.symbol_table[tokens[id_idx].val][1] = prec_to_type[op_type] - # Return the opcode and i (the token after var statement) - return ( - OpCode( - "var_assign", - table.symbol_table[tokens[id_idx].val][0] + "---" + op_value, - prec_to_type[op_type], - ), - i, - func_ret_type - ) + if(is_ptr): + return ( + OpCode( + "ptr_assign", + table.symbol_table[tokens[id_idx].val][0] + "---" + op_value+ "---" +str(count_ast), + prec_to_type[op_type], + ), + i, + func_ret_type + ) + else: + # Return the opcode and i (the token after var statement) + return ( + OpCode( + "var_assign", + table.symbol_table[tokens[id_idx].val][0] + "---" + op_value, + prec_to_type[op_type], + ), + i, + func_ret_type + ) else: # Get the value from symbol table by id value, type, _ = table.get_by_id(tokens[i].val) @@ -458,6 +490,9 @@ def var_statement(tokens, i, table, func_ret_type): table.symbol_table[tokens[i].val][1] = "declared" # Return the opcode and i+1 (the token after var statement) + if is_ptr: + return OpCode("ptr_no_assign", value), i + 1, func_ret_type + return OpCode("var_no_assign", value), i + 1, func_ret_type @@ -486,6 +521,17 @@ def assign_statement(tokens, i, table, func_ret_type): operator -> + | - | * | / """ + #Check if the identifier is a pointer + is_ptr = False + #count depth of pointer + count_ast = 0 + if(tokens[i-2].type == "multiply"): + j = -2 + while(tokens[j+i].type == "multiply"): + j -= 1 + count_ast = -1*j-2 + is_ptr = True + # Check if variable is declared or not value, type, _ = table.get_by_id(tokens[i - 1].val) @@ -527,7 +573,15 @@ def assign_statement(tokens, i, table, func_ret_type): # Modify datatype of the identifier table.symbol_table[tokens[id_idx].val][1] = prec_to_type[op_type] - + #Check if a pointer is being assigned + if(is_ptr): + return ( + OpCode( + "ptr_only_assign", table.symbol_table[tokens[id_idx].val][0] + "---" + op_value +"---"+str(count_ast), "" + ), + i, + func_ret_type + ) # Return the opcode and i (the token after assign statement) return ( OpCode( diff --git a/test.c b/test.c index e2cfe88..2952a3a 100644 --- a/test.c +++ b/test.c @@ -1,13 +1,10 @@ #include - -int sum(int a, int b) { - - return a + b; -} - -int main() { - int hello = sum(1, 2); - printf("The sum = %d", hello); - exit(0); - return 0; -} \ No newline at end of file + int a; + a = 10; + int *b; + b = &a; + float f = 1.2; + float **e = &f; + printf("%d", &b); + ******b = * a; + **b = * * a; diff --git a/test.simc b/test.simc index bfe179d..9eafb8f 100644 --- a/test.simc +++ b/test.simc @@ -1,9 +1,9 @@ -fun sum(a, b) { - return a + b -} - -MAIN - var hello = sum(1, 2) - print("The sum = {hello}") - exit (0) -END_MAIN +var a +a = 10 +var *b +b = &a +var f = 1.2 +var **e = &f +print(&b) +******b = *a +**b = **a