loom

Форк
0
243 строки · 8.7 Кб
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/inout/token/FileStream.h"
13
#include "simodo/inout/token/RefBufferStream.h"
14
#include "simodo/inout/token/Tokenizer.h"
15
#include "simodo/inout/convert/functions.h"
16

17
#include <fstream>
18
#include <iostream>
19
#include <locale>
20
#include <codecvt>
21
#include <memory>
22
#include <algorithm>
23

24
using namespace simodo;
25

26
namespace
27
{
28

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

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

41
        if (use_string_buffer)
42
        {
43
            inout::InputStream in_stream(in);
44

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

53
            stream = std::make_unique<inout::RefBufferStream>(string_buffer.data());
54
        }
55
        else
56
            stream = std::make_unique<inout::InputStream>(in);
57

58
        inout::Tokenizer tzer(0, *stream, lex_param);
59

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

73
        inout::Token t = tzer.getAnyToken();
74

75
        while (t.type() != inout::LexemeType::Empty)
76
        {
77
            token_count ++;
78

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

114
            inout::Location loc = t.makeLocation({file_name});
115

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

121
            if (t.token() != t.lexeme())
122
                std::cout << ", lexeme: \"" << inout::toU8(t.lexeme()) << "\"";
123

124
            std::cout << ", type: " << getLexemeTypeName(t.type());
125

126
            if (t.qualification() != inout::TokenQualification::None)
127
                std::cout << ", qualification: " << getQualificationName(t.qualification());
128

129
            std::cout << std::endl;
130

131
            t = tzer.getAnyToken();
132
        }
133

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

146
        return 0;
147
    }
148
}
149

150
int main(int argc, char *argv[])
151
{
152
    /// @todo Переделать работу с аргументами командной строки на использование 
153
    /// класса utility::SafeParameters
154

155
    std::vector<std::string> arguments(argv + 1, argv + argc);
156

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

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

163
    std::vector<inout::NumberMask> masks;
164

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

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

195
    if (!help && file_name.empty())
196
        error = true;
197

198
    if (error)
199
    {
200
        std::cout << "Ошибка в параметрах запуска" << std::endl;
201
        help = true;
202
    }
203

204
    if (help)
205
        std::cout	<< "Утилита лексического анализа. Проект SIMODO." << std::endl
206
                << "Формат запуска:" << std::endl
207
                << "    <имя утилиты> [<параметры>] <файл>" << std::endl
208
                << "Параметры:" << std::endl
209
                << "    -h | --help                  - отображение подсказки по запуску программы" << std::endl
210
                << "         --use-char16-buffer     - провести лексический анализ заданного файла с использованием строкового буфера" << std::endl
211
                << "    -n | --number_mask <маска> <система счисления> - добавить маску числа" << std::endl
212
                ;
213

214
    if (error)
215
        return 1;
216

217
    if (file_name.empty())
218
        return 0;
219

220
    inout::LexicalParameters lex_param {
221
        {
222
            {u"/*", u"*/", u"", inout::LexemeType::Comment},
223
            {u"//", u"",   u"", inout::LexemeType::Comment},
224
            {u"\"", u"\"", u"\\", inout::LexemeType::Annotation},
225
            {u"'",  u"'",  u"\\", inout::LexemeType::Annotation},
226
        },
227
        {},
228
        u"+-,;",
229
        {u"_",u"_Nebuchadnezzar_II",u"ФУ_"},
230
        u"0123456789ABCDEF",
231
        u"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
232
        u"абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ",
233
        u"_",
234
        false,
235
        false,
236
        true
237
    };
238

239
    for(const inout::NumberMask & m : masks)
240
        lex_param.masks.push_back(m);
241

242
    return produceLexicalAnalysis(file_name, use_char16_buffer, lex_param);
243
}
244

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

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

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

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