Newer
Older
#include "mcc/ast_visit.h"
#include <assert.h>
#include <stdlib.h>
#define visit(node, callback, visitor) \
do { \
if (callback) { \
(callback)(node, (visitor)->userdata); \
} \
} while (0)
#define visit_if(cond, node, callback, visitor) \
do { \
if (cond) { \
visit(node, callback, visitor); \
} \
} while (0)
#define visit_if_pre_order(node, callback, visitor) \
visit_if((visitor)->order == MCC_AST_VISIT_PRE_ORDER, node, callback, visitor)
#define visit_if_post_order(node, callback, visitor) \
visit_if((visitor)->order == MCC_AST_VISIT_POST_ORDER, node, callback, visitor)
void mcc_ast_visit_expression(struct mcc_ast_expression *expression, struct mcc_ast_visitor *visitor)
{
assert(expression);
assert(visitor);
visit_if_pre_order(expression, visitor->expression, visitor);
switch (expression->type) {
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
case MCC_AST_EXPRESSION_TYPE_LITERAL:
visit_if_pre_order(expression, visitor->expression_literal, visitor);
mcc_ast_visit_literal(expression->literal, visitor);
visit_if_post_order(expression, visitor->expression_literal, visitor);
break;
case MCC_AST_EXPRESSION_TYPE_BINARY_OP:
visit_if_pre_order(expression, visitor->expression_binary_op, visitor);
mcc_ast_visit_expression(expression->lhs, visitor);
mcc_ast_visit_expression(expression->rhs, visitor);
visit_if_post_order(expression, visitor->expression_binary_op, visitor);
break;
case MCC_AST_EXPRESSION_TYPE_UNARY_OP:
visit_if_pre_order(expression, visitor->expression_unary_op,visitor);
mcc_ast_visit_expression(expression->unary_expression, visitor);
visit_if_post_order(expression, visitor->expression_unary_op, visitor);
break;
case MCC_AST_EXPRESSION_TYPE_PARENTH:
visit_if_pre_order(expression, visitor->expression_parenth, visitor);
mcc_ast_visit_expression(expression->expression, visitor);
visit_if_post_order(expression, visitor->expression_parenth, visitor);
break;
case MCC_AST_EXPRESSION_TYPE_IDENTIFIER:
visit_if_pre_order(expression, visitor->expression_identifier, visitor);
mcc_ast_visit_identifier(expression->identifier, visitor);
visit_if_post_order(expression, visitor->expression_identifier, visitor);
break;
case MCC_AST_EXPRESSION_TYPE_CALL_EXPRESSION:
visit_if_pre_order(expression, visitor->expression_call_expression, visitor);
mcc_ast_visit_identifier(expression->function_name,visitor);
if (expression->argument != NULL) {
mcc_ast_visit_argument(expression->argument, visitor);
}
visit_if_post_order(expression, visitor->expression_parenth, visitor);
break;
case MCC_AST_EXPRESSION_TYPE_BRACKET:
visit_if_pre_order(expression,visitor->expression_bracket,visitor);
mcc_ast_visit_identifier(expression->bracket_identifier,visitor);
mcc_ast_visit_expression(expression->bracket_expression,visitor);
visit_if_post_order(expression,visitor->expression_bracket,visitor);
}
visit_if_post_order(expression, visitor->expression, visitor);
}
void mcc_ast_visit_literal(struct mcc_ast_literal *literal,struct mcc_ast_visitor *visitor)
{
assert(literal);
assert(visitor);
switch (literal->type) {
case MCC_AST_DATA_TYPE_BOOL:
visit(literal, visitor->literal_bool, visitor);
break;
case MCC_AST_DATA_TYPE_INT:
visit(literal, visitor->literal_int, visitor);
break;
case MCC_AST_DATA_TYPE_FLOAT:
visit(literal, visitor->literal_float, visitor);
break;
case MCC_AST_DATA_TYPE_STRING:
visit(literal, visitor->literal_string, visitor);
break;
default:
break;
}
}
void mcc_ast_visit_declaration(struct mcc_ast_declaration *declaration,
{
assert(declaration);
assert(visitor);
visit_if_pre_order(declaration, visitor->declaration, visitor);
if (declaration->arr_literal) {
mcc_ast_visit_literal(declaration->arr_literal, visitor);
}
mcc_ast_visit_identifier(declaration->ident, visitor);
visit_if_post_order(declaration, visitor->declaration, visitor);
}
void mcc_ast_visit_statement_list(struct mcc_ast_statement_list *statement_list,
assert(statement_list);
assert(visitor);
struct mcc_ast_statement_list *next = statement_list;
while (next != NULL) {
visit_if_pre_order(next, visitor->statement_list, visitor);
mcc_ast_visit_statement(next->statement, visitor);
visit_if_post_order(statement_list, visitor->statement_list, visitor);
next = next->next;
}
}
void mcc_ast_visit_statement(struct mcc_ast_statement *statement,
assert(statement);
assert(visitor);
visit_if_pre_order(statement, visitor->statement, visitor);
case MCC_AST_STATEMENT_TYPE_IF:
visit_if_pre_order(statement, visitor->statement_if, visitor);
mcc_ast_visit_expression(statement->if_condition, visitor);
mcc_ast_visit_statement(statement->if_stmt, visitor);
if (statement->else_stmt != NULL) {
mcc_ast_visit_statement(statement->else_stmt, visitor);
}
visit_if_post_order(statement, visitor->statement_if, visitor);
break;
case MCC_AST_STATEMENT_TYPE_WHILE:
visit_if_pre_order(statement, visitor->statement_while, visitor);
mcc_ast_visit_expression(statement->while_condition, visitor);
mcc_ast_visit_statement(statement->while_stmt, visitor);
visit_if_post_order(statement, visitor->statement_while, visitor);
break;
case MCC_AST_STATEMENT_TYPE_DECL:
visit_if_pre_order(statement, visitor->statement_declaration,
mcc_ast_visit_declaration(statement->declaration, visitor);
visit_if_post_order(statement, visitor->statement_declaration,
break;
case MCC_AST_STATEMENT_TYPE_ASSGN:
visit_if_pre_order(statement, visitor->statement_assignment,
mcc_ast_visit_identifier(statement->assignment->identifier, visitor);
if (statement->assignment) {
mcc_ast_visit_expression(statement->assignment->array_ass.index, visitor);
}
mcc_ast_visit_expression(statement->assignment->normal_ass.rhs, visitor);
visit_if_post_order(statement, visitor->statement_assignment,
break;
case MCC_AST_STATEMENT_TYPE_EXPRESSION:
visit_if_pre_order(statement, visitor->statement_expression,
mcc_ast_visit_expression(statement->expression, visitor);
visit_if_post_order(statement, visitor->statement_expression,
break;
case MCC_AST_STATEMENT_TYPE_COMPOUND:
visit_if_pre_order(statement, visitor->statement_compound, visitor);
if (statement->statement_list != NULL) {
mcc_ast_visit_statement_list(statement->statement_list, visitor);
}
visit_if_post_order(statement, visitor->statement_compound,
break;
case MCC_AST_STATEMENT_TYPE_RETURN:
visit_if_pre_order(statement, visitor->statement_return, visitor);
if (statement->expression != NULL) {
mcc_ast_visit_expression(statement->expression, visitor);
}
visit_if_post_order(statement, visitor->statement_return, visitor);
break;
case MCC_AST_STATEMENT_TYPE_ASSGN_ARR:
break;
}
visit_if_post_order(statement, visitor->statement, visitor);
}
void mcc_ast_visit_assignment(struct mcc_ast_assignment *assignment,
{
assert(assignment);
assert(visitor);
visit_if_pre_order(assignment, visitor->assignment, visitor);
switch (assignment->type) {
case MCC_AST_ASSIGNMENT_TYPE_NORMAL:
mcc_ast_visit_identifier(assignment->identifier, visitor);
mcc_ast_visit_expression(assignment->normal_ass.rhs, visitor);
break;
case MCC_AST_ASSIGNMENT_TYPE_ARRAY:
mcc_ast_visit_identifier(assignment->identifier, visitor);
mcc_ast_visit_expression(assignment->array_ass.index, visitor);
mcc_ast_visit_expression(assignment->array_ass.rhs, visitor);
break;
}
visit_if_post_order(assignment, visitor->assignment, visitor);
}
void mcc_ast_visit_identifier(struct mcc_ast_identifier *identifier, struct mcc_ast_visitor *visitor)
{
assert(identifier);
assert(visitor);
visit(identifier, visitor->identifier, visitor);
}
void mcc_ast_visit_parameter(struct mcc_ast_parameter *parameter,
{
assert(visitor);
if (parameter) {
visit_if_pre_order(parameter, visitor->parameter, visitor);
for (int i = 0; i < parameter-> parameters -> size; i++) {
mcc_ast_visit_declaration(parameter->parameters -> arr[i], visitor);
}
visit_if_post_order(parameter, visitor->parameter, visitor);
}
}
void mcc_ast_visit_argument(struct mcc_ast_argument *argument,
{
assert(visitor);
if (argument) {
visit_if_pre_order(argument, visitor->argument, visitor);
for (int i = 0; i < argument-> expressions -> size; i++) {
mcc_ast_visit_expression(argument->expressions -> arr[i], visitor);
}
visit_if_post_order(argument, visitor->argument, visitor);
}
}
void mcc_ast_visit_function(struct mcc_ast_function *function,
{
assert(function);
assert(visitor);
visit_if_pre_order(function, visitor->function, visitor);
mcc_ast_visit_identifier(function->identifier, visitor);
if (function -> parameter != NULL) {
mcc_ast_visit_parameter(function->parameter, visitor);
}
if (function -> statement != NULL) {
mcc_ast_visit_statement(function->statement, visitor);
}
visit_if_post_order(function, visitor->function, visitor);
}
void mcc_ast_visit_program(struct mcc_ast_program *program, struct mcc_ast_visitor *visitor)
{
assert(program);
assert(visitor);
visit_if_pre_order(program, visitor->program, visitor);
for (int i = 0; i < program-> function_def -> size; i++) {
mcc_ast_visit_function(program->function_def -> arr [i], visitor);
}
visit_if_post_order(program, visitor->program, visitor);
}