• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ArkScript-lang / Ark / 11304355606

12 Oct 2024 08:53AM UTC coverage: 76.391% (+1.2%) from 75.225%
11304355606

push

github

SuperFola
feat(ir, compiler): implementing the IR optimizer

62 of 75 new or added lines in 3 files covered. (82.67%)

402 existing lines in 9 files now uncovered.

5054 of 6616 relevant lines covered (76.39%)

9231.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.52
/src/arkreactor/Compiler/AST/BaseParser.cpp
1
#include <Ark/Compiler/AST/BaseParser.hpp>
2
#include <Ark/Exceptions.hpp>
3

4
#include <utility>
5
#include <algorithm>
6

7
#include <fmt/core.h>
8

9
namespace Ark::internal
10
{
11
    void BaseParser::registerNewLine(std::string::iterator it, std::size_t row)
2,583✔
12
    {
2,583✔
13
        // search for an existing new line position
14
        if (std::ranges::find_if(m_it_to_row, [it](const auto& pair) {
165,210✔
15
                return pair.first == it;
162,627✔
16
            }) != m_it_to_row.end())
2,583✔
17
            return;
267✔
18

19
        // if the mapping is empty, the loop while never hit and we'll never insert anything
20
        if (m_it_to_row.empty())
2,316✔
21
        {
22
            m_it_to_row.emplace_back(it, row);
142✔
23
            return;
141✔
24
        }
25

26
        for (std::size_t i = 0, end = m_it_to_row.size(); i < end; ++i)
154,028✔
27
        {
28
            auto current = m_it_to_row[i].first;
151,853✔
29
            auto next = i + 1 < end ? m_it_to_row[i + 1].first : m_str.end();
151,853✔
30
            if (current < it && it < next)
151,854✔
31
            {
32
                m_it_to_row.insert(
4,351✔
33
                    m_it_to_row.begin() + static_cast<decltype(m_it_to_row)::difference_type>(i) + 1,
2,175✔
34
                    std::make_pair(it, row));
2,175✔
35
                break;
2,175✔
36
            }
37
        }
151,853✔
38
    }
2,583✔
39

40
    void BaseParser::next()
160,112✔
41
    {
160,111✔
42
        m_it = m_next_it;
160,112✔
43
        if (isEOF())
160,111✔
44
        {
45
            m_sym = utf8_char_t();  // reset sym to EOF
174✔
46
            return;
174✔
47
        }
48

49
        // getting a character from the stream
50
        auto [it, sym] = utf8_char_t::at(m_it, m_str.end());
159,938✔
51
        m_next_it = it;
159,937✔
52
        m_sym = sym;
159,938✔
53

54
        if (*m_it == '\n')
159,937✔
55
        {
56
            ++m_filepos.row;
2,583✔
57
            m_filepos.col = 0;
2,583✔
58
            registerNewLine(m_it, m_filepos.row);
2,583✔
59
        }
2,583✔
60
        else if (m_sym.isPrintable())
157,355✔
61
            m_filepos.col += m_sym.size();
157,354✔
62
    }
160,112✔
63

64
    void BaseParser::initParser(const std::string& filename, const std::string& code)
169✔
65
    {
169✔
66
        m_filename = filename;
169✔
67

68
        // if the input string is empty, raise an error
69
        if (code.empty())
169✔
70
        {
1✔
71
            m_sym = utf8_char_t();
×
72
            error("Expected symbol, got empty string", "");
1✔
73
        }
×
74

75
        m_str = code;
169✔
76
        m_it = m_next_it = m_str.begin();
169✔
77

78
        // otherwise, get the first symbol
79
        next();
169✔
80
    }
170✔
81

82
    void BaseParser::backtrack(const long n)
69,244✔
83
    {
69,244✔
84
        if (std::cmp_greater_equal(n, m_str.size()))
69,244✔
85
            return;
4✔
86

87
        m_it = m_str.begin() + n;
69,240✔
88
        auto [it, sym] = utf8_char_t::at(m_it, m_str.end());
4,713,698✔
89
        m_next_it = it;
69,240✔
90
        m_sym = sym;
69,240✔
91

92
        // search for the nearest it < m_it in the map to know the line number
93
        for (std::size_t i = 0, end = m_it_to_row.size(); i < end; ++i)
4,713,698✔
94
        {
95
            auto [at, line] = m_it_to_row[i];
4,644,665✔
96
            if (it < at)
4,644,458✔
97
            {
98
                m_filepos.row = line - 1;
207✔
99
                break;
207✔
100
            }
101
        }
4,644,458✔
102
        // compute the position in the line
103
        std::string_view view = m_str;
69,240✔
104
        const auto it_pos = static_cast<std::size_t>(std::distance(m_str.begin(), m_it));
69,240✔
105
        view = view.substr(0, it_pos);
69,240✔
106
        const auto nearest_newline_index = view.find_last_of('\n');
69,240✔
107
        if (nearest_newline_index != std::string_view::npos)
69,240✔
108
            m_filepos.col = it_pos - nearest_newline_index + 1;
65,475✔
109
        else
110
            m_filepos.col = it_pos + 1;
3,765✔
111
    }
69,244✔
112

113
    FilePosition BaseParser::getCursor() const
59,627✔
114
    {
59,627✔
115
        return m_filepos;
59,627✔
116
    }
117

118
    void BaseParser::error(const std::string& error, std::string exp)
27✔
119
    {
27✔
120
        const auto [row, col] = getCursor();
81✔
121
        throw CodeError(error, m_filename, row, col, std::move(exp), m_sym);
27✔
122
    }
54✔
123

124
    void BaseParser::errorWithNextToken(const std::string& message)
16✔
125
    {
16✔
126
        const auto pos = getCount();
16✔
127
        std::string next_token;
16✔
128

1✔
129
        anyUntil(IsEither(IsInlineSpace, IsEither(IsChar('('), IsChar(')'))), &next_token);
16✔
130
        backtrack(pos);
16✔
131

132
        error(message, next_token);
16✔
133
    }
16✔
134

135
    void BaseParser::errorMissingSuffix(const char suffix, const std::string& node_name)
2✔
136
    {
2✔
137
        errorWithNextToken(fmt::format("Missing '{}' after {}", suffix, node_name));
2✔
138
    }
2✔
139

140
    bool BaseParser::accept(const CharPred& t, std::string* s)
317,522✔
141
    {
317,522✔
142
        if (isEOF())
317,522✔
143
            return false;
227✔
144

145
        // return false if the predicate couldn't consume the symbol
146
        if (!t(m_sym.codepoint()))
317,295✔
147
            return false;
159,319✔
148
        // otherwise, add it to the string and go to the next symbol
149
        if (s != nullptr)
157,976✔
150
            *s += m_sym.c_str();
124,781✔
151

152
        next();
157,976✔
153
        return true;
157,976✔
154
    }
317,522✔
155

156
    bool BaseParser::expect(const CharPred& t, std::string* s)
1,971✔
157
    {
1,972✔
158
        // throw an error if the predicate couldn't consume the symbol
159
        if (!t(m_sym.codepoint()))
1,972✔
160
            error("Expected " + t.name, m_sym.c_str());
5✔
161
        // otherwise, add it to the string and go to the next symbol
162
        if (s != nullptr)
1,966✔
163
            *s += m_sym.c_str();
×
164
        next();
1,966✔
165
        return true;
1,966✔
166
    }
5✔
167

168
    bool BaseParser::space(std::string* s)
30,114✔
169
    {
30,114✔
170
        if (accept(IsSpace))
30,114✔
171
        {
172
            if (s != nullptr)
6,339✔
173
                s->push_back(' ');
×
174
            // loop while there are still ' ' to consume
175
            while (accept(IsSpace))
12,078✔
176
                ;
177
            return true;
6,339✔
178
        }
179
        return false;
23,775✔
180
    }
30,114✔
181

182
    bool BaseParser::inlineSpace(std::string* s)
1,331✔
183
    {
1,331✔
184
        if (accept(IsInlineSpace))
1,331✔
185
        {
186
            if (s != nullptr)
72✔
UNCOV
187
                s->push_back(' ');
×
188
            // loop while there are still ' ' to consume
189
            while (accept(IsInlineSpace))
77✔
190
                ;
191
            return true;
72✔
192
        }
193
        return false;
1,259✔
194
    }
1,331✔
195

196
    bool BaseParser::comment(std::string* s)
31,200✔
197
    {
31,200✔
198
        if (accept(IsChar('#'), s))
31,200✔
199
        {
200
            while (accept(IsNot(IsChar('\n')), s))
19,716✔
201
                ;
202
            accept(IsChar('\n'), s);
644✔
203
            return true;
644✔
204
        }
205
        return false;
30,556✔
206
    }
31,200✔
207

208
    bool BaseParser::spaceComment(std::string* s)
1,305✔
209
    {
1,305✔
210
        bool matched = false;
1,305✔
211

212
        inlineSpace();
1,305✔
213
        while (!isEOF() && comment(s))
1,331✔
214
        {
215
            inlineSpace();
26✔
216
            matched = true;
26✔
217
        }
218

219
        return matched;
1,305✔
220
    }
1,305✔
221

222
    bool BaseParser::newlineOrComment(std::string* s)
29,428✔
223
    {
29,428✔
224
        bool matched = false;
29,428✔
225

226
        space();
29,428✔
227
        while (!isEOF() && comment(s))
30,046✔
228
        {
229
            space();
618✔
230
            matched = true;
618✔
231
        }
232

233
        return matched;
29,428✔
234
    }
29,428✔
235

236
    bool BaseParser::prefix(const char c)
22,494✔
237
    {
22,494✔
238
        if (!accept(IsChar(c)))
22,494✔
239
            return false;
11,944✔
240
        return true;
10,550✔
241
    }
22,494✔
242

243
    bool BaseParser::suffix(const char c)
786✔
244
    {
786✔
245
        return accept(IsChar(c));
786✔
246
    }
×
247

248
    bool BaseParser::number(std::string* s)
7,748✔
249
    {
7,748✔
250
        if (accept(IsDigit, s))
7,748✔
251
        {
252
            // consume all the digits available,
253
            // stop when the symbol isn't a digit anymore
254
            while (accept(IsDigit, s))
1,079✔
255
                ;
256
            return true;
979✔
257
        }
258
        return false;
6,769✔
259
    }
7,748✔
260

261
    bool BaseParser::signedNumber(std::string* s)
7,727✔
262
    {
7,727✔
263
        accept(IsMinus, s);
7,727✔
264
        if (!number(s))
7,727✔
265
            return false;
6,769✔
266

267
        // (optional) floating part
268
        accept(IsChar('.'), s) && number(s);
958✔
269
        // (optional) scientific part
270
        if (accept(IsEither(IsChar('e'), IsChar('E')), s))
958✔
271
        {
272
            accept(IsEither(IsMinus, IsChar('+')), s);
5✔
273
            number(s);
5✔
274
        }
5✔
275

276
        return true;
958✔
277
    }
7,727✔
278

279
    bool BaseParser::hexNumber(unsigned int length, std::string* s)
8✔
280
    {
8✔
281
        while (length != 0)
56✔
282
        {
283
            if (!accept(IsHex, s))
48✔
284
                return false;
×
285
            --length;
48✔
286
        }
287
        return true;
8✔
288
    }
8✔
289

290
    bool BaseParser::name(std::string* s)
29,221✔
291
    {
29,221✔
292
        const auto alpha_symbols = IsEither(IsAlpha, IsSymbol);
29,221✔
293
        const auto alnum_symbols = IsEither(IsAlnum, IsSymbol);
29,221✔
294

295
        if (accept(alpha_symbols, s))
29,221✔
296
        {
297
            while (accept(alnum_symbols, s))
97,539✔
298
                ;
299
            return true;
21,099✔
300
        }
301
        return false;
8,122✔
302
    }
29,221✔
303

304
    bool BaseParser::sequence(const std::string& s)
6,494✔
305
    {
6,494✔
306
        return std::ranges::all_of(s, [this](const char c) {
13,074✔
307
            return accept(IsChar(c));
6,580✔
308
        });
×
309
    }
310

311
    bool BaseParser::packageName(std::string* s)
93✔
312
    {
93✔
313
        if (accept(IsAlnum, s))
93✔
314
        {
315
            while (accept(IsEither(IsAlnum, IsEither(IsChar('_'), IsChar('-'))), s))
855✔
316
                ;
317
            return true;
90✔
318
        }
319
        return false;
3✔
320
    }
93✔
321

322
    bool BaseParser::anyUntil(const CharPred& delim, std::string* s)
16✔
323
    {
16✔
324
        if (accept(IsNot(delim), s))
16✔
325
        {
326
            while (accept(IsNot(delim), s))
1,214✔
327
                ;
328
            return true;
4✔
329
        }
330
        return false;
12✔
331
    }
16✔
332

333
    bool BaseParser::oneOf(const std::initializer_list<std::string> words, std::string* s)
15,183✔
334
    {
15,183✔
335
        std::string buffer;
15,183✔
336
        if (!name(&buffer))
15,183✔
337
            return false;
126✔
338

339
        if (s)
15,057✔
340
            *s = buffer;
2,329✔
341

342
        return std::ranges::any_of(words, [&buffer](const std::string& word) {
34,162✔
343
            return word == buffer;
19,105✔
344
        });
345
    }
15,183✔
346
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc