GCC Code Coverage Report


Directory: ./
File: src/lexer/buffer.h
Date: 2023-04-27 00:55:30
Exec Total Coverage
Lines: 22 44 50.0%
Functions: 12 20 60.0%
Branches: 9 20 45.0%

Line Branch Exec Source
1 #pragma once
2
3 #include <string>
4
5 #include "dependencies/coz_wrap.h"
6 #include "dependencies/fmt.h"
7
8 #include "dtypes.h"
9 #include "logging/exceptions.h"
10
11 /*
12 * Buffers are special reader that keep track of current line/col and indent level
13 * they only need getc() to be defined to work properly
14 *
15 * StringBuffer is made to make debugging easy (might be useful for
16 * the eval option and macro gen)
17 *
18 * FileBuffer is the usual reader
19 */
20 namespace lython {
21 class AbstractBuffer {
22 public:
23 virtual char getc() = 0;
24 virtual const String& file_name() = 0;
25
26 AbstractBuffer() {}
27
28 virtual ~AbstractBuffer();
29
30 void init() { _next_char = getc(); }
31
32 // TODO: add a hash digest compute
33 // so we can hash files with little overhead
34 void consume() {
35
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27352 times.
27352 if (_next_char == EOF)
36 return;
37
38 27352 _col += 1;
39
40
2/2
✓ Branch 0 taken 1218 times.
✓ Branch 1 taken 26134 times.
27352 if (_next_char == '\n') {
41 1218 _line += 1;
42 1218 _col = 0;
43
44 1218 _indent = 0;
45 1218 _empty_line = true;
46 1218 _next_char = getc();
47 1218 return;
48 }
49
50
2/2
✓ Branch 0 taken 7634 times.
✓ Branch 1 taken 18500 times.
26134 if (_next_char == ' ') {
51
2/2
✓ Branch 0 taken 2966 times.
✓ Branch 1 taken 4668 times.
7634 if (_empty_line)
52 2966 _indent += 1;
53 7634 _next_char = getc();
54 7634 return;
55 }
56
57 18500 _empty_line = false;
58 18500 _next_char = getc();
59 }
60
61 // Used to fetch a given line for error reporting
62 virtual String getline(int start_line, int end_line = -1) { return ""; }
63
64 char peek() { return _next_char; }
65 int32 line() { return _line; }
66 int32 col() { return _col; }
67 int32 indent() { return _indent; }
68 bool empty_line() { return _empty_line; }
69
70 virtual void reset() {
71 _next_char = ' ';
72 _line = 1;
73 _col = 0;
74 _indent = 0;
75 _empty_line = true;
76 init();
77 }
78
79 private:
80 char _next_char{' '};
81 int32 _line = 1;
82 int32 _col = 0;
83 int32 _indent{0};
84 bool _empty_line{true};
85 };
86
87 class FileError: public Exception {
88 public:
89 template <typename... Args>
90 FileError(FmtStr fmt, const Args&... args): Exception(fmt, "FileError", args...) {}
91 };
92
93 String read_file(String const& name);
94
95 class FileBuffer: public AbstractBuffer {
96 public:
97 FileBuffer(String const& name);
98
99 ~FileBuffer() override;
100
101 char getc() override {
102 COZ_BEGIN("T::FileBuffer::getc");
103
104 515 char c = char(::getc(_file));
105
106 COZ_PROGRESS_NAMED("FileBuffer::getc");
107 COZ_END("T::FileBuffer::getc");
108 515 return c;
109 }
110
111 const String& file_name() override { return _file_name; }
112
113 void reset() override;
114
115 String getline(int start_line, int end_line = -1) override;
116
117 private:
118 String _file_name;
119 FILE* _file{nullptr};
120 };
121
122 class StringBuffer: public AbstractBuffer {
123 public:
124 StringBuffer(String code, String const& file = "c++ string"):
125 _code(std::move(code)), _file_name(file) {
126 init();
127 }
128
129 char getc() override {
130
2/2
✓ Branch 1 taken 858 times.
✓ Branch 2 taken 26843 times.
27701 if (_pos >= _code.size())
131 858 return EOF;
132
133 26843 _pos += 1;
134 26843 return _code[_pos - 1];
135 }
136
137 ~StringBuffer() override;
138
139 const String& file_name() override { return _file_name; }
140
141 private:
142 uint32 _pos{0};
143 String _code;
144 const String _file_name;
145
146 public:
147 void reset() override {
148 _pos = 0;
149 AbstractBuffer::reset();
150 }
151
152 String getline(int start_line, int end_line = -1) override {
153 uint32 old_pos = _pos;
154 //--
155
156 String result;
157 result.reserve(128);
158 _pos = start_line;
159
160 char c = getc();
161
162 while (c != '\n') {
163 result.push_back(c);
164 c = getc();
165 }
166
167 // --
168 _pos = old_pos;
169 return result;
170 }
171
172 // helper for testing
173 void read_all() {
174 char c;
175 do {
176 c = peek();
177 consume();
178 } while (c);
179 }
180
181 void load_code(const std::string& code) {
182 _code = code;
183 _pos = 0;
184 }
185 };
186
187 // Quick solution but not satisfactory
188 class ConsoleBuffer: public AbstractBuffer {
189 public:
190 ConsoleBuffer(): _file_name("console") { init(); }
191
192 char getc() override { return char(std::getchar()); }
193
194 const String& file_name() override { return _file_name; }
195
196 ~ConsoleBuffer() override;
197
198 private:
199 const String _file_name;
200 };
201
202 } // namespace lython
203