summaryrefslogtreecommitdiffstats
path: root/yql/essentials/sql/v1/ide/completion/analysis/global/parser.cpp
blob: bf91da38dca44bc7e2ad9046fceeef0813377a8d (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
#include "parser.h"

#include <yql/essentials/sql/v1/ide/completion/text/word.h>
#include <yql/essentials/sql/v1/ide/pure_ast/parser.h>

#include <util/charset/utf8.h>

namespace NSQLComplete {

namespace {

class TParser: public IParser {
public:
    explicit TParser(NSQLPureAST::IParser::TPtr parser)
        : Parser_(std::move(parser))
    {
    }

    TParsedInput Parse(TCompletionInput input) override {
        Recovered_.clear();
        if (IsRecoverable(input)) {
            Recovered_ = TString(input.Text);
            // "_" is to parse `SELECT x._ FROM table`
            //        instead of `SELECT x.FROM table`
            Recovered_.insert(input.CursorPosition, "_");
            input.Text = Recovered_;
        }

        TStringBuf prefix = TStringBuf(input.Text).Head(input.CursorPosition);
        input.CursorPosition = GetNumberOfUTF8Chars(prefix);

        NSQLPureAST::TParseTree tree = Parser_->Parse(input.Text);

        return {
            .Original = {
                .Text = tree.Text,
                .CursorPosition = input.CursorPosition,
            },
            .Tokens = tree.Tokens,
            .Parser = tree.Parser,
            .SqlQuery = tree.SqlQuery,
        };
    }

private:
    bool IsRecoverable(TCompletionInput input) const {
        TStringBuf s = input.Text;
        size_t i = input.CursorPosition;
        return (i < s.size() && IsWordBoundary(s[i]) || i == s.size());
    }

    TString Recovered_;
    NSQLPureAST::IParser::TPtr Parser_;
};

} // namespace

IParser::TPtr MakeParser(bool isAnsiLexer) {
    return MakeHolder<TParser>(NSQLPureAST::MakeParser(isAnsiLexer));
}

} // namespace NSQLComplete