loom

Форк
0
/
CodeSupplier.cpp 
225 строк · 8.7 Кб
1
/*
2
MIT License
3

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

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

9
#include "simodo/module/CodeSupplier.h"
10

11
#include "simodo/ast/generator/FormationFlow.h"
12
#include "simodo/parser/fuze/FuzeRdp.h"
13
#include "simodo/parser/automaton/PushdownAutomaton.h"
14
#include "simodo/interpret/Interpret.h"
15
#include "simodo/interpret/SemanticOperationsEnumsLoader.h"
16
#include "simodo/interpret/builtins/hosts/fuze/FuzeRunning.h"
17
#include "simodo/interpret/builtins/hosts/base/BaseRunning.h"
18
#include "simodo/interpret/builtins/modules/LexicalParametersModule.h"
19
#include "simodo/interpret/builtins/modules/AstFormationModule.h"
20
#include "simodo/interpret/builtins/AstFormationBuilder.h"
21
#include "simodo/inout/convert/functions.h"
22
#include "simodo/inout/format/fmt.h"
23

24
#if __cplusplus >= __cpp_2017
25
#include <filesystem>
26
namespace fs = std::filesystem;
27
#else
28
#include <experimental/filesystem>
29
namespace fs = std::filesystem::experimental;
30
#endif
31

32
#include <cassert>
33

34
namespace simodo::module
35
{
36
    namespace 
37
    {
38
        static parser::Grammar EMPTY_GRAMMAR_TABLE;
39
    }
40

41
    CodeSupplier::CodeSupplier( inout::Reporter_abstract & m,
42
                                 std::vector<std::string> grammar_places,
43
                                 inout::InputStreamSupplier_interface & stream_supplier,
44
                                 parser::SyntaxDataCollector_interface & syntax_data_collector)
45
        : _m(m)
46
        , _grammar_places(grammar_places)
47
        , _stream_supplier(stream_supplier)
48
        , _syntax_data_collector(syntax_data_collector)
49
    {
50
    }
51

52
    const ast::Node * CodeSupplier::getCode(const std::string & module_name,
53
                                            const inout::uri_set_t & files)
54
    {
55
        _last_error = {};
56
        
57
        {
58
            auto it = _codes.find(module_name);
59
            if (it != _codes.end())
60
                return &(it->second);
61
        }
62

63
        fs::path    path_to_module = module_name;
64
        std::string grammar_name   = path_to_module.extension().string().substr(1);
65
        std::string grammar_file   = findGrammarFile(grammar_name);
66

67
        if (grammar_file.empty()) {
68
            _last_error = inout::fmt("Unable to find grammar '%1'").arg(grammar_name);
69
            return nullptr;
70
        }
71

72
        std::shared_ptr<inout::InputStream_interface> in = _stream_supplier.supply(module_name);
73

74
        if (!in) {
75
            _last_error = inout::fmt("Unable to load file '%1'").arg(module_name);
76
            return nullptr;
77
        }
78

79
        inout::uri_index_t uri_index = files.empty() ? 0 : files.size()-1;
80

81
        auto [it, success] = _codes.insert({module_name,{}});
82
        
83
        bool ok = parse(files,uri_index,*in,grammar_file,it->second);
84

85
        if (!ok) {
86
            _codes.erase(it);
87
            /// \note В случае ошибки удалять файл не нужно, иначе может быть некорректной 
88
            /// диагностика.
89
            // files.pop_back();
90
            return nullptr;
91
        }
92

93
        return &(it->second);
94
    }
95

96
    std::string CodeSupplier::findGrammarFile(const std::string & grammar_name) const
97
    {
98
        for(const std::string & dir_name : _grammar_places) {
99
            fs::path    path_to_grammar = dir_name;
100

101
            path_to_grammar /= grammar_name + ".fuze"; 
102

103
            if (fs::exists(path_to_grammar)) 
104
                return path_to_grammar.string();
105
        }
106

107
        return {};
108
    }
109

110
    bool CodeSupplier::parse( const inout::uri_set_t & files,
111
                              inout::uri_index_t uri_index, 
112
                              inout::InputStream_interface & stream, 
113
                              const std::string & grammar_file, 
114
                              ast::Node & code)
115
    {
116
        /// \todo Необходимо сделать приём константной ссылки на грамматику 
117
        /// + поправить конструктор parser::PushdownAutomaton
118
        parser::Grammar g = getGrammarTable(grammar_file);
119
        if (g.rules.empty())
120
            return false;
121

122
        std::string file_name = uri_index < files.size() ? files[uri_index] : "?";
123

124
        variable::VariableSet_t hosts = interpret::loadSemanticOperationsEnums(fs::path(grammar_file).parent_path().string());
125

126
        ast::Node                       null_node;
127
        interpret::Interpret            inter(interpret::InterpretType::Preview, _m, _loom, {file_name}, null_node);
128
        interpret::builtins::BaseInterpret_abstract * 
129
                                        sbl = new interpret::builtins::BaseRunning(&inter);
130
        interpret::builtins::AstFormationBuilder  
131
                                        builder(_m,*sbl,hosts,_syntax_data_collector);
132
        parser::PushdownAutomaton       parser(_m, g, files, builder);
133

134
        inter.instantiateSemantics({sbl});
135

136
        if (!parser.parse(stream))
137
            return false;
138

139
        const_cast<ast::Node &>(builder.ast().tree().root()).swap(code);
140
        return true;
141
    }
142

143
    const parser::Grammar & CodeSupplier::getGrammarTable(const std::string & grammar_file)
144
    {
145
        {
146
            const auto it = _grammar_tables.find(grammar_file);
147
            if (it != _grammar_tables.end())
148
                return it->second;
149
        }
150

151
        parser::Grammar     grammar_table;
152

153
        if (parser::loadGrammarDump(grammar_file,grammar_table)) {
154
            auto [it, ok] = _grammar_tables.insert({grammar_file,grammar_table});
155
            return ok ? it->second : EMPTY_GRAMMAR_TABLE;
156
        }
157

158
        ast::FormationFlow  flow;
159
        parser::FuzeRdp     fuze(_m, grammar_file, flow);
160
        
161
        if (!fuze.parse())
162
            return EMPTY_GRAMMAR_TABLE;
163

164
        if (!buildGrammarTable(fs::path(grammar_file).stem().string(),
165
                               flow.tree().files(), 
166
                               flow.tree().root(),
167
                               parser::TableBuildMethod::SLR,
168
                               grammar_table)) {
169
            if (!buildGrammarTable(fs::path(grammar_file).stem().string(),
170
                                   flow.tree().files(), 
171
                                   flow.tree().root(),
172
                                   parser::TableBuildMethod::LR1,
173
                                   grammar_table))
174
                return EMPTY_GRAMMAR_TABLE;
175
        }
176

177
        for(const auto & [name, node] : grammar_table.handlers)
178
            /// \todo Для работы с грамматикой ode используется вставка кода "on_Start"
179
            /// Нужно будет её тоже прогонять!
180
            if (name == u"lex") {
181
                interpret::Interpret *  inter   = new interpret::Interpret(interpret::InterpretType::Preview, _m, _loom, flow.tree().files(), node);
182
                interpret::builtins::BaseRunning *   
183
                                    lex_runner  = new interpret::builtins::BaseRunning(inter);
184
                std::shared_ptr<interpret::builtins::LexicalParametersModule> 
185
                                    lex         = std::make_shared<interpret::builtins::LexicalParametersModule>(
186
                                                                                            grammar_table.lexical);
187

188
                lex_runner->importNamespace(u"lex", lex->instantiate(lex), inout::null_token_location);
189
                inter->instantiateSemantics({lex_runner});
190
                _loom.dock(inter, true);
191
                _loom.stretch(inter);
192
            }
193

194
        _loom.finish();
195

196
        parser::saveGrammarDump(grammar_file,grammar_table);
197

198
        auto [it, ok] = _grammar_tables.insert({grammar_file,grammar_table});
199
        return ok ? it->second : EMPTY_GRAMMAR_TABLE;
200
    }
201

202
    bool CodeSupplier::buildGrammarTable(const std::string & grammar_name,
203
                                          const inout::uri_set_t & fuze_files, 
204
                                          const ast::Node & fuze_code, 
205
                                          parser::TableBuildMethod method,
206
                                          parser::Grammar & grammar_table)
207
    {
208
        interpret::Interpret    inter(interpret::InterpretType::Preview, _m, _loom, fuze_files, fuze_code,
209
                                    {
210
                                        new interpret::builtins::FuzeRunning(
211
                                                &inter,
212
                                                grammar_name,
213
                                                grammar_table,
214
                                                method),
215
                                    });
216

217
        _loom.stretch(&inter);
218
        _loom.finish();
219

220
        grammar_table.files = fuze_files;
221

222
        return !inter.errors();
223
    }
224

225
}
226

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

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

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

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