Skip to content

Commit

Permalink
Merge pull request #14 from cimplec/ptr
Browse files Browse the repository at this point in the history
Added functionality for pointers
  • Loading branch information
frankhart2018 authored Jul 16, 2020
2 parents 0c204bf + 77561a3 commit 60d6800
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 14 deletions.
37 changes: 37 additions & 0 deletions compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 - <identifier>---<expression>---<count_ast>, 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 <identifier>[]
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":
Expand All @@ -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 - <identifier>---<expression>, split that into a list
Expand All @@ -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 - <identifier>---<expression>---<count_ast>, 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 - <identifier>---<expression>, split that into a list
Expand Down
5 changes: 5 additions & 0 deletions lexical_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,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] == "=":
Expand Down
3 changes: 3 additions & 0 deletions op_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
80 changes: 67 additions & 13 deletions simc_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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':
Expand Down Expand Up @@ -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']):
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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


Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion test.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ int main() {
}

return 0;
}
}

0 comments on commit 60d6800

Please sign in to comment.