loom

Форк
0
254 строки · 8.9 Кб
1
/*
2
MIT License
3

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

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

9
/*! \file Утилита тестирования средств лексического анализа библиотеки SIMODO core. Проект SIMODO.
10
*/
11

12
#include "simodo/variable/json/LexicalParametersLoader.h"
13
#include "simodo/inout/convert/functions.h"
14
#include "simodo/inout/reporter/Reporter_abstract.h"
15
#include "simodo/inout/token/Tokenizer.h"
16
#include "simodo/inout/token/FileStream.h"
17
#include "simodo/inout/token/RefBufferStream.h"
18

19
#include <fstream>
20
#include <iostream>
21
#include <locale>
22
#include <codecvt>
23
#include <memory>
24
#include <algorithm>
25

26
using namespace simodo::inout;
27
using namespace simodo::variable;
28

29
namespace
30
{
31

32
    int produceLexicalAnalysis (const std::string & file_name, bool use_string_buffer, const LexicalParameters & lex_param)
33
    {
34
        std::ifstream                          in(file_name);
35
        std::u16string                         string_buffer;
36
        std::unique_ptr<InputStream_interface> stream;
37

38
        if (!in)
39
        {
40
            std::cout << "Ошибка при открытии файла '" << file_name << "'" << std::endl;
41
            return 2;
42
        }
43

44
        if (use_string_buffer)
45
        {
46
            InputStream in_stream(in);
47

48
            while(true)
49
            {
50
                char16_t ch = in_stream.get();
51
                if (ch == std::char_traits<char16_t>::eof())
52
                    break;
53
                string_buffer += ch;
54
            }
55

56
            stream = std::make_unique<RefBufferStream>(string_buffer.data());
57
        }
58
        else
59
            stream = std::make_unique<InputStream>(in);
60

61
        Tokenizer   tzer(0, *stream, lex_param);
62

63
        uint32_t comment_n = 0;
64
        uint32_t annotation_n = 0;
65
        uint32_t punctuation_n = 0;
66
        uint32_t keyword_n = 0;
67
        uint32_t word_n = 0;
68
        uint32_t word_national_mix_error_n = 0;
69
        uint32_t word_national_use_error_n = 0;
70
        uint32_t number_n = 0;
71
        uint32_t number_wrong_n = 0;
72
        uint32_t error_n = 0;
73
        uint32_t unknown = 0;
74
        uint32_t token_count = 0;
75

76
        Token t = tzer.getAnyToken();
77

78
        while (t.type() != LexemeType::Empty)
79
        {
80
            token_count ++;
81

82
            switch(t.type())
83
            {
84
            case LexemeType::Punctuation:
85
                punctuation_n ++;
86
                if (t.qualification() == TokenQualification::Keyword)
87
                    keyword_n ++;
88
                break;
89
            case LexemeType::Id:
90
                word_n ++;
91
                if (t.qualification() == TokenQualification::NationalCharacterMix)
92
                    word_national_mix_error_n ++;
93
                break;
94
            case LexemeType::Annotation:
95
                annotation_n ++;
96
                break;
97
            case LexemeType::Number:
98
                number_n ++;
99
                if (t.qualification() == TokenQualification::NotANumber)
100
                    number_wrong_n ++;
101
                break;
102
            case LexemeType::Comment:
103
                comment_n ++;
104
                break;
105
            case LexemeType::Error:
106
                error_n ++;
107
                if (t.qualification() == TokenQualification::NationalCharacterMix)
108
                    word_national_mix_error_n ++;
109
                if (t.qualification() == TokenQualification::NationalCharacterUse)
110
                    word_national_use_error_n ++;
111
                break;
112
            default:
113
                unknown ++;
114
                break;
115
            }
116

117
            Location loc = t.makeLocation({file_name});
118

119
            std::cout << loc.uri()
120
                 << ":" << loc.range().start().line() << "/" << loc.range().start().character()
121
                 << "-" << loc.range().end().line() << "/" << loc.range().end().character() << ", token: \""
122
                 << simodo::inout::toU8(t.token()) << "\"";
123

124
            if (t.token() != t.lexeme())
125
                std::cout << ", lexeme: \"" << toU8(t.lexeme()) << "\"";
126

127
            std::cout << ", type: " << getLexemeTypeName(t.type());
128

129
            if (t.qualification() != TokenQualification::None)
130
                std::cout << ", qualification: " << getQualificationName(t.qualification());
131

132
            std::cout << std::endl;
133

134
            t = tzer.getAnyToken();
135
        }
136

137
        std::cout << "ИТОГО: токенов ..... " << token_count << std::endl
138
                  << "       комментариев. " << comment_n << std::endl
139
                  << "       аннотаций ... " << annotation_n << std::endl
140
                  << "       пунктуаций .. " << punctuation_n << " (из них ключевых слов: " << keyword_n << ")" << std::endl
141
                  << "       слов ........ " << word_n  << " (из них с перемешанными алфавитами: " << word_national_mix_error_n << ")" << std::endl
142
                  << "       чисел ....... " << number_n  << " (из них с ошибками: " << number_wrong_n << ")" << std::endl
143
                  << "       ошибок ...... " << error_n 
144
                  << " (из них с недопустимым алфавитом: " << word_national_use_error_n << "," 
145
                  << " c перемешанными алфавитами: " << word_national_mix_error_n << ")" << std::endl
146
                  << "       сбоев ....... " << unknown << std::endl
147
                  ;
148

149
        return 0;
150
    }
151
}
152

