1/** 2 * \file 3 * \brief Function to generate/manipulate abstract syntax tree for records. 4 */ 5 6/* 7 * Copyright (c) 2011, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <assert.h> 17 18#ifdef TEST_PARSER 19#include "../../../include/octopus/parser/ast.h" 20#else 21#include <octopus/parser/ast.h> 22#endif 23 24#include "y.tab.h" 25#include "flex.h" 26 27void free_ast(struct ast_object* p) 28{ 29 if (p == NULL) { 30 return; 31 } 32 33 switch (p->type) { 34 case nodeType_Object: 35 free_ast(p->u.on.name); 36 free_ast(p->u.on.attrs); 37 break; 38 39 case nodeType_Attribute: 40 free_ast(p->u.an.attr); 41 free_ast(p->u.an.next); 42 break; 43 44 case nodeType_String: 45 free(p->u.sn.str); 46 p->u.sn.str = NULL; 47 break; 48 49 case nodeType_Ident: 50 free(p->u.in.str); 51 p->u.in.str = NULL; 52 break; 53 54 case nodeType_Constraint: 55 free_ast(p->u.cnsn.value); 56 break; 57 58 case nodeType_Pair: 59 free_ast(p->u.pn.left); 60 free_ast(p->u.pn.right); 61 break; 62 63 case nodeType_Unset: 64 assert(!"nodeType_Unset encountered in free_ast!"); 65 abort(); 66 break; 67 68 default: 69 // Nothing special to do for value nodes 70 break; 71 } 72 73 free(p); 74} 75 76void ast_append_attribute(struct ast_object* ast, struct ast_object* to_insert) 77{ 78 struct ast_object** attr = &ast->u.on.attrs; 79 for (; *attr != NULL; attr = &(*attr)->u.an.next) { 80 // continue 81 } 82 83 struct ast_object* new_attr = ast_alloc_node(); 84 new_attr->type = nodeType_Attribute; 85 new_attr->u.an.attr = to_insert; 86 new_attr->u.an.next = NULL; 87 *attr = new_attr; 88} 89 90struct ast_object* ast_find_attribute(struct ast_object* ast, char* name) 91{ 92 struct ast_object** attr = &ast->u.on.attrs; 93 94 for (; *attr != NULL; attr = &(*attr)->u.an.next) { 95 96 assert((*attr)->type == nodeType_Attribute); 97 if (strcmp((*attr)->u.an.attr->u.pn.left->u.in.str, name) == 0) { 98 return (*attr)->u.an.attr; 99 } 100 101 } 102 103 return NULL; 104} 105 106struct ast_object* ast_remove_attribute(struct ast_object* ast, char* name) 107{ 108 struct ast_object** attr = &ast->u.on.attrs; 109 110 for (; *attr != NULL; attr = &(*attr)->u.an.next) { 111 112 assert((*attr)->type == nodeType_Attribute); 113 struct ast_object* pair = (*attr)->u.an.attr; 114 struct ast_object* left = pair->u.pn.left; 115 116 if (strcmp(left->u.in.str, name) == 0) { 117 struct ast_object* current_attr = *attr; 118 119 *attr = current_attr->u.an.next; 120 121 current_attr->u.an.next = NULL; 122 current_attr->u.an.attr = NULL; 123 free_ast(current_attr); 124 125 return pair; 126 } 127 128 } 129 130 return NULL; 131} 132 133errval_t generate_ast(const char* input, struct ast_object** record) 134{ 135 // Save re-entrant state for Flex/Bison 136 struct oct_parser_state p; 137 p.ast = NULL; 138 p.err = SYS_ERR_OK; 139 p.scanner = NULL; 140 141 struct string_buffer buf; 142 buf.ptr = NULL; 143 144 int res = octyy_lex_init_extra(&buf, &p.scanner); 145 if (res != 0) { 146 goto out; 147 } 148 149 // Run Lexer and Parser 150 octyy__scan_string(input, p.scanner); 151 res = octyy_parse((void*) &p); 152 octyy_lex_destroy(p.scanner); 153 if (res == 0) { 154 *record = p.ast; 155 p.ast = NULL; 156 return SYS_ERR_OK; 157 } 158 159 out: 160 // Memory got cleaned up by bison destructors... 161 *record = NULL; 162 return OCT_ERR_PARSER_FAIL; 163} 164