summaryrefslogtreecommitdiffstats
path: root/src/ast.c
blob: 2ba1e7dee51db55d18220bc0ef1f95d07bf81a9b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "ast.h"
#include "common.h"

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>


CcmmcAst *ccmmc_ast_new(CcmmcAstNodeType type_node, size_t line_number)
{
    CcmmcAst *node;
    node = malloc(sizeof(CcmmcAst));
    ERR_FATAL_CHECK(node, malloc);
    node->parent = NULL;
    node->child = NULL;
    // Notice that leftmostSibling is not initialized as NULL
    node->leftmost_sibling = node;
    node->right_sibling = NULL;
    node->type_node = type_node;
    node->type_value = CCMMC_AST_VALUE_NONE;
    node->line_number = line_number;
    return node;
}

CcmmcAst *ccmmc_ast_append_sibling(CcmmcAst *node, CcmmcAst *sibling)
{
    while (node->right_sibling)
        node = node->right_sibling;
    if (sibling == NULL)
        return node;
    sibling = sibling->leftmost_sibling;
    node->right_sibling = sibling;

    sibling->leftmost_sibling = node->leftmost_sibling;
    sibling->parent = node->parent;
    while (sibling->right_sibling) {
        sibling = sibling->right_sibling;
        sibling->leftmost_sibling = node->leftmost_sibling;
        sibling->parent = node->parent;
    }
    return sibling;
}

CcmmcAst *ccmmc_ast_append_child(CcmmcAst *parent, CcmmcAst *child)
{
    if (child == NULL)
        return parent;
    if (parent->child) {
        ccmmc_ast_append_sibling(parent->child, child);
    } else {
        child = child->leftmost_sibling;
        parent->child = child;
        while (child) {
            child->parent = parent;
            child = child->right_sibling;
        }
    }
    return parent;
}

CcmmcAst *ccmmc_ast_append_children(
    CcmmcAst *parent, size_t children_count, ...)
{
    va_list children_list;
    va_start(children_list, children_count);
    CcmmcAst *child = va_arg(children_list, CcmmcAst*);
    ccmmc_ast_append_child(parent, child);
    CcmmcAst *tmp = child;
    for (size_t index = 1; index < children_count; ++index) {
        child = va_arg(children_list, CcmmcAst*);
        tmp = ccmmc_ast_append_sibling(tmp, child);
    }
    va_end(children_list);
    return parent;
}

CcmmcAst *ccmmc_ast_new_id(char *lexeme, CcmmcKindId kind, size_t line_number)
{
    CcmmcAst *node = ccmmc_ast_new(CCMMC_AST_NODE_ID, line_number);
    node->value_id.kind = kind;
    node->value_id.name = lexeme;
    // node->value_id.symbolTableEntry = NULL;
    return node;
}

CcmmcAst *ccmmc_ast_new_stmt(CcmmcKindStmt kind, size_t line_number)
{
    CcmmcAst *node = ccmmc_ast_new(CCMMC_AST_NODE_STMT, line_number);
    node->value_stmt.kind = kind;
    return node;
}

CcmmcAst *ccmmc_ast_new_decl(CcmmcKindDecl kind, size_t line_number)
{
    CcmmcAst *node = ccmmc_ast_new(CCMMC_AST_NODE_DECL, line_number);
    node->value_decl.kind = kind;
    return node;
}

CcmmcAst *ccmmc_ast_new_expr(CcmmcKindExpr kind, int op_kind, size_t line_number)
{
    CcmmcAst *node = ccmmc_ast_new(CCMMC_AST_NODE_EXPR, line_number);
    node->value_expr.kind = kind;
    node->value_expr.is_const_eval = false;
    if (kind == CCMMC_KIND_EXPR_BINARY_OP)
        node->value_expr.op_binary = op_kind;
    else if (kind == CCMMC_KIND_EXPR_UNARY_OP)
        node->value_expr.op_unary = op_kind;
    else
        fprintf(stderr, "%s: invalid expression kind in %s\n", prog_name, __func__);
    return node;
}

// vim: set sw=4 ts=4 sts=4 et: