You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
452 lines
8.6 KiB
452 lines
8.6 KiB
/* ast.c */ |
|
|
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#include <err.h> |
|
#include "types.h" |
|
#include "ast.h" |
|
#include "mem.h" |
|
|
|
extern int yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
return elem; |
|
} |
|
|
|
ast *make_string(char *string) |
|
{ |
|
ast *elem = safe_malloc(sizeof(ast)); |
|
|
|
elem->tag = str_ast; |
|
elem->info.string = string; |
|
elem->lineno = yylineno; |
|
|
|
return elem; |
|
} |
|
|
|
ast *make_integer(long integer) |
|
{ |
|
ast *elem = safe_malloc(sizeof(ast)); |
|
|
|
elem->tag = int_ast; |
|
elem->info.integer = integer; |
|
elem->lineno = yylineno; |
|
|
|
return elem; |
|
} |
|
|
|
ast *make_real(float real) |
|
{ |
|
ast *elem = safe_malloc(sizeof(ast)); |
|
|
|
elem->tag = real_ast; |
|
elem->info.real = real; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
return elem; |
|
} |
|
|
|
ast *make_fndefint_v(char *identifier, long num) |
|
{ |
|
ast *elem = safe_malloc(sizeof(ast)); |
|
ast_list *list = NULL; |
|
|
|
elem->tag = node_ast; |
|
elem->info.node.tag = kind_fndefint_v; |
|
list = make_list(make_integer(num), list); |
|
list = make_list(make_string(identifier), list); |
|
elem->info.node.head = list; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
return elem; |
|
} |
|
|
|
ast *make_variable(char *identifier) |
|
{ |
|
ast *elem = safe_malloc(sizeof(ast)); |
|
|
|
elem->tag = var_ast; |
|
elem->info.variable = identifier; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
return elem; |
|
} |
|
|
|
ast *make_case_statement_variable(char *identifier) |
|
{ |
|
ast *elem = safe_malloc(sizeof(ast)); |
|
|
|
elem->tag = casevar_ast; |
|
elem->info.variable = identifier; |
|
elem->lineno = yylineno; |
|
|
|
return elem; |
|
} |
|
|
|
ast *make_case_statement_number(long num) |
|
{ |
|
ast *elem = safe_malloc(sizeof(ast)); |
|
|
|
elem->tag = casenum_ast; |
|
elem->info.integer = num; |
|
elem->lineno = yylineno; |
|
|
|
return elem; |
|
} |
|
|
|
ast *make_return_statement(ast *expression) |
|
{ |
|
ast *elem = safe_malloc(sizeof(ast)); |
|
|
|
elem->tag = node_ast; |
|
elem->info.node.tag = stmt_return; |
|
elem->info.node.head = make_list(expression, NULL); |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
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; |
|
elem->lineno = yylineno; |
|
|
|
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); |
|
} |
|
|
|
|