loom

Форк
0
231 строка · 7.9 Кб
1
/*
2
MIT License
3

4
Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
5

6
https://bmstu.codes/lsx/simodo/loom
7
*/
8

9
#include "simodo/variable/Module_interface.h"
10
#include "simodo/variable/VariableSetWrapper.h"
11
#include "simodo/variable/json/Serialization.h"
12
#include "simodo/inout/convert/functions.h"
13
#include "simodo/inout/reporter/Reporter_abstract.h"
14
#include "simodo/inout/token/Tokenizer.h"
15
#include "simodo/inout/token/RefBufferStream.h"
16
#include "simodo/variable/json/LexicalParametersLoader.h"
17

18
#include <memory>
19
#include <filesystem>
20
#include <cassert>
21

22
#ifdef CROSS_WIN
23
// MinGW related workaround
24
#define BOOST_DLL_FORCE_ALIAS_INSTANTIATION
25
#endif
26

27
#include <boost/dll/alias.hpp>
28

29
using namespace simodo;
30
using namespace simodo::variable;
31
using namespace simodo::inout;
32

33
namespace fs = std::filesystem;
34

35
namespace
36
{
37
    Value setup(Module_interface * host, const VariableSetWrapper & args);
38
    Value symbols(Module_interface * host, const VariableSetWrapper & args);
39
    Value comments(Module_interface * host, const VariableSetWrapper & args);
40
    Value produceTokens(Module_interface * host, const VariableSetWrapper & args);
41
}
42

43
class MainTokenizer : public Module_interface
44
{
45
    // ModuleFactory_interface *   _factory;
46
    LexicalParameters           _lexis;
47
    bool                        _lexis_ok = false;
48

49
public:
50
    // MainTokenizer(ModuleFactory_interface * factory) : _factory(factory) {}
51

52
    Value setup(const std::string & path_to_data, const std::string & language);
53
    Value symbols();
54
    Value comments();
55
    Value produceTokens(const std::u16string & text_to_parse, int position, context_index_t context);
56

57
    virtual version_t version() const override { return lib_version(); }
58

59
    virtual Value instantiate(std::shared_ptr<variable::Module_interface> module_object) override
60
    {
61
        return {{
62
            // {u"version", u"0.1"},
63
            {u"priority", 0},
64
            {u"setup", {ValueType::Function, Object {{
65
                {u"@", ExternalFunction {module_object, ::setup}},
66
                {{}, ValueType::String},
67
                {u"path_to_data", ValueType::String},
68
                {u"language", ValueType::String},
69
            }}}},
70
            {u"symbols", {ValueType::Function, Object {{
71
                {u"@", ExternalFunction {module_object, ::symbols}},
72
                {{}, ValueType::Array},
73
            }}}},
74
            {u"comments", {ValueType::Function, Object {{
75
                {u"@", ExternalFunction {module_object, ::comments}},
76
                {{}, ValueType::Array},
77
            }}}},
78
            {u"produceTokens", {ValueType::Function, Object {{
79
                {u"@", ExternalFunction {module_object, ::produceTokens}},
80
                {{}, ValueType::Object},
81
                {u"text_to_parse", ValueType::String},
82
                {u"position", ValueType::Int},
83
                {u"context", ValueType::Int},
84
            }}}},
85
        }};
86
    }
87

88
    // Factory method
89
    static std::shared_ptr<Module_interface> create() {
90
        return std::make_shared<MainTokenizer>();
91
    }
92
};
93

94
BOOST_DLL_ALIAS(
95
    MainTokenizer::create,    // <-- this function is exported with...
96
    create_simodo_module      // <-- ...this alias name
97
)
98

