aboutsummaryrefslogtreecommitdiffstats
path: root/yql/essentials/sql/v1/complete/syntax/parser_call_stack.cpp
blob: 03e07181a0dcfc7ebd8c9fead1e1ea681a830be8 (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
119
120
121
122
123
124
125
126
127
128
129
130
#include "parser_call_stack.h"

#include "grammar.h"

#include <util/generic/vector.h>
#include <util/generic/algorithm.h>
#include <util/generic/yexception.h>

#include <ranges>

#define DEBUG_SYMBOLIZE_STACK(stack) \
    auto debug_symbolized_##stack = Symbolized(stack)

namespace NSQLComplete {

    const TVector<TRuleId> PreferredRules = {
        RULE(Keyword),
        RULE(Keyword_expr_uncompat),
        RULE(Keyword_table_uncompat),
        RULE(Keyword_select_uncompat),
        RULE(Keyword_alter_uncompat),
        RULE(Keyword_in_uncompat),
        RULE(Keyword_window_uncompat),
        RULE(Keyword_hint_uncompat),
        RULE(Keyword_as_compat),
        RULE(Keyword_compat),
        RULE(Type_id),

        RULE(An_id_or_type),
        RULE(An_id),
        RULE(Id_expr),
        RULE(Id_or_type),
        RULE(Id_hint),
        RULE(Opt_id_prefix_or_type),
        RULE(Type_name_simple),
    };

    TVector<std::string> Symbolized(const TParserCallStack& stack) {
        const ISqlGrammar& grammar = GetSqlGrammar();

        TVector<std::string> symbolized;
        symbolized.reserve(stack.size());
        for (const TRuleId& rule : stack) {
            symbolized.emplace_back(grammar.SymbolizedRule(rule));
        }
        return symbolized;
    }

    bool EndsWith(const TParserCallStack& suffix, const TParserCallStack& stack) {
        if (stack.size() < suffix.size()) {
            return false;
        }
        const size_t prefixSize = stack.size() - suffix.size();
        return Equal(std::begin(stack) + prefixSize, std::end(stack), std::begin(suffix));
    }

    bool Contains(const TParserCallStack& sequence, const TParserCallStack& stack) {
        return !std::ranges::search(stack, sequence).empty();
    }

    bool ContainsRule(TRuleId rule, const TParserCallStack& stack) {
        return Find(stack, rule) != std::end(stack);
    }

    bool IsLikelyPragmaStack(const TParserCallStack& stack) {
        return EndsWith({RULE(Pragma_stmt), RULE(Opt_id_prefix_or_type)}, stack) ||
               EndsWith({RULE(Pragma_stmt), RULE(An_id)}, stack);
    }

    bool IsLikelyTypeStack(const TParserCallStack& stack) {
        return EndsWith({RULE(Type_name_simple)}, stack) ||
               (Contains({RULE(Invoke_expr),
                          RULE(Named_expr_list),
                          RULE(Named_expr),
                          RULE(Expr)}, stack) &&
                EndsWith({RULE(Atom_expr), RULE(An_id_or_type)}, stack));
    }

    bool IsLikelyFunctionStack(const TParserCallStack& stack) {
        return EndsWith({RULE(Unary_casual_subexpr), RULE(Id_expr)}, stack) ||
               EndsWith({RULE(Unary_casual_subexpr),
                         RULE(Atom_expr),
                         RULE(An_id_or_type)}, stack) ||
               EndsWith({RULE(Atom_expr), RULE(Id_or_type)}, stack);
    }

    bool IsLikelyHintStack(const TParserCallStack& stack) {
        return ContainsRule(RULE(Id_hint), stack) ||
               Contains({RULE(External_call_param), RULE(An_id)}, stack);
    }

    bool IsLikelyObjectRefStack(const TParserCallStack& stack) {
        return Contains({RULE(Object_ref)}, stack);
    }

    bool IsLikelyExistingTableStack(const TParserCallStack& stack) {
        return !Contains({RULE(Create_table_stmt),
                          RULE(Simple_table_ref)}, stack) &&
               (Contains({RULE(Simple_table_ref),
                          RULE(Simple_table_ref_core),
                          RULE(Object_ref)}, stack) ||
                Contains({RULE(Single_source),
                          RULE(Table_ref),
                          RULE(Table_key),
                          RULE(Id_table_or_type)}, stack));
    }

    bool IsLikelyClusterStack(const TParserCallStack& stack) {
        return Contains({RULE(Cluster_expr)}, stack);
    }

    TMaybe<EStatementKind> StatementKindOf(const TParserCallStack& stack) {
        for (TRuleId rule : std::ranges::views::reverse(stack)) {
            if (rule == RULE(Process_core) || rule == RULE(Reduce_core) || rule == RULE(Select_core)) {
                return EStatementKind::Select;
            }
            if (rule == RULE(Into_table_stmt)) {
                return EStatementKind::Insert;
            }
        }
        return Nothing();
    }

    std::unordered_set<TRuleId> GetC3PreferredRules() {
        std::unordered_set<TRuleId> preferredRules;
        preferredRules.insert(std::begin(PreferredRules), std::end(PreferredRules));
        return preferredRules;
    }

} // namespace NSQLComplete