aboutsummaryrefslogtreecommitdiff
path: root/include/lexer/ast.h
blob: 59c1e4b832235c2daa43ef517347d382fa5c937a (plain)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

#pragma once

#include <string>

#include "lexer/enum_type.h"
#include "lexer/token.h"
#include "lexer/shared.h"

using namespace std; // remove this

namespace ov4
{

class T_token;

class T_ast
{
public:
    T_ast() = default;

    enum_token_type token_type;
    string command_text;
    size_t left = string::npos;
    size_t right = string::npos;
};

string final_trim(size_t _begin, size_t _end)
{
    string s;
    for (size_t i = _begin; i < _end; i++)
    {
        if (token[i].token_type != TEXT)
            continue;
        s += token[i].text + " ";
    }
    s = s.substr(0, s.size()-1); // eat final space
    return s;
}

size_t alloc_ast()
{
    ast.emplace_back();
    return ast_index++;
}

int get_pivot_order(enum_token_type x)
{
    switch(x)
    {
        case ASYNC:
        case SEMICOLON:
            return 1000;
        
        case LOGIC_AND:
        case LOGIC_OR:
            return 500;

        case PIPE:
            return 100;
            
        default:
            return 0;
    }
    return 0;
}

bool is_operator(enum_token_type x)
{
    switch(x)
    {
        case LOGIC_AND:
        case LOGIC_OR:
        case PIPE:
        case ASYNC:
            return true;
        default:
            return false;
    }
}

// region [begin, end)
void parse(size_t cmd_begin, size_t cmd_end, size_t ast_vec)
{
    int current_depth = 0;
    int current_order = -1;
    int max_depth = -1;
    size_t found_pos = string::npos;

    for (size_t i = cmd_begin; i < cmd_end; i++)
    {
        if (token[i].bracket_depth > max_depth)
            max_depth = token[i].bracket_depth;
    }


    while (found_pos == string::npos)
    {
        // scan from right to left
        for (size_t i = cmd_end - 1; i >= cmd_begin && i < cmd_end; i--)
        {
            // if same depth
            // and higher order number
            if (token[i].bracket_depth == current_depth 
                && is_operator(token[i].token_type) 
                && get_pivot_order(token[i].token_type) > current_order)
            {
                current_order =  get_pivot_order(token[i].token_type);
                found_pos = i;
                println("Found pos: {} order: {} depth: {}", i, current_order, current_depth);
            }
        }
        current_depth++;
        if (current_depth > max_depth)
        {
            break;
        }
    }

    if (found_pos == string::npos)
    {
        println("Smallest unit");
        ast[ast_vec].token_type = TEXT;
        ast[ast_vec].command_text = final_trim(cmd_begin, cmd_end);
        return;
    }

    size_t l = alloc_ast();
    size_t r = alloc_ast();
    ast[ast_vec].left = l;
    ast[ast_vec].right = r;
    ast[ast_vec].token_type = token[found_pos].token_type;

    println("Parse sub: {}, {}, {}", cmd_begin, found_pos, cmd_end);

    parse(cmd_begin, found_pos, l);
    parse(found_pos+1, cmd_end, r);
}

}