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; }
void text_op_transform2(text_op *result, text_op *op, text_op *other, bool isLefthand) { init_op(result); if (op->components == NULL && op->content.type == NONE) { return; } op_iter iter = {}; text_op_component *other_components = other->components; size_t num_other_components; text_op_component inline_components[2]; if (other_components == NULL) { other_components = inline_components; if (other->content.type == NONE) { num_other_components = 0; } else if (other->skip == 0) { num_other_components = 1; inline_components[0] = other->content; } else { num_other_components = 2; inline_components[0].type = SKIP; inline_components[0].num = other->skip; inline_components[1] = other->content; } } else { num_other_components = other->num_components; } for (int i = 0; i < num_other_components; i++) { if (peek_type(op, iter) == NONE) { break; } switch (other_components[i].type) { case SKIP: { size_t num = other_components[i].num; while (num > 0) { text_op_component c = take(op, &iter, num, INSERT); if (c.type == NONE) { break; } append(result, c); if (c.type != INSERT) { num -= c.num; } } break; } case INSERT: { // If isLeftHand and there's an insert next in the current op, the insert should go first. if (isLefthand && peek_type(op, iter) == INSERT) { // The left insert goes first. append(result, take(op, &iter, SIZE_MAX, NONE)); } if (peek_type(op, iter) == NONE) { break; } text_op_component skip = {SKIP}; skip.num = str_num_chars(&other_components[i].str); append(result, skip); break; } case DELETE: { size_t num = other_components[i].num; while (num > 0) { text_op_component c = take(op, &iter, num, INSERT); switch (c.type) { case NONE: num = 0; break; case SKIP: num -= c.num; break; case INSERT: append(result, c); break; case DELETE: // The delete is unnecessary now. num -= c.num; break; } } break; } default: assert(0); } } while (iter.idx < (op->components ? op->num_components : 2)) { // The op doesn't have skips at the end. Just copy everything. append(result, take(op, &iter, SIZE_MAX, NONE)); } // Trim any trailing skips from the result. if (result->components) { while (result->num_components && result->components[result->num_components - 1].type == SKIP) { result->num_components--; } } }