/* 2015/10 functions to support printGV() */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "ast.h" #include #include #include #include #include const char *AST_TYPE_string[] = {"PROGRAM", "GLOBAL_DECL_LIST", "GLOBAL_DECL", "DECL_LIST", "FUNCTION_DECL", "PARAM_LIST", "PARAM", "DIM_FN", "DIMFN1", "EXPR_NULL", "BLOCK", "DECL", "TYPE_DECL", "VAR_DECL", "TYPE", "STRUCT_TYPE", "DEF_LIST", "DEF", "OPT_TAG", "TAG", "ID_LIST", "DIM_DECL", "CEXPR", "MCEXPR", "CFACTOR", "INIT_ID_LIST", "INIT_ID", "STMT_LIST", "STMT", "ASSIGN_EXPR_LIST", "NONEMPTY_ASSIGN_EXPR_LIST", "TEST", "ASSIGN_EXPR", "RELOP_EXPR", "RELOP_TERM", "RELOP_FACTOR", "REL_OP", "RELOP_EXPR_LIST", "NONEMPTY_RELOP_EXPR_LIST", "EXPR", "ADD_OP", "TERM", "MUL_OP", "FACTOR", "VAR_REF", "DIM", "STRUCT_TAIL", "NUL","ID_value", "CONST_value"}; static void printLabelString(FILE *fp, AST_NODE *astNode) { const char *binaryOpString[] = { "+", "-", "*", "/", "==", ">=", "<=", "!=", ">", "<", "&&", "||" }; const char *unaryOpString[] = { "+", "-", "!" }; // fprintf(fp, "%d ", astNode->linenumber); switch (astNode->nodeType) { case PROGRAM_NODE: fprintf(fp, "PROGRAM_NODE"); break; case DECLARATION_NODE: fprintf(fp, "DECLARATION_NODE "); switch (astNode->semantic_value.declSemanticValue.kind) { case VARIABLE_DECL: fprintf(fp, "VARIABLE_DECL"); break; case TYPE_DECL: fprintf(fp, "TYPE_DECL"); break; case FUNCTION_DECL: fprintf(fp, "FUNCTION_DECL"); break; case FUNCTION_PARAMETER_DECL: fprintf(fp, "FUNCTION_PARAMETER_DECL"); break; default: assert(false); } break; case IDENTIFIER_NODE: fprintf(fp, "IDENTIFIER_NODE "); fprintf(fp, "%s ", astNode->semantic_value.identifierSemanticValue.identifierName); switch (astNode->semantic_value.identifierSemanticValue.kind) { case NORMAL_ID: fprintf(fp, "NORMAL_ID"); break; case ARRAY_ID: fprintf(fp, "ARRAY_ID"); break; case WITH_INIT_ID: fprintf(fp, "WITH_INIT_ID"); break; default: assert(false); } break; case PARAM_LIST_NODE: fprintf(fp, "PARAM_LIST_NODE"); break; case NUL_NODE: fprintf(fp, "NUL_NODE"); break; case BLOCK_NODE: fprintf(fp, "BLOCK_NODE"); break; case VARIABLE_DECL_LIST_NODE: fprintf(fp, "VARIABLE_DECL_LIST_NODE"); break; case STMT_LIST_NODE: fprintf(fp, "STMT_LIST_NODE"); break; case STMT_NODE: fprintf(fp, "STMT_NODE "); switch (astNode->semantic_value.stmtSemanticValue.kind) { case WHILE_STMT: fprintf(fp, "WHILE_STMT"); break; case FOR_STMT: fprintf(fp, "FOR_STMT"); break; case ASSIGN_STMT: fprintf(fp, "ASSIGN_STMT"); break; case IF_STMT: fprintf(fp, "IF_STMT"); break; case FUNCTION_CALL_STMT: fprintf(fp, "FUNCTION_CALL_STMT"); break; case RETURN_STMT: fprintf(fp, "RETURN_STMT"); break; default: assert(false); } break; case EXPR_NODE: fprintf(fp, "EXPR_NODE "); switch (astNode->semantic_value.exprSemanticValue.kind) { case BINARY_OPERATION: fprintf(fp, "%s", binaryOpString[astNode->semantic_value.exprSemanticValue.op.binaryOp]); break; case UNARY_OPERATION: fprintf(fp, "%s", unaryOpString[astNode->semantic_value.exprSemanticValue.op.unaryOp]); break; default: assert(false); } break; case CONST_VALUE_NODE: fprintf(fp, "CONST_VALUE_NODE "); switch (astNode->semantic_value.const1->const_type) { case INTEGERC: fprintf(fp, "%d", astNode->semantic_value.const1->const_u.intval); break; case FLOATC: fprintf(fp, "%f", astNode->semantic_value.const1->const_u.fval); break; case STRINGC: astNode->semantic_value.const1->const_u.sc[strlen(astNode->semantic_value.const1->const_u.sc) - 1] = 0; fprintf(fp, "\\\"%s\\\"", astNode->semantic_value.const1->const_u.sc + 1); astNode->semantic_value.const1->const_u.sc[strlen(astNode->semantic_value.const1->const_u.sc)] = '"'; astNode->semantic_value.const1->const_u.sc[strlen(astNode->semantic_value.const1->const_u.sc) + 1] = 0; break; default: assert(false); } break; case NONEMPTY_ASSIGN_EXPR_LIST_NODE: fprintf(fp, "NONEMPTY_ASSIGN_EXPR_LIST_NODE"); break; case NONEMPTY_RELOP_EXPR_LIST_NODE: fprintf(fp, "NONEMPTY_RELOP_EXPR_LIST_NODE"); break; default: fprintf(fp, "default case in char *getLabelString(AST_TYPE astType)"); break; } } // count: the (unused) id number to be used // return: then next unused id number static int printGVNode(FILE *fp, AST_NODE* node, int count) { if (node == NULL) { return count; } int currentNodeCount = count; fprintf(fp, "node%d [label =\"", count); printLabelString(fp, node); fprintf(fp, "\"]\n"); ++count; int countAfterCheckChildren = count; if (node->child) { countAfterCheckChildren = printGVNode(fp, node->child, count); fprintf(fp, "node%d -> node%d [style = bold]\n", currentNodeCount, count); } int countAfterCheckSibling = countAfterCheckChildren; if (node->rightSibling) { countAfterCheckSibling = printGVNode(fp, node->rightSibling, countAfterCheckChildren); fprintf(fp, "node%d -> node%d [style = dashed]\n", currentNodeCount, countAfterCheckChildren); } return countAfterCheckSibling; } void printGV(AST_NODE *root, const char* fileName) { if (fileName == NULL) { fileName = "AST_Graph.gv"; } FILE *fp; fp = fopen(fileName, "w"); if (!fp) { printf("Cannot open file \"%s\"\n", fileName); return; } fprintf(fp , "Digraph AST\n"); fprintf(fp , "{\n"); fprintf(fp , "label = \"%s\"\n", fileName); int nodeCount = 0; printGVNode(fp, root, nodeCount); fprintf(fp , "}\n"); fclose(fp); }