loom

Форк
0
/
FuzeInterpret_abstract.cpp 
306 строк · 12.0 Кб
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
    FuzeInterpret_abstract::FuzeInterpret_abstract(Interpret_interface * inter, 
22
                                                std::string grammar_name,
23
                                                parser::Grammar & grammar,
24
                                                parser::TableBuildMethod method,
25
                                                bool need_strict_rule_consistency)
26
        : _interpret(inter)
27
        , _grammar_name(grammar_name)
28
        , _grammar(grammar)
29
        , _method(method)
30
        , _need_strict_rule_consistency(need_strict_rule_consistency)
31
        , _main_rule(inout::null_token)
32
    {
33
    }
34

35
    void FuzeInterpret_abstract::reset()
36
    {
37
    }
38

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

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

56
        return false;
57
    }
58

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

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

68
        case parser::FuzeOperationCode::Main:
69
            return parseMain(op);
70

71
        case parser::FuzeOperationCode::GlobalScript:
72
            return parseGlobalScript(op);
73

74
        case parser::FuzeOperationCode::Production:
75
            return parseProduction(op);
76

77
        case parser::FuzeOperationCode::RemoveProduction:
78
            return parseProduction(op, ProductionForWhat::Removing);
79

80
        case parser::FuzeOperationCode::Reference:
81
            return parseRef(op);
82

83
        default:
84
            break;
85
        }
86

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

91
    InterpretState FuzeInterpret_abstract::before_finish(InterpretState state)
92
    {
93
        return executeFinal(state);
94
    }
95

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

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

106
        return executeGlobalScript(op.token(), op.branches().front());
107
    }
108

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

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

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

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

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

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

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

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

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

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

169
        return executeRemovingProduction(op.token(), pattern, action);
170
    }
171

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

177
        return executeRef(op.token(), op.branches().front().token().lexeme());
178
    }
179

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

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

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

197
        return InterpretState::Flow;
198
    }
199

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

210
        parser::RuleReduceDirection direction = parser::RuleReduceDirection::Undefined;   
211

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

217
        _rules.push_back({production, pattern, action, direction});
218

219
        return InterpretState::Flow;
220
    }
221

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

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

236
        size_t rule_index = findRule(_rules, production, pattern);
237

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

245
        return InterpretState::Flow;
246
    }
247

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

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

258
        // Строим таблицу
259

260
        std::unique_ptr<ParsingTableBuilder_abstract>  builder;
261

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

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

280
        return InterpretState::Flow;
281
    }
282

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

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

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

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

304
        return i;
305
    }
306
}

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

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

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

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