GCC Code Coverage Report


Directory: src/
File: src/frontend/gyoji.l
Date: 2025-10-15 09:43:47
Exec Total Coverage
Lines: 148 160 92.5%
Functions: 1 1 100.0%
Branches: 12 12 100.0%

Line Branch Exec Source
1 %{
2 #include <cstdlib>
3 #include <memory>
4 #include <gyoji-frontend.hpp>
5 #include <gyoji.y.hpp>
6
7 using namespace Gyoji::context;
8 using namespace Gyoji::frontend;
9 using namespace Gyoji::frontend::tree;
10 using namespace Gyoji::frontend::namespaces;
11 using namespace Gyoji::frontend::yacc;
12
13
14 std::vector<Gyoji::owned<TerminalNonSyntax>> non_syntax_data;
15
16 #define DEBUG_TERMINALS 0
17 #if DEBUG_TERMINALS
18 #define PRINT_TERMINALS(s,t) \
19 printf("%s : %s%s\n", s, t, \
20 (node->get_fully_qualified_name().size() > 0) ? \
21 (std::string(" : ") + node->get_fully_qualified_name()).c_str() : \
22 std::string().c_str());
23 #else
24 #define PRINT_TERMINALS(s,t) /**/
25 #endif
26
27 #define YY_INPUT(buf,result,max_size) \
28 ((LexContext*)yyget_extra(yyscanner))->input_source.read(buf, result, max_size)
29
30
31 32188 void move_array(
32 std::vector<Gyoji::owned<TerminalNonSyntax>> & dst,
33 std::vector<Gyoji::owned<TerminalNonSyntax>> & src
34 )
35 {
36 32188 dst.clear();
37
2/2
✓ Branch 5 taken 26348 times.
✓ Branch 6 taken 32188 times.
58536 for (auto & srcitem : src) {
38 26348 dst.push_back(std::move(srcitem));
39 }
40 32188 src.clear();
41 32188 }
42
43 #define TOKEN_APPEND() \
44 { \
45 LexContext *lc = (LexContext*)yyget_extra(yyscanner); \
46 lc->compiler_context.get_token_stream() \
47 .append_token(std::string(yytext)); \
48 }
49
50 #define TOKEN_ADD(nodetype) \
51 LexContext *lc = (LexContext*)yyget_extra(yyscanner); \
52 const Token &tok = \
53 lc->compiler_context.get_token_stream() \
54 .add_token( \
55 Gyoji::frontend::tree::TERMINAL_ ##nodetype, \
56 std::string(yytext), \
57 lc->compiler_context.get_filename(), \
58 lc->line, \
59 lc->column \
60 ); \
61 lc->column += strlen(yytext); \
62
63 #define START_NODE(nodetype) \
64 TOKEN_ADD(nodetype); \
65 Terminal* node = new Terminal(tok); \
66 move_array(node->non_syntax, non_syntax_data); \
67 yylval->emplace<Gyoji::owned<Terminal>>(node);
68
69 #define RETURN_NODE(nodetype) \
70 return YaccParser::token::nodetype;
71
72 #define PROCESS_NODE(nodetype) \
73 START_NODE(nodetype) \
74 PRINT_TERMINALS(#nodetype, yytext) \
75 RETURN_NODE(nodetype);
76
77 #define PROCESS_IDENTIFIER(nodetype, entity) \
78 START_NODE(nodetype) \
79 node->set_ns2_entity(entity); \
80 PRINT_TERMINALS(#nodetype, yytext) \
81 RETURN_NODE(nodetype);
82
83 // \&\& { PROCESS_NODE(AND_OP);}
84 //|"0b"|"0")
85 //radix ("0x"|"0b"|"0o")
86 //opt_radix ({radix}?)
87 %}
88
89 %option reentrant interactive noyywrap nodefault
90
91 %x COMMENT
92
93 opt_sign (\-?)
94
95 bin_digit [01]
96 oct_digit ({bin_digit}|[234567])
97 dec_digit ({oct_digit}|[89])
98 hex_digit ({dec_digit}|[aAbBcCdDeEfF])
99
100 bin_dseq ("0b"{bin_digit}({dec_digit}|\_)*)
101 oct_dseq ("0o"{oct_digit}({dec_digit}|\_)*)
102 dec_dseq ({dec_digit}({dec_digit}|\_)*)
103 hex_dseq ("0x"{hex_digit}({hex_digit}|\_)*)
104
105 int_dseq ({bin_dseq}|{oct_dseq}|{dec_dseq}|{hex_dseq})
106
107 opt_dec_dseq ({dec_dseq}?)
108
109 frac (({opt_dec_dseq}"."{dec_dseq})|{dec_dseq}".")
110 exp ([eE][+-]?{dec_dseq})
111 exp_opt ({exp}?)
112
113 integer ({opt_sign}{int_dseq}{opt_integer_size})
114 integer_size ("u64"|"u32"|"u16"|"u8"|"i64"|"i32"|"i16"|"i8")
115 opt_integer_size ({integer_size}?)
116
117 float ({opt_sign}(({frac}{exp_opt})|({dec_dseq}{exp}))({opt_float_size}))
118 float_size ("f32"|"f64")
119 opt_float_size ({float_size}?)
120
121 identifier ([a-zA-Z_][a-zA-Z_0-9]*)
122 whitespace ([[:space:]])
123 %%
124
125 600 namespace {PROCESS_NODE(NAMESPACE);}
126 168 using {PROCESS_NODE(USING);}
127 98 as {PROCESS_NODE(AS);}
128 548 typedef {PROCESS_NODE(TYPEDEF);}
129 850 class {PROCESS_NODE(CLASS);}
130 1070 public {PROCESS_NODE(PUBLIC);}
131 378 enum {PROCESS_NODE(ENUM);}
132 32
133 186 private {PROCESS_NODE(PRIVATE);}
134 66 protected {PROCESS_NODE(PROTECTED);}
135 22
136 struct {PROCESS_NODE(STRUCT);}
137 union {PROCESS_NODE(UNION);}
138
139 792 if {PROCESS_NODE(IF);}
140 384 else {PROCESS_NODE(ELSE);}
141 254 while {PROCESS_NODE(WHILE);}
142 48 for {PROCESS_NODE(FOR);}
143 32 switch {PROCESS_NODE(SWITCH);}
144 1648 return {PROCESS_NODE(RETURN);}
145 582 break {PROCESS_NODE(BREAK);}
146 48 continue {PROCESS_NODE(CONTINUE);}
147 48 label {PROCESS_NODE(LABEL);}
148 48 goto {PROCESS_NODE(GOTO);}
149 102 case {PROCESS_NODE(CASE);}
150 60 default {PROCESS_NODE(DEFAULT);}
151 10
152 264 sizeof {PROCESS_NODE(SIZEOF);}
153 390 cast {PROCESS_NODE(CAST);}
154 190 typeof {PROCESS_NODE(TYPEOF);}
155 20
156 354 const {PROCESS_NODE(CONST);}
157 318 volatile {PROCESS_NODE(VOLATILE);}
158 208 unsafe {PROCESS_NODE(UNSAFE);}
159 34
160 14814 ; {PROCESS_NODE(SEMICOLON);}
161 186 -> {PROCESS_NODE(PTR_OP);}
162 152 >> {PROCESS_NODE(RIGHT_OP);}
163 876 \+\+ {PROCESS_NODE(INC_OP);}
164 822 \-\- {PROCESS_NODE(DEC_OP);}
165 210 \<\< {PROCESS_NODE(LEFT_OP);}
166 88 \< { PROCESS_NODE(COMPARE_LESS); }
167 56 \> { PROCESS_NODE(COMPARE_GREATER); }
168 40 \<= { PROCESS_NODE(COMPARE_LESS_EQUAL); }
169 70 \>= { PROCESS_NODE(COMPARE_GREATER_EQUAL); }
170 542 == { PROCESS_NODE(COMPARE_EQUAL); }
171 498 != { PROCESS_NODE(COMPARE_NOT_EQUAL); }
172 138 \^ { PROCESS_NODE(XOR_OP);}
173 10
174 60 \|\| { PROCESS_NODE(OR_OP);}
175 30 \*\= { PROCESS_NODE(MUL_ASSIGNMENT); }
176 40 \/\= { PROCESS_NODE(DIV_ASSIGNMENT); }
177 52 \+\= { PROCESS_NODE(ADD_ASSIGNMENT); }
178 44 \-\= { PROCESS_NODE(SUB_ASSIGNMENT); }
179 40 \<\<\= { PROCESS_NODE(LEFT_ASSIGNMENT); }
180 40 \>\>\= { PROCESS_NODE(RIGHT_ASSIGNMENT); }
181 10 \&\= { PROCESS_NODE(AND_ASSIGNMENT); }
182 \^\= { PROCESS_NODE(XOR_ASSIGNMENT); }
183 \|\= { PROCESS_NODE(OR_ASSIGNMENT); }
184
185 6090 \( {PROCESS_NODE(PAREN_L);}
186 6090 \) {PROCESS_NODE(PAREN_R);}
187 2276 \[ {PROCESS_NODE(BRACKET_L);}
188 328 \] {PROCESS_NODE(BRACKET_R);}
189 3982 \{ {PROCESS_NODE(BRACE_L);}
190 5200 \} {PROCESS_NODE(BRACE_R);}
191 1300
192 300 \. {PROCESS_NODE(DOT);}
193 \? {PROCESS_NODE(QUESTIONMARK);}
194 156 \: {PROCESS_NODE(COLON);}
195 2422 \, {PROCESS_NODE(COMMA);}
196 916 \! {PROCESS_NODE(BANG);}
197 192 \~ {PROCESS_NODE(TILDE);}
198 434 \& {PROCESS_NODE(ANDPERSAND);}
199 158 \| {PROCESS_NODE(PIPE);}
200 298 \+ {PROCESS_NODE(PLUS);}
201 276 \- {PROCESS_NODE(MINUS);}
202 2586 \* {PROCESS_NODE(STAR);}
203 986 \/ {PROCESS_NODE(SLASH);}
204 174 \% {PROCESS_NODE(PERCENT);}
205 3294 \= {PROCESS_NODE(ASSIGNMENT);}
206 1084
207 486 \"[^\"]*\" {PROCESS_NODE(LITERAL_STRING);}
208 \'([^'\\\n]|\\[abefnrt\'])\' {
209 624 PROCESS_NODE(LITERAL_CHAR);
210 }
211 (true|false) {PROCESS_NODE(LITERAL_BOOL);}
212 null {PROCESS_NODE(LITERAL_NULL);}
213
214 288 {float} {PROCESS_NODE(LITERAL_FLOAT);}
215 4026 {integer} { PROCESS_NODE(LITERAL_INT);}
216 1342 (::)*{identifier}({whitespace}*:{whitespace}*:{whitespace}*{identifier})* {
217 11076 LexContext *lex_context = (LexContext*)yyget_extra(yyscanner);
218 11076 NS2Context & ns2_context = lex_context->ns2_context;
219
220 //fprintf(stderr, "Looking up in namespace context %s\n", yytext);
221 11076 NS2Entity *entity = ns2_context.namespace_find(std::string(yytext));
222
2/2
✓ Branch 0 taken 4396 times.
✓ Branch 1 taken 6680 times.
11076 if (entity == nullptr) {
223 // Not yet known. We expect the syntax layer to
224 // find a place to put this identifier in a namespace.
225 //fprintf(stderr, "Name is an unknown identifier %s\n", yytext);
226 13188 PROCESS_IDENTIFIER(IDENTIFIER, nullptr);
227 }
228
2/2
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 6642 times.
6680 else if (entity->get_type() == NS2Entity::ENTITY_TYPE_NAMESPACE) {
229 //fprintf(stderr, "Name is a namespace %s\n", yytext);
230 114 PROCESS_IDENTIFIER(NAMESPACE_NAME, entity);
231 }
232
6/6
✓ Branch 1 taken 3344 times.
✓ Branch 2 taken 3298 times.
✓ Branch 4 taken 172 times.
✓ Branch 5 taken 3172 times.
✓ Branch 6 taken 3470 times.
✓ Branch 7 taken 3172 times.
6642 else if (entity->get_type() == NS2Entity::ENTITY_TYPE_TYPE || entity->get_type() == NS2Entity::ENTITY_TYPE_CLASS) {
233 //fprintf(stderr, "Name is a type %s\n", yytext);
234 10410 PROCESS_IDENTIFIER(TYPE_NAME, entity);
235 }
236 else {
237 //fprintf(stderr, "Name is an identifier we've seen before %s\n", yytext);
238 // An identifier we've seen before. It should
239 // already be assigned to a namespace location.
240 9516 PROCESS_IDENTIFIER(IDENTIFIER, entity);
241 }
242 }
243
244 62 "/*" {
245 62 BEGIN(COMMENT);
246 124 TOKEN_ADD(comment);
247 Gyoji::owned<TerminalNonSyntax> nsd = std::make_unique<TerminalNonSyntax>(
248 124 TerminalNonSyntax::TerminalNonSyntax::Type::EXTRA_COMMENT_MULTI_LINE,
249 tok
250 62 );
251 62 non_syntax_data.push_back(std::move(nsd));
252 62 }
253 62 <COMMENT>"*/" {
254 124 TOKEN_APPEND()
255 62 BEGIN(INITIAL);
256 }
257 62 <COMMENT>[^*]* {
258 208 TOKEN_APPEND()
259 }
260 104 <COMMENT>\* {
261 148 TOKEN_APPEND()
262 }
263 74
264 496 \/\/.* {
265 // Single-line comment:
266 992 TOKEN_ADD(single_line_comment);
267 Gyoji::owned<TerminalNonSyntax> nsd = std::make_unique<TerminalNonSyntax>(
268 992 TerminalNonSyntax::Type::EXTRA_COMMENT_SINGLE_LINE,
269 tok
270 496 );
271 496 non_syntax_data.push_back(std::move(nsd));
272 496 }
273 496 [ \t]+ {
274 33744 TOKEN_ADD(whitespace);
275 Gyoji::owned<TerminalNonSyntax> nsd = std::make_unique<TerminalNonSyntax>(
276 33744 TerminalNonSyntax::Type::EXTRA_WHITESPACE,
277 tok
278 16872 );
279 16872 non_syntax_data.push_back(std::move(nsd));
280 16872 }
281 16872 \n {
282 17764 TOKEN_ADD(newline);
283 Gyoji::owned<TerminalNonSyntax> nsd = std::make_unique<TerminalNonSyntax>(
284 17764 TerminalNonSyntax::Type::EXTRA_WHITESPACE,
285 tok
286 8882 );
287 8882 non_syntax_data.push_back(std::move(nsd));
288 8882 LexContext *lex_context = (LexContext*)yyget_extra(yyscanner);
289 8882 lex_context->line++;
290 8882 lex_context->column = 0;
291 8882 }
292 8882 \#[a-zA-Z]+\ [[:digit:]]+\ \".*\"\n {
293 10 // XXX TODO : Parse the source file and line number to
294 // mark the current position of compilation in terms of
295 // an original source file that generated this block of code.
296 // This is useful, for example, when working with a YACC file
297 // that generates some Gyoji code and you want to trace
298 // the error to the correct line of YACC code and not necessarily
299 // to the source file being compiled.
300 20 TOKEN_ADD(file_metadata)
301 Gyoji::owned<TerminalNonSyntax> nsd = std::make_unique<TerminalNonSyntax>(
302 20 TerminalNonSyntax::Type::EXTRA_FILE_METADATA,
303 tok
304 10 );
305 10 non_syntax_data.push_back(std::move(nsd));
306 10 }
307 10 \#.*\n {
308 52 TOKEN_ADD(file_metadata)
309 Gyoji::owned<TerminalNonSyntax> nsd = std::make_unique<TerminalNonSyntax>(
310 52 TerminalNonSyntax::Type::EXTRA_FILE_METADATA,
311 tok
312 26 );
313 26 non_syntax_data.push_back(std::move(nsd));
314 26 }
315 26 . {
316 return YaccParser::token::INVALID_INPUT;
317 }
318 1638 <<EOF>> {PROCESS_NODE(YYEOF)}
319 546
320 %%
321