loom

Форк
0
299 строк · 9.0 Кб
1
/*
2
MIT License
3

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

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

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"
13

14
#include <fstream>
15
#include <algorithm>
16

17
namespace simodo::variable
18
{
19

20
namespace {
21

22
    class JsonAnalyzeDataBuilder_dummy : public JsonAnalyzeDataBuilder_interface
23
    {
24
    public:
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 {}
28
    };
29

30
    static JsonAnalyzeDataBuilder_dummy dummy_builder;
31
}
32

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)
37
    , _value(value)
38
{
39
    _files.push_back(json_file);
40
}
41

42
JsonRdp::JsonRdp(inout::Reporter_abstract & m, JsonAnalyzeDataBuilder_interface & builder, const std::string json_file, Value & value) 
43
    : inout::RdpBaseSugar(m,_files) 
44
    , _builder(builder)
45
    , _json_file(json_file)
46
    , _value(value)
47
{
48
    _files.push_back(json_file);
49
}
50

51
bool JsonRdp::parse() 
52
{
53
    SIMODO_INOUT_STD_IFSTREAM(in, _json_file);
54

55
    if (!in) {
56
        reporter().reportFatal(inout::fmt("Ошибка при открытии файла '%1'").arg(_json_file));
57
        return false;
58
    }
59

60
    inout::InputStream stream(in);
61

62
    return parse(stream);
63
}
64

65
bool JsonRdp::parse(inout::InputStream_interface &stream) 
66
{
67
    inout::LexicalParameters lex;
68

69
    lex.markups = {
70
        {u"\"", u"\"", u"\\", inout::LexemeType::Annotation}
71
    };
72
    lex.masks = {
73
        {inout::BUILDING_NUMBER, inout::LexemeType::Number, 10}
74
    };
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;
82

83
    _tokenizer = std::make_unique<inout::Tokenizer>(0, stream, lex);
84

85
    inout::Token t = _tokenizer->getToken();
86

87
    if (t.type() == inout::LexemeType::Empty)
88
        return true;
89

90
    parseValue(t, _value);
91

92
    return _ok;
93
}
94

95
void JsonRdp::parseValue(const inout::Token & value_token, Value & value) const
96
{
97
    if (value_token.type() == inout::LexemeType::Punctuation)
98
    {
99
        if (value_token.lexeme() == u"{") {
100
            parseObject(value_token, value);
101
            return;
102
        }
103

104
        if (value_token.lexeme() == u"[") {
105
            parseArray(value_token, value);
106
            return;
107
        }
108

109
        if (value_token.lexeme() == u"true" || value_token.lexeme() == u"false")
110
        {
111
            value = Value(value_token.lexeme() == u"true");
112
            _builder.addConst(value_token);
113
            return;
114
        }
115

116
        if (value_token.lexeme() == u"null")
117
        {
118
            value = Value();
119
            _builder.addConst(value_token);
120
            return;
121
        }
122
    }
123
    else if (value_token.type() == inout::LexemeType::Annotation)
124
    {
125
        value = Value(value_token.lexeme());
126
        _builder.addConst(value_token);
127
        return;
128
    }
129
    else if (value_token.type() == inout::LexemeType::Number)
130
    {
131
        try
132
        {
133
            if (value_token.qualification() == inout::TokenQualification::RealNumber)
134
                value = Value(stod(inout::toU8(value_token.lexeme())));
135
            else
136
                value = Value(int64_t(stol(inout::toU8(value_token.lexeme()))));
137
        }
138
        catch(const std::exception & ex)
139
        {
140
            reporter().reportError(value_token.makeLocation(files()), inout::fmt("The numeric value is formatted incorrectly"));
141
        }
142
        _builder.addConst(value_token);
143
        return;
144
    }
145

146
    _ok = reportUnexpected(value_token, inout::fmt("number, string constant, '{', '[', 'true', 'false' or 'null'"));
147

148
    // 1. Встречено , ] } - пропущено значение
149
    if (value_token.lexeme() == u"," || value_token.lexeme() == u"}" || value_token.lexeme() == u"]") {
150
        reporter().reportInformation(inout::fmt("Пропущено значение"));
151
        value = Value();
152
        return;
153
    }
154

155
    // 2. Встречено : - ?
156
    reporter().reportInformation("?");
157
    value = Value();
158
}
159

160
void JsonRdp::parseObject(const inout::Token & open_brace_token, Value & value) const
161
{
162
    VariableSet_t member_list;
163

164
    inout::Token t = _tokenizer->getToken();
165

166
    if (t.type() == inout::LexemeType::Punctuation && t.lexeme() == u"}")
167
    {
168
        value = Value(member_list);
169
        _builder.addGroup(open_brace_token, t);
170
        return;
171
    }
172

173
    while(t.type() != inout::LexemeType::Empty)
174
    {
175
        std::u16string variable_name;
176
        bool colon = true;
177
        if (t.type() != inout::LexemeType::Annotation) {
178
            _ok = reportUnexpected(t, "member name (string)");
179
            if (t.lexeme() == u":") {
180
            }
181
            else {
182
                // Восстановление после ошибки методом "паники" до символов "," и "}"
183
                t = _tokenizer->getToken();
184
                while(t.type() != inout::LexemeType::Empty && t.lexeme() != u"," && t.lexeme() != u"}")
185
                    t = _tokenizer->getToken();
186
                colon = false;
187
                if (t.type() == inout::LexemeType::Empty)
188
                    return;
189
            }
190
        }
191
        else
192
        {
193
            auto it = find_if(member_list.begin(), member_list.end(),
194
                                [t](const Variable & var)
195
                                {
196
                                    return t.lexeme() == var.name();
197
                                });
198

199
            if (it != member_list.end())
200
            {
201
                reporter().reportError(t.makeLocation(files()), 
202
                                        inout::fmt("Member '%1' is duplicated").arg(t.lexeme()));
203
            }
204
        }
205

206
        if (colon) {
207
            _builder.addVariable(t);
208
            variable_name = t.lexeme();
209
            if (t.lexeme() != u":")
210
                t = _tokenizer->getToken();
211

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)
219
                    return;
220
            }
221
            else {
222
                t = _tokenizer->getToken();
223

224
                Value variable_value;
225

226
                parseValue(t,variable_value);
227

228
                member_list.push_back(Variable {variable_name, variable_value});
229

230
                t = _tokenizer->getToken();
231
            }
232
        }
233

234
        if (t.type() == inout::LexemeType::Punctuation && t.lexeme() == u"}")
235
        {
236
            value = Value(member_list);
237
            _builder.addGroup(open_brace_token, t);
238
            return;
239
        }
240

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)
248
                return;
249
            if (t.type() == inout::LexemeType::Annotation)
250
                continue;
251
            value = Value(member_list);
252
            _builder.addGroup(open_brace_token, t);
253
            return;
254
        }
255

256
        t = _tokenizer->getToken();
257
    }
258
}
259

260
void JsonRdp::parseArray(const inout::Token & open_brace_token, Value & value) const
261
{
262
    std::vector<Value> value_list;
263

264
    inout::Token t = _tokenizer->getToken();
265

266
    if (t.type() == inout::LexemeType::Punctuation && t.lexeme() == u"]")
267
    {
268
        value = Value(value_list);
269
        _builder.addGroup(open_brace_token, t);
270
        return;
271
    }
272

273
    while(t.type() != inout::LexemeType::Empty)
274
    {
275
        Value array_element_value;
276

277
        parseValue(t,array_element_value);
278

279
        value_list.push_back(array_element_value);
280

281
        t = _tokenizer->getToken();
282

283
        if (t.type() == inout::LexemeType::Punctuation && t.lexeme() == u"]")
284
        {
285
            value = Value(value_list);
286
            _builder.addGroup(open_brace_token, t);
287
            return;
288
        }
289

290
        if (t.type() != inout::LexemeType::Punctuation || t.lexeme() != u",")
291
            break;
292

293
        t = _tokenizer->getToken();
294
    }
295

296
    _ok = reportUnexpected(t);
297
}
298

299
}

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

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

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

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