loom

Форк
0
/
Scanner.cpp 
160 строк · 4.1 Кб
1
/*
2
MIT License
3

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

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

9
#include "simodo/inout/token/Scanner.h"
10

11
#include <cassert>
12

13

14
namespace simodo::inout
15
{
16

17
bool Scanner::putCharToBuffer()
18
{
19
    if (_is_end_of_file_reached)
20
        return false;
21

22
    // ВАЖНО! Предполагается, что входной поток содержит коды текста длиной не более двух байт
23
    /// \todo При чтении символов из входного потока потенциально возможно искажение (если размер кода текста > 16 бит).
24
    /// Кроме того, это приводит к слабости кода перед изменениями, например, при переходе на строки по 32 бита в символе.
25
    /// Решение: сделать класс с параметрическим типом на размер символа в потоке и строке.
26
    char16_t ch = _input.get();
27

28
    if (ch == std::char_traits<char16_t>::eof())
29
    {
30
        _is_end_of_file_reached = true;
31
        return false;
32
    }
33

34
    _buffer.push_back(ch);
35
    return true;
36
}
37

38
Scanner::Scanner(uri_index_t uri_index, InputStream_interface &input_stream, context_index_t context_index)
39
    : _uri_index(uri_index)
40
    , _input(input_stream)
41
    , _context_index(context_index)
42
    , _buffer()
43
    , _current_line(0)
44
    , _current_character(0)
45
    , _is_end_of_file_reached(false)
46
{
47
    _buffer.reserve(20);
48
}
49

50
bool Scanner::shift(size_t length)
51
{
52
    assert(_buffer.size() >= length);  // Нельзя сдвигать за пределы буфера (откуда токенайзеру знать то, чего он не видел?)
53

54
    // Вычисляем локацию
55
    for(size_t i=0; i < length; ++i)
56
    {
57
        char16_t ch = _buffer[i];
58

59
        if (ch == u'\n')
60
        {
61
            _current_line ++;
62
            _current_character = 0;
63
        }
64
        else
65
            _current_character ++;
66
    }
67

68
    // Выпиливаем неактуальное
69
    _buffer = _buffer.substr(length);
70

71
    if (_buffer.empty())
72
        return putCharToBuffer();
73

74
    return true;
75
}
76

77
TokenLocation Scanner::makeTokenLocation() const 
78
{
79
    return {_uri_index,{_token_start_line,_token_start_character,_current_line,_current_character}};
80
}
81

82
void Scanner::fixLocation(context_index_t context_index)
83
{
84
    _token_start_line = _current_line;
85
    _token_start_character = _current_character;
86
    _token_context_index = context_index;
87
}
88

89
bool Scanner::startsWith(char16_t ch)
90
{
91
    if (_buffer.empty())
92
    {
93
        if (_is_end_of_file_reached || _input.eof())
94
            return false;
95

96
        bool ok = putCharToBuffer();
97
        if (!ok)
98
            return false; // Достигли конца потока
99
    }
100

101
    return (_buffer[0] == ch);
102
}
103

104
bool Scanner::startsWith(const std::u16string &str)
105
{
106
    if (str.empty())
107
        return false;
108

109
    while(_buffer.size() < str.size())
110
    {
111
        if (_is_end_of_file_reached || _input.eof())
112
            return false;
113

114
        bool ok = putCharToBuffer();
115
        if (!ok)
116
            return false; // Достигли конца потока
117
    }
118

119
    return (_buffer.compare(0,str.size(),str) == 0);
120
}
121

122
bool Scanner::startsWithAnyOf(const std::u16string &str)
123
{
124
    if (str.empty())
125
        return false;
126

127
    if (_buffer.empty())
128
    {
129
        if (_is_end_of_file_reached || _input.eof())
130
            return false;
131

132
        bool ok = putCharToBuffer();
133
        if (!ok)
134
            return false; // Достигли конца потока
135
    }
136

137
    return (str.find(_buffer[0]) != std::u16string::npos);
138
}
139

140
char16_t Scanner::getFirstChar(void)
141
{
142
    return getChar();
143
}
144

145
char16_t Scanner::getChar(size_t pos)
146
{
147
    while(_buffer.size() < pos+1)
148
    {
149
        if (_is_end_of_file_reached || _input.eof())
150
            return std::char_traits<char16_t>::eof();
151

152
        bool ok = putCharToBuffer();
153
        if (!ok)
154
            return std::char_traits<char16_t>::eof(); // Достигли конца потока
155
    }
156

157
    return _buffer[pos];
158
}
159

160
}

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

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

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

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