builder_t* builder_create(const char* description) { if(description == NULL) return NULL; source_t* source = source_open_string(description); symtab_t* symtab = symtab_new(); ast_t* ast = build_ast(source, symtab); if(ast == NULL) { // Error, tidy up source_close(source); symtab_free(symtab); return NULL; } // Success, create builder builder_t* builder = POOL_ALLOC(builder_t); builder->sources = NULL; builder->defs = symtab; builder->dummy_root = ast_blank(TK_TEST); ast_add(builder->dummy_root, ast); add_source(builder, source); return builder; }
void build_ast(node *root){ if(root==NULL) return; if(strcmp(root->str_type,"FuncDefinition")==0) go_to_funcbody(root); build_ast(root->brother); }
static ast_t* builder_add_ast(builder_t* builder, const char* description) { assert(builder != NULL); assert(description != NULL); source_t* source = source_open_string(description); ast_t* ast = build_ast(source, builder->defs); if(ast == NULL) { // Error, tidy up source_close(source); return NULL; } // Success, add new source to builder add_source(builder, source); return ast; }
int parse(char *file) { token *tokens[MAX_TOKEN_NUM]; ast *syntax_tree; int token_count = tokenise(file, tokens); if (tokens == NULL) { fprintf(stderr, "Couldn't read file: %s\n", file); return -1; } show_tokens(tokens, token_count); build_ast(tokens, syntax_tree); if (syntax_tree == NULL) { fprintf(stderr, "Couldn't parse file: %s\n", file); return -1; } pretty_print_ast(syntax_tree); return 0; }
AST *build_ast (lexer *lex) { /* TODO: Implement me. */ /* Hint: switch statements are pretty cool, and they work * brilliantly with enums. */ if (lex) { AST *ast = safe_malloc(sizeof(AST)); token_type ast_type; char *ast_val; read_token(lex); if (peek_type(lex) == token_CLOSE_PAREN) { num_paren--; if (num_paren < 0) { fatal_error("Extra close parenthesis"); } else { return NULL; } } else if (peek_type(lex) == token_END) { if (num_paren != 0) { fatal_error("Uneven number of parenthesis"); } else { return NULL; } } else if (peek_type(lex) == token_OPEN_PAREN) { AST *struct_num; // for when we get a node_STRUCT num_paren++; read_token(lex); ast_type = peek_type(lex); ast_val = peek_value(lex); if (ast_type == token_CLOSE_PAREN) { fatal_error("Empty pair of parenthesis"); } else if (ast_type == token_NAME) { //any variable name that comes after ( will be a function call ast->type = node_CALL; } else if (ast_type == token_KEYWORD) { // if it's a keyword, use smap if (!strcmp(ast_val,"None")) { ast->type = node_INT; ast_val = "0"; } else { ast->type = lookup_keyword_enum(ast_val); if (ast->type == node_STRUCT) { struct_num = safe_malloc(sizeof(AST)); struct_num->type = node_STRING; struct_num->children = NULL; struct_num->last_child = NULL; struct_num->val = safe_malloc(8*sizeof(char)); sprintf(struct_num->val,"struct%d",num_structs); num_structs++; } } } else if (ast_type == token_INT || ast_type == token_STRING) { fatal_error("INT/STRING lone in parenthesis"); } else if (ast_type == token_OPEN_PAREN) { fatal_error("Two consecutive open parenthesis"); } else if (ast_type == token_END) { fatal_error("Abrupt end after open parenthesis"); } ast->val = safe_malloc((strlen(ast_val) + 1) * sizeof(char)); strcpy(ast->val, ast_val); ast->children = safe_malloc(sizeof(AST_lst)); AST_lst *children = ast->children; // somewhere here fit the struct_num child in!! if (ast->type == node_STRUCT) { ast->last_child = children; children->val = struct_num; children->next = safe_malloc(sizeof(AST_lst)); children = children->next; } AST *temp = build_ast(lex); if (temp == NULL && ast->type != node_STRUCT) { ast->children = NULL; ast->last_child = NULL; } else { while (temp != NULL) { ast->last_child = children; children->val = temp; children->next = safe_malloc(sizeof(AST_lst)); children = children->next; temp = build_ast(lex); } (ast->last_child)->next = NULL; } free(children);// free next of last child for which we malloced space earlier, thinking there existed a next. if (ast->type == node_FUNCTION) { ((ast->children)->val)->type = node_VAR; smap_put(num_args,((ast->children)->val)->val,AST_lst_len(((ast->children)->val)->children)); } } else { ast_type = peek_type(lex); ast_val = peek_value(lex); if (ast_type == token_NAME) { ast->type = node_VAR; } else if (ast_type == token_KEYWORD) { if (!strcmp(ast_val,"None")) { ast->type = node_INT; ast_val = "0"; } else { ast->type = lookup_keyword_enum(ast_val); } } ast->val = safe_malloc((strlen(ast_val) + 1) * sizeof(char)); strcpy(ast->val, ast_val); ast->children = NULL; ast->last_child = NULL; } switch (ast_type) { case token_INT: ast->type = node_INT; break; case token_STRING: ast->type = node_STRING; break; } return ast; } return NULL; }
//main function - call with the name of the AST input file int main(int argc, char **argv) { //generate the array of quads (okay we have a limit of 10,000 - we really don't think people //in C48 will get beyond this using our compiler - consider it a "compiler limit" quads = calloc(10000, sizeof(Quad *)); //CODE FROM THC's ast.c if (argc != 2) { fprintf(stderr, "Usage: %s input_file\n", argv[0]); return -1; } ast_node root; printf("Building AST\n"); root = build_ast(argv[1]); /* build an abstract syntax tree */ printf("Printing AST\n"); print_ast(root, 0); /* and print it out */ printf("Creating Symbol Table\n"); //OUR CODE AGAIN //create symbol table symtab = CreateSymbolTable(); //now we call CG of the root node InsertIntoSymbolTable(symtab, "dog"); printf("Calling CG on root node\n"); CG(root); //print all of our quads for debug purposes int i = 0; //char a1[5]; //char a2[5]; //char a3[5]; printf("Entering Debug Printing While Loop - we have %d quads and they are:\n", currentQuad); FILE *qfile; qfile = fopen("quadsout.txt","w"); while(quads[i] != NULL) { char* a1 = malloc(sizeof(char) * 15); char* a2 = malloc(sizeof(char) * 15); char* a3 = malloc(sizeof(char) * 15); printf("Printing quad %d", i); //printf("entered while\n"); switch (quads[i]->addr1.kind) { case Empty: a1 = " - "; break; case IntConst: sprintf(a1,"%d",quads[i]->addr1.contents.val); break; case DouConst: sprintf(a1,"%f",quads[i]->addr1.contents.dval); break; case String: //printf("%s", quads[i]->addr1.contents.name); a1 = quads[i]->addr1.contents.name; //printf("%s", a1); break; default: break; } switch (quads[i]->addr2.kind) { case Empty: a2 = " - "; break; case IntConst: sprintf(a2,"%d",quads[i]->addr2.contents.val); break; case DouConst: sprintf(a2,"%f",quads[i]->addr2.contents.dval); break; case String: //printf("%s", quads[i]->addr2.contents.name); a2 = quads[i]->addr2.contents.name; break; default: break; } switch (quads[i]->addr3.kind) { case Empty: a3 = " - "; break; case IntConst: sprintf(a3,"%d",quads[i]->addr3.contents.val); break; case DouConst: sprintf(a3,"%f",quads[i]->addr3.contents.dval); break; case String: //printf("%s", quads[i]->addr3.contents.name); a3 = quads[i]->addr3.contents.name; break; default: break; } //printf("Finished switches, printing quad details\n"); //printf("%s",a1); //printf("%s",a2); //printf("%s",a3); printf("(%s,%s,%s,%s)\n",namesOfOps[quads[i]->op],a1,a2,a3); fprintf(qfile, "(%s,%s,%s,%s)\n",namesOfOps[quads[i]->op],a1,a2,a3); i++; } fclose(qfile); /* EnterScope(symtab); EnterScope(symtab); char *c = malloc(sizeof(char) *5); c = "a"; printf("before segfault?\n"); SymNode *sn = LookupInSymbolTable(symtab, c); printf("%d the offset of a is\n", GetOffsetAttr(sn)); */ if(DOASSEMBLY) { //File for final assembly output FILE *file; file = fopen("tm48code.txt","w"); //Send over to the assembly generator, the quads array and symbol table AssemblyGen(quads, file, symtab); fclose(file); } return 0; }