153
int main(int argc, char *argv[])
154
{
155
    std::vector<std::string> arguments(argv + 1, argv + argc);
156

157
    std::string	file_name           = "";
158
    bool        use_char16_buffer   = false;
159
    std::string	lex_file_name       = "";
160

161
    bool	    error               = false;
162
    bool	    help                = false;
163

164
    std::vector<NumberMask> masks;
165

166
    for(size_t i=0; i < arguments.size(); ++i)
167
    {
168
        const std::string & arg = arguments[i];
169

170
        if (arg[0] == '-')
171
        {
172
            if (arg == "--help" || arg == "-h")
173
                help = true;
174
            else if (arg == "--use-char16-buffer")
175
                use_char16_buffer = true;
176
            else if (arg == "--lex-param-json" || arg == "-l")
177
            {
178
                if (i == arguments.size()-1 || !lex_file_name.empty())
179
                    error = true;
180
                else
181
                    lex_file_name = arguments[++i];
182
            }
183
            else if (arg == "--number_mask" || arg == "-n")
184
            {
185
                if (i+2 >= arguments.size())
186
                    error = true;
187
                else {
188
                    masks.push_back({toU16(arguments[i+1]),
189
                                    LexemeType::Number,
190
                                    static_cast<number_system_t>(stoi(arguments[i+2]))});
191
                    i += 2;
192
                }
193
            }
194
            else
195
                error = true;
196
        }
197
        else if (file_name.empty())
198
            file_name = arg;
199
        else
200
            error = true;
201
    }
202

203
    if (!help && file_name.empty())
204
        error = true;
205

206
    if (error)
207
    {
208
        std::cout << "Ошибка в параметрах запуска" << std::endl;
209
        help = true;
210
    }
211

212
    if (help)
213
        std::cout << "Утилита лексического анализа. Чтение лексических параметров из JSON-файла. Проект SIMODO." << std::endl
214
                  << "Формат запуска:" << std::endl
215
                  << "    <имя утилиты> [<параметры>] <файл>" << std::endl
216
                  << "Параметры:" << std::endl
217
                  << "    -h | --help                  - отображение подсказки по запуску программы" << std::endl
218
                  << "         --use-char16-buffer     - провести лексический анализ заданного файла с использованием строкового буфера" << std::endl
219
                  << "    -l | --lex-param-json <файл> - JSON-файл определения лексических параметров" << std::endl
220
                  << "    -n | --number_mask <маска> <система счисления> - добавить маску числа" << std::endl
221
                  ;
222

223
    if (error)
224
        return 1;
225

226
    if (file_name.empty())
227
        return 0;
228

229
    LexicalParameters lex_param{
230
        {},
231
        {},
232
        u"",
233
        {},
234
        u"",
235
        u"",
236
        u"",
237
        u"",
238
        false,
239
        false,
240
        false
241
    };
242

243
    if (!lex_file_name.empty())
244
        if (!loadLexicalParameters(lex_file_name,lex_param))
245
        {
246
            std::cout << "Ошибка при загрузке файла описания лексики '" << lex_file_name << "'" << std::endl;
247
            return 1;
248
        }
249

250
    for(const NumberMask & m : masks)
251
        lex_param.masks.push_back(m);
252

253
    return produceLexicalAnalysis(file_name, use_char16_buffer, lex_param);
254
}
255

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

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

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

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