loom
219 строк · 8.9 Кб
1/*
2MIT License
3
4Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
5
6https://bmstu.codes/lsx/simodo/loom
7*/
8
9/*! \file Синтаксический анализ
10*
11* Утилита синтаксического анализа текста на любом языке, заданном грамматикой на языке SIMODO fuze.
12*
13* Проект SIMODO.
14*/
15
16#include "simodo/inout/reporter/ConsoleReporter.h"
17#include "simodo/inout/convert/functions.h"
18#include "simodo/LibVersion.h"
19#include "simodo/inout/token/InputStream.h"
20#include "simodo/parser/fuze/fuze_file_extension.h"
21#include "simodo/engine/utility/grammatize.h"
22
23#include <iostream>
24#include <fstream>
25#include <memory>
26#include <algorithm>
27#include <chrono>
28
29#if __cplusplus >= __cpp_2017
30#include <filesystem>
31namespace fs = std::filesystem;
32#else
33#include <experimental/filesystem>
34namespace fs = std::filesystem::experimental;
35#endif
36
37using namespace std;
38using namespace simodo;
39
40int main(int argc, char *argv[])
41{
42vector<std::string> arguments(argv + 1, argv + argc);
43
44string json_file_name = "";
45string st_dot_file_name = "";
46string dot_file_name = "";
47string grammar_file = "";
48string grammar_builder_method_string = "";
49bool need_time_intervals = false;
50bool need_state_transitions_info = false;
51bool need_rules_info = false;
52bool need_st_info = false;
53bool error = false;
54bool help = false;
55bool version = false;
56bool need_silence = false;
57bool need_build_grammar = false;
58bool need_load_grammar = false;
59bool need_analyze_inserts= false;
60
61for(size_t i=0; i < arguments.size(); ++i)
62{
63const string & arg = arguments[i];
64
65if (arg[0] == '-')
66{
67if (arg == "--help" || arg == "-h")
68help = true;
69else if (arg == "--version" || arg == "-v")
70version = true;
71else if (arg == "--grammar-builder-method" || arg == "-z")
72{
73if (i == arguments.size()-1 || !grammar_builder_method_string.empty())
74error = true;
75else
76grammar_builder_method_string = arguments[++i];
77}
78else if (arg == "--json-semantics" || arg == "-j")
79{
80if (i == arguments.size()-1 || !json_file_name.empty())
81error = true;
82else
83json_file_name = arguments[++i];
84}
85else if (arg == "--dot-semantics" || arg == "-s")
86{
87if (i == arguments.size()-1 || !st_dot_file_name.empty())
88error = true;
89else
90st_dot_file_name = arguments[++i];
91}
92else if (arg == "--dot-grammar" || arg == "-d")
93{
94if (i == arguments.size()-1 || !st_dot_file_name.empty())
95error = true;
96else
97dot_file_name = arguments[++i];
98}
99else if (arg == "--state-transitions-info" || arg == "-i")
100need_state_transitions_info = true;
101else if (arg == "--rules-info" || arg == "-r")
102need_rules_info = true;
103else if (arg == "--insertion-info" || arg == "-o")
104need_st_info = true;
105else if (arg == "--time-intervals" || arg == "-t")
106need_time_intervals = true;
107else if (arg == "--silence" || arg == "-S")
108need_silence = true;
109else if (arg == "--dump-grammar" || arg == "-u")
110need_build_grammar = true;
111else if (arg == "--load-grammar" || arg == "-l")
112need_load_grammar = true;
113else if (arg == "--analyze-inserts" || arg == "-a")
114need_analyze_inserts = true;
115else
116error = true;
117}
118else if (grammar_file.empty())
119grammar_file = arg;
120else
121error = true;
122}
123
124parser::TableBuildMethod grammar_builder_method = parser::TableBuildMethod::LR1;
125
126if (grammar_builder_method_string == "lr" || grammar_builder_method_string == "lr1")
127grammar_builder_method = parser::TableBuildMethod::LR1; // -V1048
128else if (grammar_builder_method_string == "slr")
129grammar_builder_method = parser::TableBuildMethod::SLR;
130else if (!grammar_builder_method_string.empty()) {
131cout << "Задан недопустимый метод формирования таблицы грамматики" << endl;
132error = true;
133}
134
135if (grammar_file.empty() && !version && !help)
136error = true;
137
138if (need_load_grammar && (need_build_grammar || need_time_intervals))
139error = true;
140
141if (need_load_grammar && (!json_file_name.empty() || !st_dot_file_name.empty())) {
142cout << "Нельзя построить JSON или граф семантического дерева из загружаемой грамматики" << endl;
143error = true;
144}
145
146if (error) {
147cout << "Ошибка в параметрах запуска" << endl;
148help = true;
149}
150
151const string logo = "Утилита анализа грамматики. Проект SIMODO.";
152
153if (help)
154cout << logo << endl
155<< "Формат запуска:" << endl
156<< " simodo-grammatize [<параметры>] <файл>" << endl
157<< "Параметры:" << endl
158<< " -h | --help - отображение подсказки по запуску программы" << endl
159<< " -v | --version - отображение версии программы" << endl
160<< " -z | --grammar-builder-method <метод> - метод построения таблицы грамматики (slr,lr1)" << endl
161<< " -t | --time-intervals - отображать интервалы времени разбора" << endl
162<< " -j | --json-semantics <путь> - создать JSON-файл абстрактного дерева операционной семантики" << endl
163<< " -s | --dot-semantics <путь> - создать DOT-файл абстрактного дерева операционной семантики" << endl
164<< " -d | --dot-grammar <путь> - создать DOT-файл графа переходов состояний грамматики" << endl
165<< " -r | --rules-info - вывести перечень правил грамматики" << endl
166<< " -i | --state-transitions-info - вывести информацию о переходах состояний грамматики" << endl
167<< " -o | --insertion-info - вывести структуры семантических вставок" << endl
168<< " -S | --silence - не выводить диагностику утилиты" << endl
169<< " -u | --dump-grammar - построить и сохранить грамматику в дампе" << endl
170<< " -l | --load-grammar - загрузить грамматику из дампа" << endl
171<< " -a | --analyze-inserts - анализ вставок кода" << endl
172;
173
174if (error)
175return 1;
176
177if (version)
178cout << logo << endl
179<< "Версия: " << lib_version().major() << "." << lib_version().minor() << endl;
180
181if (grammar_file.empty())
182return 0;
183
184fs::path grammar_path = grammar_file;
185
186if (grammar_path.extension().empty())
187grammar_path += parser::FUZE_FILE_EXTENSION;
188
189std::ifstream in(grammar_path);
190
191if (!in) {
192cout << "Ошибка при открытии файла '" << grammar_path.string() << "'" << endl;
193return 1;
194}
195
196inout::InputStream in_stream(in);
197inout::ConsoleReporter m;
198parser::Grammar grammar;
199
200return engine::grammatize(
201grammar_file,
202in_stream,
203cout,
204m,
205json_file_name,
206st_dot_file_name,
207grammar_builder_method,
208dot_file_name,
209need_state_transitions_info,
210need_rules_info,
211need_st_info,
212need_time_intervals,
213need_silence,
214need_build_grammar,
215need_load_grammar,
216need_analyze_inserts,
217need_analyze_inserts,
218grammar) ? 0 : 1;
219}
220