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