99
namespace
100
{
101
    Value setup(Module_interface * host, const VariableSetWrapper & args)
102
    {
103
        // Эти условия должны проверяться в вызывающем коде и при необходимости выполняться преобразования
104
        assert(host != nullptr);
105
        assert(args.size() == 2);
106
        assert(args[0].value().type() == ValueType::String);
107
        assert(args[1].value().type() == ValueType::String);
108

109
        MainTokenizer * main = static_cast<MainTokenizer *>(host);
110
        return main->setup(toU8(args[0].value().getString()),
111
                           toU8(args[1].value().getString()));
112
    }
113

114
    Value symbols(Module_interface * host, const VariableSetWrapper & )
115
    {
116
        // Эти условия должны проверяться в вызывающем коде и при необходимости выполняться преобразования
117
        assert(host != nullptr);
118

119
        MainTokenizer * main = static_cast<MainTokenizer *>(host);
120
        return main->symbols();
121
    }
122

123
    Value comments(Module_interface * host, const VariableSetWrapper & )
124
    {
125
        // Эти условия должны проверяться в вызывающем коде и при необходимости выполняться преобразования
126
        assert(host != nullptr);
127

128
        MainTokenizer * main = static_cast<MainTokenizer *>(host);
129
        return main->comments();
130
    }
131

132
    Value produceTokens(Module_interface * host, const VariableSetWrapper & args)
133
    {
134
        // Эти условия должны проверяться в вызывающем коде и при необходимости выполняться преобразования
135
        assert(host != nullptr);
136
        assert(args.size() == 3);
137
        assert(args[0].value().type() == ValueType::String);
138
        assert(args[1].value().type() == ValueType::Int);
139
        assert(args[2].value().type() == ValueType::Int);
140

141
        MainTokenizer *        main = static_cast<MainTokenizer *>(host);
142
        context_index_t context = NO_TOKEN_CONTEXT_INDEX;
143
        if (args[2].value().getInt() >= 0 )
144
            context = static_cast<context_index_t>(args[2].value().getInt());
145

146
        return main->produceTokens(args[0].value().getString(), args[1].value().getInt(), context);
147
    }
148

149
}
150

151
Value MainTokenizer::setup(const std::string & path_to_data, const std::string & language)
152
{
153
    fs::path path_to_lexis = path_to_data;
154
    path_to_lexis /= "lexis/" + language + ".json";
155

156
    if (!fs::exists(path_to_lexis))
157
        return u"Lexical data for " + toU16(language) + u" not found";
158

159
    _lexis_ok = loadLexicalParameters(path_to_lexis.string(), _lexis);
160
    if (!_lexis_ok)
161
        return u"Unable to load file '" + toU16(path_to_lexis.string()) + u"'";
162

163
    return u"";
164
}
165

166
Value MainTokenizer::symbols()
167
{
168
    std::vector<variable::Value> result;
169

170
    result.reserve(_lexis.punctuation_words.size());
171

172
    for(const std::u16string & s : _lexis.punctuation_words)
173
        result.push_back(Object {{
174
                {u"symbol",   s},
175
                {u"type",     u"Keyword"},
176
            }});
177

178
    return result;
179
}
180

181
Value MainTokenizer::comments()
182
{
183
    std::vector<variable::Value> result; 
184

185
    for(auto & m : _lexis.markups)
186
        if (m.type == LexemeType::Comment && m.end.empty()) {
187
            result.push_back(m.start);
188
            break;
189
        }
190

191
    for(auto & m : _lexis.markups)
192
        if (m.type == LexemeType::Comment && !m.end.empty()) {
193
            result.push_back(m.start);
194
            result.push_back(m.end);
195
            break;
196
        }
197

198
    return result;
199
}
200

201
Value MainTokenizer::produceTokens(const std::u16string & text_to_parse, int position, context_index_t context)
202
{
203
    if (!_lexis_ok)
204
        return Object {};
205

206
    RefBufferStream stream(text_to_parse.data());
207
    Tokenizer       tokenizer(0, stream, _lexis, context);
208
    Token           t = tokenizer.getAnyToken();
209
    Array           tokens;
210

211
    context = t.context();
212
    while(t.type() != LexemeType::Empty) {
213
        const char * type = t.qualification() != TokenQualification::None
214
                                ? getQualificationName(t.qualification())
215
                                : getLexemeTypeName(t.type());
216
        Object token_data {{
217
            {u"token",    t.token()},
218
            {u"lexeme",   t.lexeme()},
219
            {u"type",     inout::toU16(type)},
220
            {u"position", position + static_cast<int64_t>(t.location().range().start().character())},
221
            }};
222
        tokens.add(token_data);
223
        context = t.context();
224
        t = tokenizer.getAnyToken();
225
    }
226

227
    return Object {{
228
        {u"tokens",  tokens},
229
        {u"context", static_cast<int64_t>(context == NO_TOKEN_CONTEXT_INDEX ? -1 : context)}
230
        }};
231
}
232

233

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.