4
Copyright (c) 2021 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
6
https://bmstu.codes/lsx/simodo
9
#include "simodo/variable/json/parser/JsonRdp.h"
10
#include "simodo/inout/convert/functions.h"
11
#include "simodo/inout/token/FileStream.h"
12
#include "simodo/inout/format/fmt.h"
17
namespace simodo::variable
22
class JsonAnalyzeDataBuilder_dummy : public JsonAnalyzeDataBuilder_interface
25
virtual void addGroup(const inout::Token & , const inout::Token & ) override {}
26
virtual void addVariable(const inout::Token & ) override {}
27
virtual void addConst(const inout::Token & ) override {}
30
static JsonAnalyzeDataBuilder_dummy dummy_builder;
33
JsonRdp::JsonRdp(inout::Reporter_abstract & m, const std::string json_file, Value & value)
34
: inout::RdpBaseSugar(m,_files)
35
, _builder(dummy_builder)
36
, _json_file(json_file)
39
_files.push_back(json_file);
42
JsonRdp::JsonRdp(inout::Reporter_abstract & m, JsonAnalyzeDataBuilder_interface & builder, const std::string json_file, Value & value)
43
: inout::RdpBaseSugar(m,_files)
45
, _json_file(json_file)
48
_files.push_back(json_file);
53
SIMODO_INOUT_STD_IFSTREAM(in, _json_file);
56
reporter().reportFatal(inout::fmt("Ошибка при открытии файла '%1'").arg(_json_file));
60
inout::InputStream stream(in);
65
bool JsonRdp::parse(inout::InputStream_interface &stream)
67
inout::LexicalParameters lex;
70
{u"\"", u"\"", u"\\", inout::LexemeType::Annotation}
73
{inout::BUILDING_NUMBER, inout::LexemeType::Number, 10}
75
lex.punctuation_chars = u"{}[],:";
76
lex.punctuation_words = {u"true", u"false", u"null"};
77
lex.national_alphabet = u"";
78
lex.id_extra_symbols = u"_";
79
lex.may_national_letters_use = false;
80
lex.may_national_letters_mix = false;
81
lex.is_case_sensitive = true; // -V1048
83
_tokenizer = std::make_unique<inout::Tokenizer>(0, stream, lex);
85
inout::Token t = _tokenizer->getToken();
87
if (t.type() == inout::LexemeType::Empty)
90
parseValue(t, _value);
95
void JsonRdp::parseValue(const inout::Token & value_token, Value & value) const
97
if (value_token.type() == inout::LexemeType::Punctuation)
99
if (value_token.lexeme() == u"{") {
100
parseObject(value_token, value);
104
if (value_token.lexeme() == u"[") {
105
parseArray(value_token, value);
109
if (value_token.lexeme() == u"true" || value_token.lexeme() == u"false")
111
value = Value(value_token.lexeme() == u"true");
112
_builder.addConst(value_token);
116
if (value_token.lexeme() == u"null")
119
_builder.addConst(value_token);
123
else if (value_token.type() == inout::LexemeType::Annotation)
125
value = Value(value_token.lexeme());
126
_builder.addConst(value_token);
129
else if (value_token.type() == inout::LexemeType::Number)
133
if (value_token.qualification() == inout::TokenQualification::RealNumber)
134
value = Value(stod(inout::toU8(value_token.lexeme())));
136
value = Value(int64_t(stol(inout::toU8(value_token.lexeme()))));
138
catch(const std::exception & ex)
140
reporter().reportError(value_token.makeLocation(files()), inout::fmt("The numeric value is formatted incorrectly"));
142
_builder.addConst(value_token);
146
_ok = reportUnexpected(value_token, inout::fmt("number, string constant, '{', '[', 'true', 'false' or 'null'"));
148
// 1. Встречено , ] } - пропущено значение
149
if (value_token.lexeme() == u"," || value_token.lexeme() == u"}" || value_token.lexeme() == u"]") {
150
reporter().reportInformation(inout::fmt("Пропущено значение"));
155
// 2. Встречено : - ?
156
reporter().reportInformation("?");
160
void JsonRdp::parseObject(const inout::Token & open_brace_token, Value & value) const
162
VariableSet_t member_list;
164
inout::Token t = _tokenizer->getToken();
166
if (t.type() == inout::LexemeType::Punctuation && t.lexeme() == u"}")
168
value = Value(member_list);
169
_builder.addGroup(open_brace_token, t);
173
while(t.type() != inout::LexemeType::Empty)
175
std::u16string variable_name;
177
if (t.type() != inout::LexemeType::Annotation) {
178
_ok = reportUnexpected(t, "member name (string)");
179
if (t.lexeme() == u":") {
182
// Восстановление после ошибки методом "паники" до символов "," и "}"
183
t = _tokenizer->getToken();
184
while(t.type() != inout::LexemeType::Empty && t.lexeme() != u"," && t.lexeme() != u"}")
185
t = _tokenizer->getToken();
187
if (t.type() == inout::LexemeType::Empty)
193
auto it = find_if(member_list.begin(), member_list.end(),
194
[t](const Variable & var)
196
return t.lexeme() == var.name();
199
if (it != member_list.end())
201
reporter().reportError(t.makeLocation(files()),
202
inout::fmt("Member '%1' is duplicated").arg(t.lexeme()));
207
_builder.addVariable(t);
208
variable_name = t.lexeme();
209
if (t.lexeme() != u":")
210
t = _tokenizer->getToken();
212
if (t.type() != inout::LexemeType::Punctuation || t.lexeme() != u":") {
213
_ok = reportUnexpected(t, ":");
214
// Восстановление после ошибки методом "паники" до символов "," и "}"
215
t = _tokenizer->getToken();
216
while(t.type() != inout::LexemeType::Empty && t.lexeme() != u"," && t.lexeme() != u"}")
217
t = _tokenizer->getToken();
218
if (t.type() == inout::LexemeType::Empty)
222
t = _tokenizer->getToken();
224
Value variable_value;
226
parseValue(t,variable_value);
228
member_list.push_back(Variable {variable_name, variable_value});
230
t = _tokenizer->getToken();
234
if (t.type() == inout::LexemeType::Punctuation && t.lexeme() == u"}")
236
value = Value(member_list);
237
_builder.addGroup(open_brace_token, t);
241
if (t.type() != inout::LexemeType::Punctuation || t.lexeme() != u",") {
242
_ok = reportUnexpected(t, ",");
243
// Восстановление после ошибки методом "паники" до символов СТРОКОВАЯ_КОНСТАНТА и "}"
244
t = _tokenizer->getToken();
245
while(t.type() != inout::LexemeType::Empty && t.type() != inout::LexemeType::Annotation && t.lexeme() != u"}")
246
t = _tokenizer->getToken();
247
if (t.type() == inout::LexemeType::Empty)
249
if (t.type() == inout::LexemeType::Annotation)
251
value = Value(member_list);
252
_builder.addGroup(open_brace_token, t);
256
t = _tokenizer->getToken();
260
void JsonRdp::parseArray(const inout::Token & open_brace_token, Value & value) const
262
std::vector<Value> value_list;
264
inout::Token t = _tokenizer->getToken();
266
if (t.type() == inout::LexemeType::Punctuation && t.lexeme() == u"]")
268
value = Value(value_list);
269
_builder.addGroup(open_brace_token, t);
273
while(t.type() != inout::LexemeType::Empty)
275
Value array_element_value;
277
parseValue(t,array_element_value);
279
value_list.push_back(array_element_value);
281
t = _tokenizer->getToken();
283
if (t.type() == inout::LexemeType::Punctuation && t.lexeme() == u"]")
285
value = Value(value_list);
286
_builder.addGroup(open_brace_token, t);
290
if (t.type() != inout::LexemeType::Punctuation || t.lexeme() != u",")
293
t = _tokenizer->getToken();
296
_ok = reportUnexpected(t);