/* ast.c */ #include #include #include #include "types.h" #include "ast.h" #include "mem.h" ast_list *make_list(ast *elem, ast_list *tail) { ast_list *list = safe_malloc(sizeof(ast_list)); list->elem = elem; list->next = tail; return list; } ast_list *reverse_list(ast_list *list) { ast_list *last = NULL; ast_list *next; while (list) { next = list->next; list->next = last; last = list; list = next; } return last; } ast *make_list_node(ast_list *list) { ast *elem = safe_malloc(sizeof(ast)); elem->tag = node_ast; elem->info.node.tag = kind_list; elem->info.node.head = list; return elem; } ast *make_string(char *string) { ast *elem = safe_malloc(sizeof(ast)); elem->tag = str_ast; elem->info.string = string; return elem; } ast *make_integer(long integer) { ast *elem = safe_malloc(sizeof(ast)); elem->tag = int_ast; elem->info.integer = integer; return elem; } ast *make_real(float real) { ast *elem = safe_malloc(sizeof(ast)); elem->tag = real_ast; elem->info.real = real; return elem; } ast *make_function(char *identifier, ast_list *args, ast_list *stmts) { ast *elem = safe_malloc(sizeof(ast)); ast_list *list = NULL; elem->tag = node_ast; elem->info.node.tag = kind_fndef; list = make_list(make_list_node(stmts), list); list = make_list(make_list_node(args), list); list = make_list(make_string(identifier), list); elem->info.node.head = list; return elem; } ast *make_fndefint(char *identifier, long num) { ast *elem = safe_malloc(sizeof(ast)); ast_list *list = NULL; elem->tag = node_ast; elem->info.node.tag = kind_fndefint; list = make_list(make_integer(num), list); list = make_list(make_string(identifier), list); elem->info.node.head = list; return elem; } ast *make_constant(char *identifier, long num) { ast *elem = safe_malloc(sizeof(ast)); ast_list *list = NULL; elem->tag = node_ast; elem->info.node.tag = kind_constant; list = make_list(make_integer(num), list); list = make_list(make_string(identifier), list); elem->info.node.head = list; return elem; } ast *make_realconstant(char *identifier, float num) { ast *elem = safe_malloc(sizeof(ast)); ast_list *list = NULL; elem->tag = node_ast; elem->info.node.tag = kind_constant; list = make_list(make_real(num), list); list = make_list(make_string(identifier), list); elem->info.node.head = list; return elem; } ast *make_fndefext(char *identifier) { ast *elem = safe_malloc(sizeof(ast)); ast_list *list = NULL; elem->tag = node_ast; elem->info.node.tag = kind_fndefext; list = make_list(make_string(identifier), list); elem->info.node.head = list; return elem; } ast *make_variable(char *identifier) { ast *elem = safe_malloc(sizeof(ast)); elem->tag = var_ast; elem->info.variable = identifier; return elem; } ast *make_array(char *identifier, ast *expression) { ast *elem = safe_malloc(sizeof(ast)); ast_list *list; elem->tag = array_ast; elem->info.node.tag = kind_array; list = make_list(expression, NULL); list = make_list(make_variable(identifier), list); elem->info.node.head = list; return elem; } /* ast *make_assignment(char *identifier, ast *expression) { ast *elem = safe_malloc(sizeof(ast)); ast_list *list; elem->tag = node_ast; elem->info.node.tag = kind_assign; list = make_list(expression, NULL); list = make_list(make_variable(identifier), list); elem->info.node.head = list; return elem; } */ ast *make_assignment(ast_list *identifier_list, ast *expression) { ast *elem = safe_malloc(sizeof(ast)); ast_list *list; elem->tag = node_ast; elem->info.node.tag = kind_assign; list = make_list(expression, NULL); list = make_list(make_list_node(identifier_list), list); elem->info.node.head = list; return elem; } ast *make_binary_op(ast_kind op, ast *exp1, ast *exp2) { ast *elem = safe_malloc(sizeof(ast)); ast_list *list; elem->tag = node_ast; elem->info.node.tag = op; list = make_list(exp2, NULL); list = make_list(exp1, list); elem->info.node.head = list; return elem; } ast *make_unary_op(ast_kind op, ast *exp1) { ast *elem = safe_malloc(sizeof(ast)); ast_list *list; elem->tag = node_ast; elem->info.node.tag = op; list = make_list(exp1, NULL); elem->info.node.head = list; return elem; } ast *make_call(char *identifier, ast_list *args) { ast *elem = safe_malloc(sizeof(ast)); ast_list *list; elem->tag = node_ast; elem->info.node.tag = kind_call; list = make_list(make_list_node(args), NULL); list = make_list(make_string(identifier), list); elem->info.node.head = list; return elem; } ast *make_statement(ast_kind type, ast *expression, ast_list *statements, ast_list *more_statements) { ast *elem = safe_malloc(sizeof(ast)); ast_list *list; elem->tag = node_ast; elem->info.node.tag = type; list = NULL; if (more_statements) list = make_list(make_list_node(more_statements), list); list = make_list(make_list_node(statements), list); list = make_list(expression, list); elem->info.node.head = list; return elem; } ast *make_case_statement_variable(char *identifier) { ast *elem = safe_malloc(sizeof(ast)); elem->tag = casevar_ast; elem->info.variable = identifier; return elem; } ast *make_case_statement_number(long num) { ast *elem = safe_malloc(sizeof(ast)); elem->tag = casenum_ast; elem->info.integer = num; return elem; } ast *make_return_statement(void) { ast *elem = safe_malloc(sizeof(ast)); elem->tag = node_ast; elem->info.node.tag = stmt_return; elem->info.node.head = NULL; return elem; } ast *make_break_statement(void) { ast *elem = safe_malloc(sizeof(ast)); elem->tag = node_ast; elem->info.node.tag = stmt_break; elem->info.node.head = NULL; return elem; } ast *make_default_statement(void) { ast *elem = safe_malloc(sizeof(ast)); elem->tag = node_ast; elem->info.node.tag = stmt_default; elem->info.node.head = NULL; return elem; } void indent(int spaces) { spaces = spaces * 2; while (spaces--) { printf(" "); } } void ast_dump_main(ast *, int); void ast_dump_list(ast_list *list, int spaces) { while (list) { ast_dump_main(list->elem, spaces); list = list->next; } } void ast_dump_main(ast *node, int spaces) { indent(spaces); switch (node->tag) { case int_ast: printf("integer: %ld\n", node->info.integer); break; case real_ast: printf("real: %g\n", node->info.real); break; case var_ast: printf("variable: %s\n", node->info.variable); break; case str_ast: printf("string: %s\n", node->info.string); break; case node_ast: switch (node->info.node.tag) { case kind_fndef: printf("function definition:\n"); break; case kind_assign: printf("assignment:\n"); break; case kind_list: printf("generic list:\n"); break; case kind_call: printf("function call:\n"); break; case op_plus: printf("plus operation:\n"); break; case op_minus: printf("minus operation:\n"); break; case op_times: printf("times operation:\n"); break; case op_divide: printf("divide operation:\n"); break; case op_gt: printf("greater than operation:\n"); break; case op_lt: printf("less than operation:\n"); break; case op_ge: printf("greater than or equal operation:\n"); break; case op_le: printf("less than or equal operation:\n"); break; case op_eq: printf("equality operation:\n"); break; case op_ne: printf("not equal operation:\n"); break; case stmt_if: printf("if statement:\n"); break; case stmt_while: printf("while statement:\n"); break; default: printf("unknown list type:\n"); break; } ast_dump_list(node->info.node.head, spaces+1); break; default: printf("unknown node type\n"); break; } } void ast_dump(ast *node) { ast_dump_main(node, 0); }