void dump_ast(FILE *dotfile, node* start_node, int index) { switch(start_node->type) { case T_ADD : fprintf(dotfile, "node%i [label=\"+\"];\n", index); break; case T_MUL : fprintf(dotfile, "node%i [label=\"*\"];\n", index); break; case T_VAL : fprintf(dotfile, "node%i [label=\"%i\"];\n", index,start_node->value); break; default : fprintf(dotfile, "node%i;\n", index); } if (start_node->value > 0) { fprintf(dotfile, "node%i [label=\"%i\"];\n", index,start_node->value); } if (start_node->left > 0) { fprintf(dotfile, "node%i->node%i;\n", index, 2*index); dump_ast(dotfile, start_node->left,2*index); } if (start_node->right > 0) { fprintf(dotfile, "node%i->node%i;\n", index, 2*index+1); dump_ast(dotfile, start_node->right,2*index+1); } }
void test3(void) { int last = -42; struct ast * ast; struct gram * gram; // gram = int !.; gram = new_gram_cat(NULL, new_gram_int(NULL), new_gram_negla(NULL, new_gram_dot(NULL)), NULL); const char * text = "42"; // debug: ast = parse(text, gram, &last); printf("matching \"42\"\nast=%p, last = %d\n", ast, last); dump_ast(ast, 0, NULL); // assertions: assert(ast); assert(ast->children[0]); assert(ast->children[0]->from == 0); assert(ast->children[0]->len == 2); assert(strtol(text + ast->children[0]->from, NULL, 0) == 42); assert(ast->children[1]); assert(last == strlen(text)); // debug: last = -42; text = " 0xfoo"; ast = parse(text, gram, &last); printf("matching \" 0xfoo\"\nast=%p, last = %d\n", ast, last); dump_ast(ast, 0, NULL); // assertions: assert(!ast); assert(last == 4); printf("test3 passed!\n\n"); }
void test4(void) { int last = -42; struct ast * ast; struct gram * gram; // gram == ('a'/'b')+!. gram = new_gram_cat(NULL, new_gram_aster(NULL, new_gram_alt(NULL, new_gram_string((void*)0xa, "a"), new_gram_string((void*)0xb, "b"), NULL)), new_gram_negla(NULL, new_gram_dot(NULL)), NULL); const char * text = "baba"; ast = parse(text, gram, &last); // debug: dump_ast(ast, 0, NULL); assert(ast); ast = purge_ast(ast); printf("after cleanup:\n"); dump_ast(ast, 0, NULL); // assertions: assert(ast); assert(ast->children[0] && ast->children[1] && ast->children[2] && ast->children[3]); assert(!ast->children[4]); printf("test4 passed!\n\n"); }
void test1(void) { // gram = 'a'*!.; struct gram * gram; gram = new_gram_cat(NULL, new_gram_aster(NULL, new_gram_string(NULL, "a")), new_gram_negla(NULL, new_gram_dot(NULL)), NULL); assert(gram); int i, last = -42; struct ast * ast = parse("aaa", gram, &last); // debug printf("matching \"aaa\"\nast=%p, last = %d\n", ast, last); dump_ast(ast, 0, NULL); // assertions assert(last == 3); assert(ast); assert(ast->children[0] && ast->children[1] && !ast->children[2]); assert(ast->children[0]->from == 0 && ast->children[0]->len == 3); assert(ast->children[1]->from == 3 && ast->children[1]->len == 0); for (i = 0; i < 3; i++) assert(ast->children[0]->children[i]->from == i && ast->children[0]->children[i]->len == 1 && !ast->children[0]->children[i]->children[0]); // debug last = -42; ast = parse("aaa!", gram, &last); printf("matching \"aaa!\"\nast=%p, last = %d\n", ast, last); dump_ast(ast, 0, NULL); // assertions assert(last == 3); assert(!ast); printf("test1 passed!\n\n"); }
/* ------------------------------------------------------------------------ @NAME : bt_parse_entry_s() @INPUT : entry_text - string containing the entire entry to parse, or NULL meaning we're done, please cleanup options - standard btparse options bitmap line - current line number (if that makes any sense) -- passed to the parser to set zzline, so that lexical and syntax errors are properly localized @OUTPUT : *top - newly-allocated AST for the entry (or NULL if entry_text was NULL, ie. at EOF) @RETURNS : 1 with *top set to AST for entry on successful read/parse 1 with *top==NULL if entry_text was NULL, ie. at EOF 0 if any serious errors seen in input (*top is still set to the AST, but only for as much of the input as we were able to parse) (A "serious" error is a lexical or syntax error; "trivial" errors such as warnings and notifications count as "success" for the purposes of this function's return value.) @DESCRIPTION: Parses a BibTeX entry contained in a string. @GLOBALS : @CALLS : ANTLR @CREATED : 1997/01/18, GPW (from code in bt_parse_entry()) @MODIFIED : -------------------------------------------------------------------------- */ AST * bt_parse_entry_s (char * entry_text, char * filename, int line, ushort options, boolean * status) { AST * entry_ast = NULL; static int * err_counts = NULL; if (options & BTO_STRINGMASK) /* any string options set? */ { usage_error ("bt_parse_entry_s: illegal options " "(string options not allowed"); } InputFilename = filename; err_counts = bt_get_error_counts (err_counts); if (entry_text == NULL) /* signal to clean up */ { finish_parse (&err_counts); if (status) *status = TRUE; return NULL; } zzast_sp = ZZAST_STACKSIZE; /* workaround apparent pccts bug */ start_parse (NULL, entry_text, line); entry (&entry_ast); /* enter the parser */ ++zzasp; /* why is this done? */ if (entry_ast == NULL) /* can happen with very bad input */ { if (status) *status = FALSE; return entry_ast; } #if DEBUG dump_ast ("bt_parse_entry_s: single entry, after parsing:\n", entry_ast); #endif bt_postprocess_entry (entry_ast, StringOptions[entry_ast->metatype] | options); #if DEBUG dump_ast ("bt_parse_entry_s: single entry, after post-processing:\n", entry_ast); #endif if (status) *status = parse_status (err_counts); return entry_ast; } /* bt_parse_entry_s () */
void test2(void) { struct gram * gram, * tmp; struct ast * ast; int last = -42; // gram = ('[' gram ']')+ / ""; gram = new_gram_alt((void*)0xa, new_gram_plus((void*)0x35, tmp = new_gram_cat((void*)0xc, new_gram_string(NULL, "["), (struct gram *)(-1), new_gram_string(NULL, "]"), NULL)), new_gram_string((void*)0x1337, ""), NULL); assert(gram); // add cyclic reference by setting child: gram_set_child(tmp, gram, 1); // debug ast = parse("[[][]x]", gram, &last); printf("matching \"[[][]x]\"\nast=%p, last = %d\n", ast, last); dump_ast(ast, 0, NULL); // assertions assert(ast); assert("[[][]x]"[last] == 'x'); assert(ast->children[0]); assert(ast->children[0]->user_data == (void*)0x1337); assert(!ast->children[1]); printf("test2 passed!\n\n"); }
static void branch(const struct ast_node *ast) { if (ast) { putchar(' '); dump_ast(ast); } }
static void runPass(const char *passName, void (*pass)(void), void (*check)(), char log_tag) { static struct timeval startTimeBetweenPasses; static struct timeval stopTimeBetweenPasses; static double timeBetweenPasses = -1.0; static double totalTime = 0.0; struct timeval startTime; struct timeval stopTime; struct timezone timezone; static bool performTiming = printPasses || (printPassesFile != NULL); if (performTiming) { gettimeofday(&stopTimeBetweenPasses, &timezone); if (timeBetweenPasses < 0.0) timeBetweenPasses = 0.0; else timeBetweenPasses += ((double)((stopTimeBetweenPasses.tv_sec*1e6+ stopTimeBetweenPasses.tv_usec) - (startTimeBetweenPasses.tv_sec*1e6+ startTimeBetweenPasses.tv_usec))) / 1e6; } if (strlen(fPrintStatistics) && strcmp(passName, "parse")) printStatistics("clean"); if (performTiming) { printPassTiming("%32s :", passName); gettimeofday(&startTime, &timezone); } (*pass)(); if (performTiming) { gettimeofday(&stopTime, &timezone); printPassTiming("%8.3f seconds", ((double)((stopTime.tv_sec*1e6+stopTime.tv_usec) - (startTime.tv_sec*1e6+startTime.tv_usec))) / 1e6); if (developer && printPasses) fprintf(stderr, " [%d]", lastNodeIDUsed()); printPassTiming("\n"); totalTime += ((double)((stopTime.tv_sec*1e6+stopTime.tv_usec) - (startTime.tv_sec*1e6+startTime.tv_usec))) / 1e6; if (!strcmp(passName, "makeBinary")) { printPassTiming("%32s :%8.3f seconds\n", "time between passes", timeBetweenPasses); printPassTiming("%32s :%8.3f seconds\n", "total time", totalTime+timeBetweenPasses); } } if (strlen(fPrintStatistics)) printStatistics(passName); if (fdump_html) { html_view(passName); } if (logging(log_tag)) dump_ast(passName, currentPassNo); if (performTiming) { gettimeofday(&startTimeBetweenPasses, &timezone); } considerExitingEndOfPass(); cleanAst(); (*check)(); // Run per-pass check function. //printPrimitiveCounts(passName); }
static const char *assign_per_vertex(struct parser_comm *comm, struct sym *sym, struct ast_node *node) { if (!quiet) { printf("per_vertex = %s = ", sym->fpvm_sym.name); dump_ast(node); putchar('\n'); } return NULL; }
int main(int argc, char *argv[]) { struct v7 *v7; int i, show_ast = 0; v7 = v7_create(); /* Execute inline code */ for (i = 1; i < argc && argv[i][0] == '-'; i++) { if (strcmp(argv[i], "-e") == 0 && i + 1 < argc) { if (show_ast) { dump_ast(argv[i + 1]); } else if (!v7_exec(v7, argv[i + 1])) { fprintf(stderr, "Error executing [%s]: %s\n", argv[i + 1], v7_get_error_string(v7)); } i++; } else if (strcmp(argv[i], static_show_ast_flag) == 0) { show_ast = 1; } else if (strcmp(argv[i], "-h") == 0) { show_usage(argv); } } /* Execute files */ for (; i < argc; i++) { if (show_ast) { size_t size; char *source_code; if ((source_code = read_file(argv[i], &size)) == NULL) { fprintf(stderr, "Cannot read [%s]\n", argv[i]); } else { dump_ast(source_code); free(source_code); } } else if (!v7_exec_file(v7, argv[i])) { fprintf(stderr, "%s\n", v7_get_error_string(v7)); } } v7_destroy(&v7); return EXIT_SUCCESS; }
void dump_typedefs() { Dict *defs = init_typedefs(); for (int i = 0; i < defs->entries->length; i++) { DictEntry *entry = vector_get(defs->entries, i); printf("'%s':\n", entry->key); Node *type = entry->data; dump_ast(type); } }
static const char *assign_default(struct parser_comm *comm, struct sym *sym, struct ast_node *node) { if (fail) return strdup(fail); if (!quiet) { printf("%s = ", sym->fpvm_sym.name); dump_ast(node); putchar('\n'); } return NULL; }
void graphviz(node* start_node) { FILE *dotfile = fopen("ast.dot", "w"); fprintf(dotfile, "digraph tree {\n"); dump_ast(dotfile, start_node, 1); fprintf(dotfile, "}\n"); fclose(dotfile); // OS X //system("dot -Tpng ast.dot > ast.png && open ast.png"); // Linux system("dot -Tpng ast.dot > ast.png && xdg-open ast.png"); }
static void dump_ast(SpnAST *ast, int indent) { static const char *const nodnam[] = { "program", "block-statement", "function-statement", "while", "do-while", "for", "foreach", "if", "break", "continue", "return", "empty-statement", "vardecl", "global-constant", "assign", "assign-add", "assign-subtract", "assign-multiply", "assign-divide", "assign-modulo", "assign-and", "assign-or", "assign-xor", "assign-left-shift", "assign-right-shift", "assign-concat", "concatenate", "conditional-ternary", "add", "subtract", "multiply", "divide", "modulo", "logical-and", "logical-or", "bitwise-and", "bitwise-or", "bitwise-xor", "left-shift", "right-shift", "equals", "not-equal", "less-than", "less-than-or-equal", "greater-than", "greater-than-or-equal", "unary-plus", "unary-minus", "preincrement", "predecrement", "sizeof", "typeof", "logical-not", "bitwise-not", "nth-arg", "postincrement", "postdecrement", "array-subscript", "memberof", "function-call", "identifier", "literal", "function-expr", "argc", "decl-argument", "call-argument", "branches", "for-header", "generic-compound" }; dump_indent(indent); printf("(%s", nodnam[ast->node]); /* print name, if any */ if (ast->name != NULL) { printf(" name = \"%s\"", ast->name->cstr); } /* print formatted value */ if ((ast->value.t == SPN_TYPE_NIL && ast->node == SPN_NODE_LITERAL) || ast->value.t != SPN_TYPE_NIL) { printf(" value = "); spn_value_print(&ast->value); } if (ast->left != NULL || ast->right != NULL) { fputc('\n', stdout); } /* dump subtrees, if any */ if (ast->left != NULL) { dump_ast(ast->left, indent + 1); } if (ast->right != NULL) { dump_ast(ast->right, indent + 1); } if (ast->left != NULL || ast->right != NULL) { dump_indent(indent); } puts(")"); }
void spn_ast_dump(SpnAST *ast) { dump_ast(ast, 0); }
/* ------------------------------------------------------------------------ @NAME : bt_parse_entry() @INPUT : infile - file to read next entry from options - standard btparse options bitmap @OUTPUT : *top - AST for the entry, or NULL if no entries left in file @RETURNS : same as bt_parse_entry_s() @DESCRIPTION: Starts (or continues) parsing from a file. @GLOBALS : @CALLS : @CREATED : Jan 1997, GPW @MODIFIED : -------------------------------------------------------------------------- */ AST * bt_parse_entry (FILE * infile, char * filename, ushort options, boolean * status) { AST * entry_ast = NULL; static int * err_counts = NULL; static FILE * prev_file = NULL; if (prev_file != NULL && infile != prev_file) { usage_error ("bt_parse_entry: you can't interleave calls " "across different files"); } if (options & BTO_STRINGMASK) /* any string options set? */ { usage_error ("bt_parse_entry: illegal options " "(string options not allowed)"); } InputFilename = filename; err_counts = bt_get_error_counts (err_counts); if (feof (infile)) { if (prev_file != NULL) /* haven't already done the cleanup */ { prev_file = NULL; finish_parse (&err_counts); } else { usage_warning ("bt_parse_entry: second attempt to read past eof"); } if (status) *status = TRUE; return NULL; } /* * Here we do some nasty poking about the innards of PCCTS in order to * enter the parser multiple times on the same input stream. This code * comes from expanding the macro invokation: * * ANTLR (entry (top), infile); * * When LL_K, ZZINF_LOOK, and DEMAND_LOOK are all undefined, this * ultimately expands to * * zzbufsize = ZZLEXBUFSIZE; * { * static char zztoktext[ZZLEXBUFSIZE]; * zzlextext = zztoktext; * zzrdstream (f); * zzgettok(); * } * entry (top); * ++zzasp; * * (I'm expanding hte zzenterANTLR, zzleaveANTLR, and zzPrimateLookAhead * macros, but leaving ZZLEXBUFSIZE -- a simple constant -- alone.) * * There are two problems with this: 1) zztoktext is a statically * allocated buffer, and when it overflows we just ignore further * characters that should belong to that lexeme; and 2) zzrdstream() and * zzgettok() are called every time we enter the parser, which means the * token left over from the previous entry will be discarded when we * parse entries 2 .. N. * * I handle the static buffer problem with alloc_lex_buffer() and * realloc_lex_buffer() (in lex_auxiliary.c), and by rewriting the ZZCOPY * macro to call realloc_lex_buffer() when overflow is detected. * * I handle the extra token-read by hanging on to a static file * pointer, prev_file, between calls to bt_parse_entry() -- when * the program starts it is NULL, and we reset it to NULL on * finishing a file. Thus, any call that is the first on a given * file will allocate the lexical buffer and read the first token; * thereafter, we skip those steps, and free the buffer on reaching * end-of-file. Currently, this method precludes interleaving * calls to bt_parse_entry() on different files -- perhaps I could * fix this with the zz{save,restore}_{antlr,dlg}_state() * functions? */ zzast_sp = ZZAST_STACKSIZE; /* workaround apparent pccts bug */ #if defined(LL_K) || defined(ZZINF_LOOK) || defined(DEMAND_LOOK) # error One of LL_K, ZZINF_LOOK, or DEMAND_LOOK was defined #endif if (prev_file == NULL) /* only read from input stream if */ { /* starting afresh with a file */ start_parse (infile, NULL, 0); prev_file = infile; } assert (prev_file == infile); entry (&entry_ast); /* enter the parser */ ++zzasp; /* why is this done? */ if (entry_ast == NULL) /* can happen with very bad input */ { if (status) *status = FALSE; return entry_ast; } #if DEBUG dump_ast ("bt_parse_entry(): single entry, after parsing:\n", entry_ast); #endif bt_postprocess_entry (entry_ast, StringOptions[entry_ast->metatype] | options); #if DEBUG dump_ast ("bt_parse_entry(): single entry, after post-processing:\n", entry_ast); #endif if (status) *status = parse_status (err_counts); return entry_ast; } /* bt_parse_entry() */