loom

Форк
0
/
FuzeInterpret_abstract.cpp 
308 строк · 11.1 Кб
1
/*
2
MIT License
3

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

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

9
#include "simodo/interpret/builtins/hosts/fuze/FuzeInterpret_abstract.h"
10
#include "simodo/interpret/builtins/hosts/fuze/ParsingTableBuilder_LR1.h"
11
#include "simodo/interpret/builtins/hosts/fuze/ParsingTableBuilder_SLR.h"
12

13
#include "simodo/interpret/AnalyzeException.h"
14
#include "simodo/parser/fuze/fuze_keywords.h"
15
#include "simodo/ast/NodeFriend.h"
16

17
#include <cassert>
18

19
namespace simodo::interpret::builtins
20
{
21

22
FuzeInterpret_abstract::FuzeInterpret_abstract(Interpret_interface * inter, 
23
                                               std::string grammar_name,
24
                                               parser::Grammar & grammar,
25
                                               parser::TableBuildMethod method,
26
                                               bool need_strict_rule_consistency)
27
    : _interpret(inter)
28
    , _grammar_name(grammar_name)
29
    , _grammar(grammar)
30
    , _method(method)
31
    , _need_strict_rule_consistency(need_strict_rule_consistency)
32
    , _main_rule(inout::null_token)
33
{
34
    assert(inter);
35
}
36

37
void FuzeInterpret_abstract::reset()
38
{
39
}
40

41
bool FuzeInterpret_abstract::isOperationExists(ast::OperationCode inner_operation_code) const
42
{
43
    parser::FuzeOperationCode operation_code = static_cast<parser::FuzeOperationCode>(inner_operation_code);
44

45
    switch(operation_code)
46
    {
47
    case parser::FuzeOperationCode::None:
48
    case parser::FuzeOperationCode::Main:
49
    case parser::FuzeOperationCode::GlobalScript:
50
    case parser::FuzeOperationCode::Production:
51
    case parser::FuzeOperationCode::RemoveProduction:
52
    case parser::FuzeOperationCode::Reference:
53
        return true;
54
    default:
55
        break;
56
    }
57

58
    return false;
59
}
60

61
InterpretState FuzeInterpret_abstract::performOperation(const ast::Node & op) 
62
{
63
    parser::FuzeOperationCode operation_code = static_cast<parser::FuzeOperationCode>(op.operation());
64

65
    switch(operation_code)
66
    {
67
    case parser::FuzeOperationCode::None:
68
        return InterpretState::Flow;
69

70
    case parser::FuzeOperationCode::Main:
71
        return parseMain(op);
72

73
    case parser::FuzeOperationCode::GlobalScript:
74
        return parseGlobalScript(op);
75

76
    case parser::FuzeOperationCode::Production:
77
        return parseProduction(op);
78

79
    case parser::FuzeOperationCode::RemoveProduction:
80
        return parseProduction(op, ProductionForWhat::Removing);
81

82
    case parser::FuzeOperationCode::Reference:
83
        return parseRef(op);
84

85
    default:
86
        break;
87
    }
88

89
    throw bormental::DrBormental("FuzeInterpret_abstract::performOperation", 
90
                "Invalid operation index " + std::to_string(static_cast<size_t>(op.operation())));
91
}
92

93
InterpretState FuzeInterpret_abstract::before_finish(InterpretState state)
94
{
95
    return executeFinal(state);
96
}
97

98
InterpretState FuzeInterpret_abstract::parseMain(const ast::Node & op)
99
{
100
    return executeMain(op.token());
101
}
102

103
InterpretState FuzeInterpret_abstract::parseGlobalScript(const ast::Node & op)
104
{
105
    if (op.branches().empty())
106
        throw bormental::DrBormental("FuzeInterpret_abstract::parseGlobalScript", "Wrong operation structure");
107

108
    return executeGlobalScript(op.token(), op.branches().front());
109
}
110

111
InterpretState FuzeInterpret_abstract::parseProduction(const ast::Node & op, ProductionForWhat what)
112
{
113
    std::vector<inout::Token>   pattern;
114
    inout::Token                direction_token = inout::null_token;
115
    ast::Node                   action;
116

117
    for(const ast::Node & production_node : op.branches()) {
118
        parser::FuzeOperationCode operation_code = static_cast<parser::FuzeOperationCode>(production_node.operation());
119

120
        switch(operation_code) {
121
        case parser::FuzeOperationCode::Production_Pattern:
122
            for(const ast::Node & pattern_node : production_node.branches()) {
123
                // pattern.push_back(pattern_node.operation_symbol());
124

125
                inout::LexemeType      type    = inout::LexemeType::Empty;
126
                const inout::Token &   token = pattern_node.token();
127

128
                if (token.type() == inout::LexemeType::Annotation)
129
                    type = inout::LexemeType::Punctuation;
130
                else if (token.type() == inout::LexemeType::Id)
131
                    type = inout::LexemeType::Compound;
132
                else if (token.type() == inout::LexemeType::Punctuation) {
133
                    if (token.qualification() == inout::TokenQualification::Keyword) {
134
                        if (token.lexeme() == parser::ANNOTATION_STRING)
135
                            type = inout::LexemeType::Annotation;
136
                        else if (token.lexeme() == parser::NUMBER_STRING)
137
                            type = inout::LexemeType::Number;
138
                        else if (token.lexeme() == parser::ID_STRING)
139
                            type = inout::LexemeType::Id;
140
                        else
141
                            throw bormental::DrBormental("FuzeInterpret_abstract::parseProduction", "Wrong operation structure");
142
                    }
143
                    else
144
                        throw bormental::DrBormental("FuzeInterpret_abstract::parseProduction", "Wrong operation structure");
145
                }
146
                else
147
                    throw bormental::DrBormental("FuzeInterpret_abstract::parseProduction", "Wrong operation structure");
148

149
                pattern.push_back(inout::Token { {token.lexeme(), type}, token.token(), token.location() });
150
            }
151
            break;
152

153
        case parser::FuzeOperationCode::Production_Direction: 
154
            direction_token = production_node.token();
155
            break;
156

157
        case parser::FuzeOperationCode::Production_Script:
158
            if (!action.branches().empty() || production_node.branches().empty())
159
                throw bormental::DrBormental("FuzeInterpret_abstract::parseProduction", "Wrong operation structure");
160
            action = production_node.branches().front();
161
            break;
162

163
        default:
164
            throw bormental::DrBormental("FuzeInterpret_abstract::parseProduction", "Wrong operation code");
165
        }
166
    }
167

168
    if (what == ProductionForWhat::Adding)
169
        return executeProduction(op.token(), pattern, direction_token, action);
170

171
    return executeRemovingProduction(op.token(), pattern, action);
172
}
173

174
InterpretState FuzeInterpret_abstract::parseRef(const ast::Node & op)
175
{
176
    if (op.branches().empty())
177
        throw bormental::DrBormental("FuzeInterpret_abstract::parseRef", "Wrong operation structure");
178

179
    return executeRef(op.token(), op.branches().front().token().lexeme());
180
}
181

182
InterpretState FuzeInterpret_abstract::executeMain(const inout::Token & main_production)
183
{
184
    if (_main_rule.lexeme().empty())
185
        _main_rule = main_production;
186
        
187
    return InterpretState::Flow;
188
}
189

190
InterpretState FuzeInterpret_abstract::executeGlobalScript(const inout::Token & label, const ast::Node & script)
191
{
192
    auto it = _grammar.handlers.find(label.lexeme()); 
193

194
    if (it != _grammar.handlers.end())
195
        ast::NodeFriend::insertBranchBegin( it->second, script.branches() );
196
    else
197
        _grammar.handlers.insert({label.lexeme(), script});
198

199
    return InterpretState::Flow;
200
}
201

202
InterpretState FuzeInterpret_abstract::executeProduction(const inout::Token & production, 
203
                                            const std::vector<inout::Token> & pattern, 
204
                                            const inout::Token & direction_token,
205
                                            const ast::Node & action)
206
{
207
    if (pattern.empty())
208
        throw AnalyzeException("FuzeInterpret_abstract::executeProduction", 
209
                                production.makeLocation(_interpret->files()),
210
                                "The right side of the rule cannot be empty");
211

212
    parser::RuleReduceDirection direction = parser::RuleReduceDirection::Undefined;   
213

214
    if (direction_token.type() != inout::LexemeType::Empty)
215
        direction = (direction_token.lexeme() == u"<") 
216
                    ? parser::RuleReduceDirection::LeftAssociative 
217
                    : parser::RuleReduceDirection::RightAssociative;
218

219
    _rules.push_back({production, pattern, action, direction});
220

221
    return InterpretState::Flow;
222
}
223

224
InterpretState FuzeInterpret_abstract::executeRemovingProduction(const inout::Token & production, 
225
                                            const std::vector<inout::Token> & pattern,
226
                                            const ast::Node & action)
227
{
228
    if (pattern.empty())
229
        throw AnalyzeException("FuzeInterpret_abstract::executeRemoveProduction", 
230
                                production.makeLocation(_interpret->files()),
231
                                "The right side of the rule cannot be empty");
232

233
    if (!action.branches().empty())
234
        throw AnalyzeException("FuzeInterpret_abstract::executeRemoveProduction", 
235
                                production.makeLocation(_interpret->files()),
236
                                "When deleting products, you do not need to specify an action");
237

238
    size_t rule_index = findRule(_rules, production, pattern);
239

240
    if (rule_index < _rules.size())
241
        _rules.erase(_rules.begin()+rule_index);
242
    else
243
        throw AnalyzeException("FuzeInterpret_abstract::executeRemoveProduction", 
244
                                production.makeLocation(_interpret->files()),
245
                                "The specified rule was not found among the previously defined rules");
246

247
    return InterpretState::Flow;
248
}
249

250
InterpretState FuzeInterpret_abstract::executeRef(const inout::Token & , const std::u16string & )
251
{
252
    return InterpretState::Flow;
253
}
254

255
InterpretState FuzeInterpret_abstract::executeFinal(InterpretState state)
256
{
257
    if (state != InterpretState::Flow || _rules.empty())
258
        return state;
259

260
    // Строим таблицу
261

262
    std::unique_ptr<ParsingTableBuilder_abstract>  builder;
263

264
    if (_method == parser::TableBuildMethod::SLR)
265
        builder = std::make_unique<ParsingTableBuilder_SLR>(
266
                        _interpret->files(), 
267
                        _interpret->reporter(), 
268
                        _grammar_name, 
269
                        _grammar, 
270
                        _need_strict_rule_consistency);
271
    else
272
        builder = std::make_unique<ParsingTableBuilder_LR1>(
273
                        _interpret->files(), 
274
                        _interpret->reporter(), 
275
                        _grammar_name, 
276
                        _grammar, 
277
                        _need_strict_rule_consistency);
278

279
    if (!builder->build(_rules, _main_rule)) 
280
        return InterpretState::Complete;
281

282
    return InterpretState::Flow;
283
}
284

285
size_t FuzeInterpret_abstract::findRule(const std::vector<parser::GrammarRuleTokens> & rules, const inout::Token &production, const std::vector<inout::Token> &pattern)
286
{
287
    size_t i = 0;
288
    for(; i < rules.size(); ++i) {
289
        const parser::GrammarRuleTokens & r = rules[i];
290

291
        if (r.production.lexeme() != production.lexeme() || r.pattern.size() != pattern.size()) {
292
            continue;
293
        }
294

295
        size_t j = 0;
296
        for(; j < r.pattern.size(); ++j)
297
            if (r.pattern[j].token() != pattern[j].token()) {
298
                break;
299
            }
300

301
        if (j == r.pattern.size()) {
302
            break;
303
        }
304
    }
305

306
    return i;
307
}
308
}

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

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

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

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