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/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"
24
#if __cplusplus >= __cpp_2017
26
namespace fs = std::filesystem;
28
#include <experimental/filesystem>
29
namespace fs = std::filesystem::experimental;
34
namespace simodo::module
38
static parser::Grammar EMPTY_GRAMMAR_TABLE;
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)
46
, _grammar_places(grammar_places)
47
, _stream_supplier(stream_supplier)
48
, _syntax_data_collector(syntax_data_collector)
52
const ast::Node * CodeSupplier::getCode(const std::string & module_name,
53
const inout::uri_set_t & files)
58
auto it = _codes.find(module_name);
59
if (it != _codes.end())
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);
67
if (grammar_file.empty()) {
68
_last_error = inout::fmt("Unable to find grammar '%1'").arg(grammar_name);
72
std::shared_ptr<inout::InputStream_interface> in = _stream_supplier.supply(module_name);
75
_last_error = inout::fmt("Unable to load file '%1'").arg(module_name);
79
inout::uri_index_t uri_index = files.empty() ? 0 : files.size()-1;
81
auto [it, success] = _codes.insert({module_name,{}});
83
bool ok = parse(files,uri_index,*in,grammar_file,it->second);
87
/// \note В случае ошибки удалять файл не нужно, иначе может быть некорректной
96
std::string CodeSupplier::findGrammarFile(const std::string & grammar_name) const
98
for(const std::string & dir_name : _grammar_places) {
99
fs::path path_to_grammar = dir_name;
101
path_to_grammar /= grammar_name + ".fuze";
103
if (fs::exists(path_to_grammar))
104
return path_to_grammar.string();
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,
116
/// \todo Необходимо сделать приём константной ссылки на грамматику
117
/// + поправить конструктор parser::PushdownAutomaton
118
parser::Grammar g = getGrammarTable(grammar_file);
122
std::string file_name = uri_index < files.size() ? files[uri_index] : "?";
124
variable::VariableSet_t hosts = interpret::loadSemanticOperationsEnums(fs::path(grammar_file).parent_path().string());
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);
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
/// \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);
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);
196
parser::saveGrammarDump(grammar_file,grammar_table);
198
auto [it, ok] = _grammar_tables.insert({grammar_file,grammar_table});
199
return ok ? it->second : EMPTY_GRAMMAR_TABLE;
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)
208
interpret::Interpret inter(interpret::InterpretType::Preview, _m, _loom, fuze_files, fuze_code,
210
new interpret::builtins::FuzeRunning(
217
_loom.stretch(&inter);
220
grammar_table.files = fuze_files;
222
return !inter.errors();