summaryrefslogtreecommitdiffstats
path: root/yql/essentials/tools/yql_highlight/generator_highlight_js.cpp
blob: d8673a24601d3b3d493dbd7ca1b87e8ad0f95466 (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
#include "generator_highlight_js.h"

#include "json.h"
#include "highlighting.h"

#include <contrib/libs/re2/re2/re2.h>
#include <util/string/builder.h>

namespace NSQLHighlight {

    TString ToHighlightJSClass(EUnitKind kind) {
        switch (kind) {
            case EUnitKind::Keyword:
                return "keyword";
            case EUnitKind::Punctuation:
                return "punctuation";
            case EUnitKind::QuotedIdentifier:
                return "symbol";
            case EUnitKind::BindParameterIdentifier:
                return "variable";
            case EUnitKind::TypeIdentifier:
                return "type";
            case EUnitKind::FunctionIdentifier:
                return "title.function";
            case EUnitKind::Identifier:
                return "";
            case EUnitKind::Literal:
                return "number";
            case EUnitKind::StringLiteral:
                return "string";
            case EUnitKind::Comment:
                return "comment";
            case EUnitKind::Whitespace:
                return "";
            case EUnitKind::Error:
                return "";
        }
    }

    // FIXME: copy-pasted from generator_textmate.cpp.
    TString ToTextMateRegex(const TUnit& unit, const NSQLTranslationV1::TRegexPattern& pattern) {
        TStringBuilder regex;

        if (unit.IsPlain) {
            regex << R"re(\b)re";
        }

        if (!pattern.Before.empty()) {
            regex << "(?<=" << pattern.Before << ")";
        }

        regex << "(" << pattern.Body << ")";

        if (!pattern.After.empty()) {
            regex << "(?=" << pattern.After << ")";
        }

        if (unit.IsPlain) {
            regex << R"re(\b)re";
        }

        return regex;
    }

    NJson::TJsonValue ToHighlightJSPattern(const TUnit& unit, const NSQLTranslationV1::TRegexPattern& pattern) {
        NJson::TJsonMap json;
        json["className"] = ToHighlightJSClass(unit.Kind);
        json["begin"] = ToTextMateRegex(unit, pattern);
        return json;
    }

    NJson::TJsonValue ToHighlightJSPattern(const TUnit& unit, const TRangePattern& pattern) {
        NJson::TJsonMap json;
        json["className"] = ToHighlightJSClass(unit.Kind);
        json["begin"] = RE2::QuoteMeta(pattern.Begin);
        json["end"] = RE2::QuoteMeta(pattern.End);
        return json;
    }

    NJson::TJsonValue ToHighlightJSContains(const THighlighting& highlighting) {
        NJson::TJsonArray array;

        for (const TUnit& unit : highlighting.Units) {
            if (unit.IsCodeGenExcluded || unit.Kind == EUnitKind::Identifier) {
                continue;
            }

            for (const NSQLTranslationV1::TRegexPattern& pattern : unit.Patterns) {
                array.AppendValue(ToHighlightJSPattern(unit, pattern));
            }
            if (auto range = unit.RangePattern) {
                array.AppendValue(ToHighlightJSPattern(unit, *range));
            }
        }

        return array;
    }

    NJson::TJsonValue ToHighlightJSON(const THighlighting& highlighting) {
        NJson::TJsonMap json;
        json["name"] = highlighting.Name;
        json["case_insensitive"] = IsCaseInsensitive(highlighting);
        json["contains"] = NJson::TJsonArray{{NJson::TJsonMap{
            {"begin", ""},
            {"end", ";"},
            {"endsWithParent", true},
            {"lexemes", R"re(\w+)re"},
            {"contains", ToHighlightJSContains(highlighting)},
        }}};
        return json;
    }

    void GenerateHighlightJS(IOutputStream& out, const THighlighting& highlighting, bool /* ansi */) {
        Print(out, ToHighlightJSON(highlighting));
    }

    IGenerator::TPtr MakeHighlightJSGenerator() {
        return MakeOnlyFileGenerator(GenerateHighlightJS);
    }

} // namespace NSQLHighlight