4
Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
6
https://bmstu.codes/lsx/simodo/stars
9
#include "simodo/module/CodeSupplier.h"
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/SemanticOperationsEnumsLoader.h"
15
#include "simodo/interpret/builtins/hosts/fuze/FuzeRunning.h"
16
#include "simodo/interpret/builtins/hosts/base/BaseRunning.h"
17
#include "simodo/interpret/builtins/modules/LexicalParametersModule.h"
18
#include "simodo/interpret/builtins/modules/AstFormationModule.h"
19
#include "simodo/interpret/builtins/AstFormationBuilder.h"
20
#include "simodo/inout/convert/functions.h"
21
#include "simodo/inout/format/fmt.h"
25
#if __cplusplus >= __cpp_2017
27
namespace fs = std::filesystem;
29
#include <experimental/filesystem>
30
namespace fs = std::filesystem::experimental;
33
namespace simodo::module
37
static parser::Grammar EMPTY_GRAMMAR_TABLE;
40
CodeSupplier::CodeSupplier( inout::Reporter_abstract & m,
41
std::vector<std::string> grammar_places,
42
inout::InputStreamSupplier_interface & stream_supplier,
43
interpret::InterpretFactory_interface & interpret_factory,
44
parser::SyntaxDataCollector_interface & syntax_data_collector)
46
, _grammar_places(grammar_places)
47
, _stream_supplier(stream_supplier)
48
, _interpret_factory(interpret_factory)
49
, _syntax_data_collector(syntax_data_collector)
53
const ast::Node * CodeSupplier::getCode(const std::string & module_name,
54
const inout::uri_set_t & files)
57
auto it = _codes.find(module_name);
58
if (it != _codes.end())
62
fs::path path_to_module = module_name;
63
std::string grammar_name = path_to_module.extension().string().substr(1);
64
std::string grammar_file = findGrammarFile(grammar_name);
66
if (grammar_file.empty()) {
67
_m.reportFatal(inout::fmt("Unable to find grammar '%1'").arg(grammar_name));
71
std::shared_ptr<inout::InputStream_interface> in = _stream_supplier.supply(module_name);
74
_m.reportFatal(inout::fmt("Unable to load file '%1'").arg(module_name));
78
inout::uri_index_t uri_index = files.empty() ? 0 : files.size()-1;
80
auto [it, success] = _codes.insert({module_name,{}});
82
bool ok = parse(files,uri_index,*in,grammar_file,it->second);
86
/// \note В случае ошибки удалять файл не нужно, иначе может быть некорректной
95
std::string CodeSupplier::findGrammarFile(const std::string & grammar_name) const
97
for(const std::string & dir_name : _grammar_places) {
98
fs::path path_to_grammar = dir_name;
100
path_to_grammar /= grammar_name + ".fuze";
102
if (fs::exists(path_to_grammar))
103
return path_to_grammar.string();
109
bool CodeSupplier::parse( const inout::uri_set_t & files,
110
inout::uri_index_t uri_index,
111
inout::InputStream_interface & stream,
112
const std::string & grammar_file,
115
/// \todo Необходимо сделать приём константной ссылки на грамматику
116
/// + поправить конструктор parser::PushdownAutomaton
117
parser::Grammar g = getGrammarTable(grammar_file);
121
std::string file_name = uri_index < files.size() ? files[uri_index] : "?";
123
variable::VariableSet_t hosts = interpret::loadSemanticOperationsEnums(fs::path(grammar_file).parent_path().string());
126
std::unique_ptr<interpret::Interpret_interface>
127
inter(_interpret_factory.create(interpret::InterpretType::Preview, {file_name}, null_node));
128
interpret::builtins::BaseInterpret_abstract *
129
sbl = new interpret::builtins::BaseRunning(inter.get());
130
interpret::builtins::AstFormationBuilder
131
builder(_m,*sbl,hosts,_syntax_data_collector);
132
parser::PushdownAutomaton parser(_m, g, files, builder);
134
inter->instantiateSemantics({sbl});
136
if (!parser.parse(stream))
139
const_cast<ast::Node &>(builder.ast().tree().root()).swap(code);
143
const parser::Grammar & CodeSupplier::getGrammarTable(const std::string & grammar_file)
146
const auto it = _grammar_tables.find(grammar_file);
147
if (it != _grammar_tables.end())
151
parser::Grammar grammar_table;
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;
158
ast::FormationFlow flow;
159
parser::FuzeRdp fuze(_m, grammar_file, flow);
162
return EMPTY_GRAMMAR_TABLE;
164
if (!buildGrammarTable(fs::path(grammar_file).stem().string(),
167
parser::TableBuildMethod::SLR,
169
if (!buildGrammarTable(fs::path(grammar_file).stem().string(),
172
parser::TableBuildMethod::LR1,
174
return EMPTY_GRAMMAR_TABLE;
177
for(const auto & [name, node] : grammar_table.handlers)
178
if (name == u"lex") {
179
interpret::Interpret_interface *
180
inter = _interpret_factory.create(interpret::InterpretType::Preview, flow.tree().files(), node);
181
interpret::builtins::BaseRunning *
182
lex_runner = new interpret::builtins::BaseRunning(inter);
183
std::shared_ptr<interpret::builtins::LexicalParametersModule>
184
lex = std::make_shared<interpret::builtins::LexicalParametersModule>(
185
grammar_table.lexical);
187
/// \todo Пересмотреть странную передачу самого себя в свой же метод.
188
/// PVS Studio: warn V678 An object is used as an argument to its own method.
189
/// Consider checking the first actual argument of the 'instantiate' function.
190
lex_runner->importNamespace(u"lex", lex->instantiate(lex), inout::null_token_location);
191
inter->instantiateSemantics({lex_runner});
192
_loom.dock(inter, true);
193
_loom.stretch(inter);
195
/// \todo Фетисов 2024-07-19. Можно удалить через 3-4 месяца.
197
// interpret::Interpret_interface *
198
// inter = _interpret_factory.create(interpret::InterpretType::Preview, _m, _loom, flow.tree().files(), node);
199
// interpret::builtins::BaseRunning *
200
// runner = new interpret::builtins::BaseRunning(inter);
201
// std::shared_ptr<interpret::builtins::AstFormationModule>
202
// ast = std::make_shared<interpret::builtins::AstFormationModule>();
204
// /// \todo Пересмотреть странную передачу самого себя в свой же метод.
205
// /// PVS Studio: warn V678 An object is used as an argument to its own method.
206
// /// Consider checking the first actual argument of the 'instantiate' function.
207
// runner->importNamespace(u"ast", ast->instantiate(ast), inout::null_token_location);
208
// inter->instantiateSemantics({runner});
209
// _loom.dock(inter, true);
210
// _loom.stretch(inter);
215
parser::saveGrammarDump(grammar_file,grammar_table);
217
auto [it, ok] = _grammar_tables.insert({grammar_file,grammar_table});
218
return ok ? it->second : EMPTY_GRAMMAR_TABLE;
221
bool CodeSupplier::buildGrammarTable(const std::string & grammar_name,
222
const inout::uri_set_t & fuze_files,
223
const ast::Node & fuze_code,
224
parser::TableBuildMethod method,
225
parser::Grammar & grammar_table)
227
std::unique_ptr<interpret::Interpret_interface>
228
inter(_interpret_factory.create(interpret::InterpretType::Preview, fuze_files, fuze_code));
231
inter->instantiateSemantics({new interpret::builtins::FuzeRunning(
238
_loom.stretch(inter.get());
241
grammar_table.files = fuze_files;
243
return !inter->errors();