diff --git a/include/ast.h b/include/ast.h index 3b90a36..0be9ae3 100644 --- a/include/ast.h +++ b/include/ast.h @@ -14,6 +14,8 @@ #define AST_NODE_DECLARATION 6 #define AST_NODE_ARRAY_DECLARATION 2000 #define AST_NODE_ASSIGNMENT 7 +#define AST_NODE_MUL_ASSIGNMENT 6007 +#define AST_NODE_DIV_ASSIGNMENT 6008 #define AST_NODE_ARRAY_ASSIGNMENT 2001 #define AST_NODE_ARRAY_ACCESS 2002 #define AST_NODE_ARITHMETIC_EXP 8 @@ -59,6 +61,8 @@ #define AST_OPR_LGL_OR 43 // or #define AST_OPR_ASSIGNMENT 44 // := +#define AST_OPR_MUL_ASSIGNMENT 6009 // *= +#define AST_OPR_DIV_ASSIGNMENT 6010 // /= #define AST_CONST_INT 45 // INT CONSTANT #define AST_CONST_BOOL 46 // BOOL CONSTANT @@ -100,6 +104,8 @@ struct ast_node_compound_statement; struct ast_node_declaration; struct ast_node_array_declaration; struct ast_node_assignment; +struct ast_node_mul_assignment; +struct ast_node_div_assignment; struct ast_node_array_assignment; struct ast_node_array_access; struct ast_node_expression; @@ -125,6 +131,8 @@ typedef struct ast_node_compound_statement ast_node_compound_statement; typedef struct ast_node_declaration ast_node_declaration; typedef struct ast_node_array_declaration ast_node_array_declaration; typedef struct ast_node_assignment ast_node_assignment; +typedef struct ast_node_mul_assignment ast_node_mul_assignment; +typedef struct ast_node_div_assignment ast_node_div_assignment; typedef struct ast_node_array_assignment ast_node_array_assignment; typedef struct ast_node_array_access ast_node_array_access; typedef struct ast_node_expression ast_node_expression; @@ -160,6 +168,8 @@ struct ast_node ast_node_declaration *declaration; ast_node_array_declaration *array_declaration; ast_node_assignment *assignment; + ast_node_mul_assignment *mul_assignment; + ast_node_div_assignment *div_assignment; ast_node_array_assignment *array_assignment; ast_node_conditional_if *if_else; ast_node_loop_for *loop_for; @@ -205,6 +215,22 @@ struct ast_node_array_declaration ast_node_expression *expression; }; + struct ast_node_mul_assignment +{ + int node_type; + + sym_ptr symbol_entry; + ast_node_expression *expression; +}; + + struct ast_node_div_assignment +{ + int node_type; + + sym_ptr symbol_entry; + ast_node_expression *expression; +}; + struct ast_node_array_assignment { int node_type; @@ -363,6 +389,8 @@ ast_node_compound_statement *add_compound_statement_node(ast_node_compound_state ast_node_declaration *create_declaration_node(sym_ptr symbol, ast_node_expression *exp); ast_node_array_declaration *create_array_declaration_node(sym_ptr symbol, ast_node_expression *size, char *initial_string); ast_node_assignment *create_assignment_node(sym_ptr symbol, ast_node_expression *exp); +ast_node_mul_assignment *create_mul_assignment_node(sym_ptr symbol, ast_node_expression *exp); +ast_node_div_assignment *create_div_assignment_node(sym_ptr symbol, ast_node_expression *exp); ast_node_array_assignment *create_array_assignment_node(sym_ptr symbol, ast_node_expression *index, ast_node_expression *exp); ast_node_array_access *create_array_access_node(sym_ptr symbol, ast_node_expression *index); ast_node_expression *create_expression_node(int node_type, int opt, int value, ast_node *left, ast_node *right); diff --git a/include/code_printer.h b/include/code_printer.h index 189f5e6..cd9dee8 100644 --- a/include/code_printer.h +++ b/include/code_printer.h @@ -32,6 +32,8 @@ #define _OPR_LGL_OR " | " #define _OPR_ASSIGNMENT " = " +#define _OPR_MUL_ASSIGNMENT " *= " +#define _OPR_DIV_ASSIGNMENT " /= " #define _DT_INT_ "int" #define _DT_VOID_ "void" @@ -54,6 +56,8 @@ void ast_compound_statement_printer(ast_node_compound_statement *cmpd_stmt, FILE void ast_declaration_printer(ast_node_declaration *decl, FILE* handle); void ast_array_declaration_printer(ast_node_array_declaration *decl, FILE* handle); void ast_assignment_printer(ast_node_assignment *assg, FILE* handle); +void ast_mul_assignment_printer(ast_node_mul_assignment *mul_assg, FILE* handle); +void ast_div_assignment_printer(ast_node_div_assignment *div_assg, FILE* handle); void ast_array_assignment_printer(ast_node_array_assignment *assign, FILE *handle); void ast_array_access_printer(ast_node_array_access *access, FILE* handle); void ast_expression_printer(ast_node_expression *node, FILE* handle); diff --git a/src/ast.c b/src/ast.c index 3fb7bb8..fc20982 100644 --- a/src/ast.c +++ b/src/ast.c @@ -40,6 +40,14 @@ ast_node_statements *create_statement_node(int node_type, void *child) stmt->child_nodes.assignment = child; break; + case AST_NODE_MUL_ASSIGNMENT: + stmt->child_nodes.mul_assignment = child; + break; + + case AST_NODE_DIV_ASSIGNMENT: + stmt->child_nodes.div_assignment = child; + break; + case AST_NODE_ARRAY_ASSIGNMENT: stmt->child_nodes.array_assignment = child; break; @@ -144,6 +152,28 @@ ast_node_assignment *create_assignment_node(sym_ptr symbol, ast_node_expression return assgn; } +ast_node_mul_assignment *create_mul_assignment_node(sym_ptr symbol, ast_node_expression *exp) +{ + ast_node_mul_assignment *mul_assgn = (ast_node_mul_assignment*)malloc(sizeof(ast_node_mul_assignment)); + + mul_assgn->node_type = AST_NODE_MUL_ASSIGNMENT; + mul_assgn->expression = exp; + mul_assgn->symbol_entry = symbol; + + return mul_assgn; +} + +ast_node_div_assignment *create_div_assignment_node(sym_ptr symbol, ast_node_expression *exp) +{ + ast_node_div_assignment *div_assgn = (ast_node_div_assignment*)malloc(sizeof(ast_node_div_assignment)); + + div_assgn->node_type = AST_NODE_DIV_ASSIGNMENT; + div_assgn->expression = exp; + div_assgn->symbol_entry = symbol; + + return div_assgn; +} + ast_node_array_assignment *create_array_assignment_node(sym_ptr symbol, ast_node_expression *index, ast_node_expression *exp) { ast_node_array_assignment *assign = (ast_node_array_assignment*)malloc(sizeof(ast_node_array_assignment)); @@ -601,6 +631,14 @@ void ast_node_type(int node_type) case AST_NODE_ASSIGNMENT: printf("ast assignment"); break; + + case AST_NODE_DIV_ASSIGNMENT: + printf("ast division assignment"); + break; + + case AST_NODE_MUL_ASSIGNMENT: + printf("ast multiplication assignment"); + break; case AST_NODE_ARRAY_ASSIGNMENT: printf("ast array assignment"); diff --git a/src/code_printer.c b/src/code_printer.c index 7ff71b0..37e182b 100644 --- a/src/code_printer.c +++ b/src/code_printer.c @@ -29,6 +29,14 @@ void ast_compound_statement_printer(ast_node_compound_statement *cmpd_stmt, FILE ast_assignment_printer(((ast_node_statements*)temp)->child_nodes.assignment, handle); break; + case AST_NODE_MUL_ASSIGNMENT: + ast_mul_assignment_printer(((ast_node_statements*)temp)->child_nodes.mul_assignment, handle); + break; + + case AST_NODE_DIV_ASSIGNMENT: + ast_div_assignment_printer(((ast_node_statements*)temp)->child_nodes.div_assignment, handle); + break; + case AST_NODE_ARRAY_ASSIGNMENT: ast_array_assignment_printer(((ast_node_statements*)temp)->child_nodes.array_assignment, handle); break; @@ -174,6 +182,28 @@ void ast_assignment_printer(ast_node_assignment *assg, FILE* handle) } +void ast_mul_assignment_printer(ast_node_mul_assignment *assg, FILE* handle) +{ + if (assg != NULL && handle != NULL) + { + fprintf(handle, "\t%s *= ", assg->symbol_entry->identifier); + ast_expression_printer(assg->expression, handle); + fprintf(handle, "%s", ";\n"); + } + +} + +void ast_div_assignment_printer(ast_node_div_assignment *assg, FILE* handle) +{ + if (assg != NULL && handle != NULL) + { + fprintf(handle, "\t%s /= ", assg->symbol_entry->identifier); + ast_expression_printer(assg->expression, handle); + fprintf(handle, "%s", ";\n"); + } + +} + void ast_array_assignment_printer(ast_node_array_assignment *assign, FILE* handle) { if (assign != NULL && handle != NULL) @@ -696,7 +726,15 @@ int code_printer(ast_node* ast, int pru_id, int test) case AST_NODE_ASSIGNMENT: ast_assignment_printer(((ast_node_statements*)temp)->child_nodes.assignment, handle); break; - + + case AST_NODE_MUL_ASSIGNMENT: + ast_mul_assignment_printer(((ast_node_statements*)temp)->child_nodes.mul_assignment, handle); + break; + + case AST_NODE_DIV_ASSIGNMENT: + ast_div_assignment_printer(((ast_node_statements*)temp)->child_nodes.div_assignment, handle); + break; + case AST_NODE_ARRAY_ASSIGNMENT: ast_array_assignment_printer(((ast_node_statements*)temp)->child_nodes.array_assignment, handle); break; diff --git a/src/lexer.l b/src/lexer.l index d13a1a7..5ebf57d 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -35,6 +35,8 @@ bitwise_operators ("~"|"&"|"|"|">>"|"<<") logical_operators ("not"|"and"|"or") function ("return"|"void"|"def") assignment_operator ([:][=]) +mul_assignment_operator ([*][=]) +div_assignment_operator ([/][=]) io ("digital_read"|"digital_write"|"delay"|"pwm"|"start_counter"|"stop_counter"|"read_counter"|"init_message_channel"|"receive_message"|"send_message"|"send_int"|"send_char"|"send_bool"|"send_ints"|"send_chars"|"send_bools") print ("print"|"println") identifier ([a-zA-Z_][a-zA-Z0-9_]*) @@ -323,6 +325,14 @@ comma ([,]) return OPR_ASSIGNMENT; } +{mul_assignment_operator} { + return OPR_MUL_ASSIGNMENT; +} + +{div_assignment_operator} { + return OPR_DIV_ASSIGNMENT; +} + {io} { if (!strcmp(yytext, "digital_write")) { diff --git a/src/parser.y b/src/parser.y index 29bfe90..8c50db6 100644 --- a/src/parser.y +++ b/src/parser.y @@ -33,6 +33,8 @@ ast_node *ast = NULL; struct ast_node_declaration *declaration; struct ast_node_array_declaration *array_declaration; struct ast_node_assignment *assignment; + struct ast_node_mul_assignment *mul_assignment; + struct ast_node_div_assignment *div_assignment; struct ast_node_array_assignment *array_assignment; struct ast_node_array_access *array_access; struct ast_node_expression *expression; @@ -75,6 +77,8 @@ ast_node *ast = NULL; %right OPR_BW_NOT OPR_LGL_NOT %token OPR_ASSIGNMENT +%token OPR_MUL_ASSIGNMENT +%token OPR_DIV_ASSIGNMENT %token SEMICOLON COLON COMMA @@ -106,6 +110,8 @@ ast_node *ast = NULL; %type declaration declaration_assignment %type array_declaration array_declaration_assignment %type assignment +%type mul_assignment +%type div_assignment %type arithmetic_expression boolean_expression relational_expression logical_expression return_statement function_call_datatypes %type range_expression %type array_assignment @@ -183,6 +189,12 @@ statement: compound_statement { | assignment { $$ = create_statement_node(AST_NODE_ASSIGNMENT, (void*)$1); } + | mul_assignment { + $$ = create_statement_node(AST_NODE_MUL_ASSIGNMENT, (void*)$1); + } + | div_assignment { + $$ = create_statement_node(AST_NODE_DIV_ASSIGNMENT, (void*)$1); + } | array_assignment { $$ = create_statement_node(AST_NODE_ARRAY_ASSIGNMENT, (void*)$1); } @@ -442,6 +454,151 @@ assignment: INT_IDENTIFIER OPR_ASSIGNMENT arithmetic_expression SEMICOLON { } ; +mul_assignment: INT_IDENTIFIER OPR_MUL_ASSIGNMENT arithmetic_expression SEMICOLON { + if ($1 == NULL) + { + yyerror("variable already defined"); + } + + if ($1->is_function == 1) + { + yyerror("identifier is a function, cannot assign value"); + } + + if ($1->is_constant == 1) + { + yyerror("identifer is a pin number constant, cannot assign value"); + } + + $1->data_type = DT_INTEGER; + $1->value = $1->value * $3->value; + $$ = create_mul_assignment_node($1, $3); + + printf("%s := %d\n", $1->identifier, $1->value); + } + | BOOL_IDENTIFIER OPR_MUL_ASSIGNMENT boolean_expression SEMICOLON { + if ($1 == NULL) + { + yyerror("variable already defined"); + } + + if ($1->is_function == 1) + { + yyerror("identifier is a function, cannot assign value"); + } + + if ($1->is_constant == 1) + { + yyerror("identifer is a pin number constant, cannot assign value"); + } + + $1->data_type = DT_BOOLEAN; + $1->value = $1->value * $3->value; + $$ = create_mul_assignment_node($1, $3); + + printf("%s := %d\n", $1->identifier, $1->value); + } + | CHAR_IDENTIFIER OPR_MUL_ASSIGNMENT arithmetic_expression SEMICOLON { + if ($1 == NULL) + { + yyerror("variable already defined"); + } + + if ($1->is_function == 1) + { + yyerror("identifier is a function, cannot assign value"); + } + + if ($1->is_constant == 1) + { + yyerror("identifier is a pin number constant, cannot assign value"); + } + + $1->data_type = DT_CHAR_; + $1->value = $1->value * $3->value; + $$ = create_mul_assignment_node($1, $3); + + printf("%s := %c\n", $1->identifier, $1->value); + } + ; + +div_assignment: INT_IDENTIFIER OPR_DIV_ASSIGNMENT arithmetic_expression SEMICOLON { + if ($1 == NULL) + { + yyerror("variable already defined"); + } + + if ($1->is_function == 1) + { + yyerror("identifier is a function, cannot assign value"); + } + + if ($1->is_constant == 1) + { + yyerror("identifer is a pin number constant, cannot assign value"); + } + if ($3->value == 0) + { + yyerror("division by 0"); + } + $1->data_type = DT_INTEGER; + $1->value = $1->value / $3->value; + $$ = create_div_assignment_node($1, $3); + + printf("%s := %d\n", $1->identifier, $1->value); + } + | BOOL_IDENTIFIER OPR_DIV_ASSIGNMENT boolean_expression SEMICOLON { + if ($1 == NULL) + { + yyerror("variable already defined"); + } + + if ($1->is_function == 1) + { + yyerror("identifier is a function, cannot assign value"); + } + + if ($1->is_constant == 1) + { + yyerror("identifer is a pin number constant, cannot assign value"); + } + if ($3->value == 0) + { + yyerror("division by 0"); + } + $1->data_type = DT_BOOLEAN; + $1->value = $1->value / $3->value; + $$ = create_div_assignment_node($1, $3); + + printf("%s := %d\n", $1->identifier, $1->value); + } + | CHAR_IDENTIFIER OPR_DIV_ASSIGNMENT arithmetic_expression SEMICOLON { + if ($1 == NULL) + { + yyerror("variable already defined"); + } + + if ($1->is_function == 1) + { + yyerror("identifier is a function, cannot assign value"); + } + + if ($1->is_constant == 1) + { + yyerror("identifier is a pin number constant, cannot assign value"); + } + if ($3->value == 0) + { + yyerror("division by 0"); + } + $1->data_type = DT_CHAR_; + $1->value = $1->value / $3->value; + $$ = create_div_assignment_node($1, $3); + + printf("%s := %c\n", $1->identifier, $1->value); + } + ; + array_assignment: INT_ARR_IDENTIFIER LSQUARE arithmetic_expression RSQUARE OPR_ASSIGNMENT arithmetic_expression SEMICOLON { if ($1 == NULL) { diff --git a/tests/run_anywhere/mul-div.sim b/tests/run_anywhere/mul-div.sim new file mode 100644 index 0000000..271a504 --- /dev/null +++ b/tests/run_anywhere/mul-div.sim @@ -0,0 +1,6 @@ +int a:=5; +int b:=10; +a*=b; +b/=2; +println(a); +print(b); \ No newline at end of file diff --git a/tests/run_anywhere/mul-div.sim.output b/tests/run_anywhere/mul-div.sim.output new file mode 100644 index 0000000..4e233b1 --- /dev/null +++ b/tests/run_anywhere/mul-div.sim.output @@ -0,0 +1,2 @@ +50 +5 \ No newline at end of file