GCC Code Coverage Report


Directory: src/
File: src/cmdline/jformat-tree.cpp
Date: 2025-10-24 11:14:59
Exec Total Coverage
Lines: 98 98 100.0%
Functions: 10 10 100.0%
Branches: 37 39 94.9%

Line Branch Exec Source
1 /* Copyright 2025 Jonathan S. Arney
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * https://github.com/jarney/gyoji/blob/master/LICENSE
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "jformat-tree.hpp"
16 #include <iostream>
17 #include <gyoji-misc/xml.hpp>
18
19 using namespace Gyoji::misc;
20 using namespace Gyoji::frontend::ast;
21 using namespace Gyoji::frontend::tree;
22 using namespace Gyoji::cmdline;
23 using namespace Gyoji::context;
24
25 struct TokenName {
26 TokenID token;
27 const char *name;
28 };
29
30 static TokenName token_names[] = {
31 // Syntax Terminals
32 {TERMINAL_NAMESPACE, "NAMESPACE"},
33 {TERMINAL_USING, "USING"},
34 {TERMINAL_AS, "AS"},
35 {TERMINAL_TYPEDEF, "TYPEDEF"},
36 {TERMINAL_CLASS, "CLASS"},
37 {TERMINAL_PUBLIC, "PUBLIC"},
38 {TERMINAL_ENUM, "ENUM"},
39 {TERMINAL_PRIVATE, "PRIVATE"},
40 {TERMINAL_PROTECTED, "PROTECTED"},
41 {TERMINAL_STRUCT, "STRUCT"},
42 {TERMINAL_UNION, "UNION"},
43
44 {TERMINAL_IF, "IF"},
45 {TERMINAL_ELSE, "ELSE"},
46 {TERMINAL_WHILE, "WHILE"},
47 {TERMINAL_FOR, "FOR"},
48 {TERMINAL_SWITCH, "SWITCH"},
49 {TERMINAL_RETURN, "RETURN"},
50 {TERMINAL_BREAK, "BREAK"},
51 {TERMINAL_CONTINUE, "CONTINUE"},
52 {TERMINAL_LABEL, "LABEL"},
53 {TERMINAL_GOTO, "GOTO"},
54
55 {TERMINAL_CASE, "CASE"},
56 {TERMINAL_DEFAULT, "DEFAULT"},
57 {TERMINAL_SIZEOF, "SIZEOF"},
58 {TERMINAL_CAST, "CAST"},
59 {TERMINAL_TYPEOF, "TYPEOF"},
60 {TERMINAL_CONST, "CONST"},
61 {TERMINAL_VOLATILE, "VOLATILE"},
62 {TERMINAL_UNSAFE, "UNSAFE"},
63 {TERMINAL_SEMICOLON, "SEMICOLON"},
64 {TERMINAL_PTR_OP, "PTR_OP"},
65
66 {TERMINAL_RIGHT_OP, "RIGHT_OP"},
67 {TERMINAL_INC_OP, "INC_OP"},
68 {TERMINAL_DEC_OP, "DEC_OP"},
69 {TERMINAL_LEFT_OP, "LEFT_OP"},
70 {TERMINAL_COMPARE_LESS, "COMPARE_LESS"},
71 {TERMINAL_COMPARE_GREATER, "COMPARE_GREATER"},
72 {TERMINAL_COMPARE_LESS_EQUAL, "COMPARE_LESS_EQUAL"},
73 {TERMINAL_COMPARE_GREATER_EQUAL, "COMPARE_GREATER_EQUAL"},
74 {TERMINAL_COMPARE_EQUAL, "COMPARE_EQUAL"},
75 {TERMINAL_COMPARE_NOT_EQUAL, "COMPARE_NOT_EQUAL"},
76
77 {TERMINAL_XOR_OP, "XOR_OP"},
78 {TERMINAL_OR_OP, "OR_OP"},
79 {TERMINAL_MUL_ASSIGNMENT, "MUL_ASSIGNMENT"},
80 {TERMINAL_DIV_ASSIGNMENT, "DIV_ASSIGNMENT"},
81 {TERMINAL_ADD_ASSIGNMENT, "ADD_ASSIGNMENT"},
82 {TERMINAL_SUB_ASSIGNMENT, "SUB_ASSIGNMENT"},
83 {TERMINAL_LEFT_ASSIGNMENT, "LEFT_ASSIGNMENT"},
84 {TERMINAL_RIGHT_ASSIGNMENT, "RIGHT_ASSIGNMENT"},
85 {TERMINAL_AND_ASSIGNMENT, "AND_ASSIGNMENT"},
86 {TERMINAL_XOR_ASSIGNMENT, "XOR_ASSIGNMENT"},
87
88 {TERMINAL_OR_ASSIGNMENT, "OR_ASSIGNMENT"},
89 {TERMINAL_PAREN_L, "PAREN_L"},
90 {TERMINAL_PAREN_R, "PAREN_R"},
91 {TERMINAL_BRACKET_L, "BRACKET_L"},
92 {TERMINAL_BRACKET_R, "BRACKET_R"},
93 {TERMINAL_BRACE_L, "BRACE_L"},
94 {TERMINAL_BRACE_R, "BRACE_R"},
95 {TERMINAL_DOT, "DOT"},
96 {TERMINAL_QUESTIONMARK, "QUESTIONMARK"},
97 {TERMINAL_COLON, "COLON"},
98 {TERMINAL_COMMA, "COMMA"},
99
100 {TERMINAL_BANG, "BANG"},
101 {TERMINAL_TILDE, "TILDE"},
102 {TERMINAL_ANDPERSAND, "ANDPERSAND"},
103 {TERMINAL_PIPE, "PIPE"},
104 {TERMINAL_PLUS, "PLUS"},
105 {TERMINAL_MINUS, "MINUS"},
106 {TERMINAL_STAR, "STAR"},
107 {TERMINAL_SLASH, "SLASH"},
108 {TERMINAL_PERCENT, "PERCENT"},
109
110 {TERMINAL_ASSIGNMENT, "ASSIGNMENT"},
111 {TERMINAL_NAMESPACE_NAME, "NAMESPACE_NAME"},
112 {TERMINAL_TYPE_NAME, "TYPE_NAME"},
113 {TERMINAL_BOOL, "BOOL"},
114 {TERMINAL_IDENTIFIER, "IDENTIFIER"},
115 {TERMINAL_LITERAL_BOOL, "LITERAL_BOOL"},
116 {TERMINAL_LITERAL_CHAR, "LITERAL_CHAR"},
117 {TERMINAL_LITERAL_STRING, "LITERAL_STRING"},
118 {TERMINAL_LITERAL_NULL, "LITERAL_NULL"},
119 {TERMINAL_LITERAL_FLOAT, "LITERAL_FLOAT"},
120
121 {TERMINAL_LITERAL_INT, "LITERAL_INT"},
122 {TERMINAL_YYEOF, "YYEOF"},
123 {TERMINAL_comment, "comment"},
124 {TERMINAL_single_line_comment, "single_line_comment"},
125 {TERMINAL_whitespace, "whitespace"},
126 {TERMINAL_newline, "newline"},
127 {TERMINAL_file_metadata, "file_metadata"},
128
129 // Syntax Non-terminals
130 {NONTERMINAL_access_modifier, "access_modifier"},
131 {NONTERMINAL_access_qualifier, "access_qualifier"},
132 {NONTERMINAL_argument_expression_list, "argument_expression_list"},
133 {NONTERMINAL_array_length, "array_length"},
134 {NONTERMINAL_class_argument_list, "class_argument_list"},
135 {NONTERMINAL_class_declaration, "class_declaration"},
136 {NONTERMINAL_class_decl_start, "class_decl_start"},
137 {NONTERMINAL_class_definition, "class_definition"},
138 {NONTERMINAL_class_member_declaration, "class_member_declaration"},
139 {NONTERMINAL_class_member_declaration_list, "class_member_declaration_list"},
140
141 {NONTERMINAL_class_member_declaration_method, "class_member_declaration_method"},
142 {NONTERMINAL_class_member_declaration_variable, "class_member_declaration_variable"},
143 {NONTERMINAL_enum_definition, "enum_definition"},
144 {NONTERMINAL_enum_definition_value, "enum_definition_value"},
145 {NONTERMINAL_enum_definition_value_list, "enum_definition_value_list"},
146 {NONTERMINAL_expression, "expression"},
147 {NONTERMINAL_expression_binary, "expression_binary"},
148 {NONTERMINAL_expression_cast, "expression_cast"},
149 {NONTERMINAL_expression_postfix_array_index, "expression_postfix_array_index"},
150 {NONTERMINAL_expression_postfix_arrow, "expression_postfix_arrow"},
151 {NONTERMINAL_expression_postfix_dot, "expression_postfix_dot"},
152 {NONTERMINAL_expression_postfix_function_call, "expression_postfix_function_call"},
153 {NONTERMINAL_expression_postfix_incdec, "expression_postfix_incdec"},
154 {NONTERMINAL_expression_primary_identifier, "expression_primary_identifier"},
155 {NONTERMINAL_expression_primary_literal_bool, "expression_primary_literal_bool"},
156 {NONTERMINAL_expression_primary_literal_char, "expression_primary_literal_char"},
157 {NONTERMINAL_expression_primary_literal_float, "expression_primary_literal_float"},
158 {NONTERMINAL_expression_primary_literal_int, "expression_primary_literal_int"},
159 {NONTERMINAL_expression_primary_literal_null, "expression_primary_literal_null"},
160 {NONTERMINAL_expression_primary_literal_string, "expression_primary_literal_string"},
161 {NONTERMINAL_expression_primary_nested, "expression_primary_nested"},
162 {NONTERMINAL_expression_trinary, "expression_trinary"},
163 {NONTERMINAL_expression_unary_prefix, "expression_unary_prefix"},
164 {NONTERMINAL_expression_unary_sizeof_type, "expression_unary_sizeof_type"},
165 {NONTERMINAL_file_statement, "file_statement"},
166 {NONTERMINAL_file_statement_function_declaration, "file_statement_function_declaration"},
167 {NONTERMINAL_file_statement_global_definition, "file_statement_global_definition"},
168 {NONTERMINAL_file_statement_list, "file_statement_list"},
169 {NONTERMINAL_file_statement_namespace, "file_statement_namespace"},
170 {NONTERMINAL_file_statement_using, "file_statement_using"},
171 {NONTERMINAL_function_definition_arg, "function_definition_arg"},
172 {NONTERMINAL_function_definition_arg_list, "function_definition_arg_list"},
173 {NONTERMINAL_global_initializer, "global_initializer"},
174 {NONTERMINAL_global_initializer_addressof_expression_primary, "global_initializer_addressof_expression_primary"},
175 {NONTERMINAL_global_initializer_expression_primary, "global_initializer_expression_primary"},
176 {NONTERMINAL_global_initializer_struct_initializer_list, "global_initializer_struct_initializer_list"},
177 {NONTERMINAL_initializer_expression, "initializer_expression"},
178 {NONTERMINAL_namespace_declaration, "namespace_declaration"},
179 {NONTERMINAL_scope_body, "scope_body"},
180 {NONTERMINAL_statement, "statement"},
181 {NONTERMINAL_statement_block, "statement_block"},
182 {NONTERMINAL_statement_break, "statement_break"},
183 {NONTERMINAL_statement_continue, "statement_continue"},
184 {NONTERMINAL_statement_expression, "statement_expression"},
185 {NONTERMINAL_statement_for, "statement_for"},
186 {NONTERMINAL_statement_goto, "statement_goto"},
187 {NONTERMINAL_statement_ifelse, "statement_ifelse"},
188 {NONTERMINAL_statement_label, "statement_label"},
189 {NONTERMINAL_statement_list, "statement_list"},
190 {NONTERMINAL_statement_return, "statement_return"},
191 {NONTERMINAL_statement_switch, "statement_switch"},
192 {NONTERMINAL_statement_switch_block, "statement_switch_block"},
193 {NONTERMINAL_statement_switch_content, "statement_switch_content"},
194 {NONTERMINAL_statement_variable_declaration, "statement_variable_declaration"},
195 {NONTERMINAL_statement_while, "statement_while"},
196 {NONTERMINAL_struct_initializer, "struct_initializer"},
197 {NONTERMINAL_struct_initializer_list, "struct_initializer_list"},
198 {NONTERMINAL_terminal, "terminal"},
199 {NONTERMINAL_translation_unit, "translation_unit"},
200 {NONTERMINAL_type_definition, "type_definition"},
201 {NONTERMINAL_type_name, "type_name"},
202 {NONTERMINAL_type_specifier, "type_specifier"},
203 {NONTERMINAL_type_specifier_array, "type_specifier_array"},
204 {NONTERMINAL_type_specifier_call_args, "type_specifier_call_args"},
205 {NONTERMINAL_type_specifier_function_pointer, "type_specifier_function_pointer"},
206 {NONTERMINAL_type_specifier_pointer_to, "type_specifier_pointer_to"},
207 {NONTERMINAL_type_specifier_reference_to, "type_specifier_reference_to"},
208 {NONTERMINAL_type_specifier_simple, "type_specifier_simple"},
209 {NONTERMINAL_type_specifier_template, "type_specifier_template"},
210 {NONTERMINAL_unsafe_modifier, "unsafe_modifier"},
211 {NONTERMINAL_using_as, "using_as"},
212
213 {END_OF_TOKENS, "END_OF_TOKENS"}
214 };
215
216 48 JFormatTree::JFormatTree()
217 48 : indent(0)
218 {
219 48 size_t idx = 0;
220 while (true) {
221 8160 const TokenName & tn = token_names[idx];
222
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 8112 times.
8160 if (tn.token == END_OF_TOKENS) {
223 48 break;
224 }
225 16224 token_map.insert(std::pair(tn.token, std::string(tn.name)));
226 8112 idx++;
227 8112 };
228 48 }
229 48 JFormatTree::~JFormatTree()
230 48 {}
231
232 25948 void JFormatTree::print_indent(void)
233 {
234
2/2
✓ Branch 0 taken 471652 times.
✓ Branch 1 taken 25948 times.
497600 for (int i = 0; i < 2*indent; i++) {
235 471652 printf(" ");
236 }
237 25948 }
238
239 12 void JFormatTree::print_comment_multi_line(const TerminalNonSyntax & node)
240 {
241 12 print_indent();
242 12 printf("<comment-multi-line>\n");
243 12 indent++;
244 12 print_indent();
245 12 printf("%s\n", xml_to_cdata(node.get_data()).c_str());
246 12 indent--;
247 12 print_indent();
248 12 printf("</comment-multi-line>\n");
249 12 }
250
251 96 void JFormatTree::print_comment_single_line(const TerminalNonSyntax & node)
252 {
253 96 print_indent();
254 96 printf("<comment-single-line>\n");
255 96 indent++;
256 96 print_indent();
257 96 printf("%s\n", xml_to_cdata(node.get_data()).c_str());
258 96 indent--;
259 96 print_indent();
260 96 printf("</comment-single-line>\n");
261 96 }
262
263 3826 void JFormatTree::print_whitespace(const TerminalNonSyntax & node)
264 {
265 3826 print_indent();
266 3826 printf("<whitespace>%s</whitespace>\n", xml_escape_whitespace(node.get_data()).c_str());
267 3826 }
268
269 4 void JFormatTree::print_file_metadata(const TerminalNonSyntax & node)
270 {
271 4 printf("<metadata>%s</metadata>", xml_to_cdata(node.get_data()).c_str());
272 4 }
273
274
275 3938 void JFormatTree::print_non_syntax(const TerminalNonSyntax & node)
276 {
277
4/5
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 3826 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
3938 switch (node.get_type()) {
278 12 case TerminalNonSyntax::Type::EXTRA_COMMENT_MULTI_LINE:
279 12 print_comment_multi_line(node);
280 12 break;
281 96 case TerminalNonSyntax::Type::EXTRA_COMMENT_SINGLE_LINE:
282 96 print_comment_single_line(node);
283 96 break;
284 3826 case TerminalNonSyntax::Type::EXTRA_WHITESPACE:
285 3826 print_whitespace(node);
286 3826 break;
287 4 case TerminalNonSyntax::Type::EXTRA_FILE_METADATA:
288 4 print_file_metadata(node);
289 4 break;
290 }
291 3938 }
292
293 std::string
294 12474 JFormatTree::get_token_name(TokenID token) const
295 {
296 12474 const auto & it = token_map.find(token);
297
2/2
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 12388 times.
12474 if (it == token_map.end()) {
298 172 return std::string("Unknown");
299 }
300 12388 return it->second;
301 }
302
303
304 12474 int JFormatTree::process(const SyntaxNode & node)
305 {
306 12474 print_indent();
307 12474 std::string token_type = get_token_name(node.get_type());
308 12474 printf("<node type='%s'", xml_escape_attribute(token_type).c_str());
309
2/2
✓ Branch 1 taken 4620 times.
✓ Branch 2 taken 7854 times.
12474 if (node.has_data<Terminal>()) {
310 4620 const Terminal & terminal = node.get_data<Terminal>();
311
1/2
✓ Branch 2 taken 4620 times.
✗ Branch 3 not taken.
4620 if (terminal.get_source_ref().get_line() > 0) {
312 4620 printf(" line='%ld' column='%ld'", terminal.get_source_ref().get_line(), terminal.get_source_ref().get_column());
313 }
314
2/2
✓ Branch 2 taken 4568 times.
✓ Branch 3 taken 52 times.
4620 if (terminal.get_value().length() != 0) {
315 4568 if (terminal.get_type() == TERMINAL_IDENTIFIER ||
316
6/6
✓ Branch 0 taken 3608 times.
✓ Branch 1 taken 960 times.
✓ Branch 3 taken 3170 times.
✓ Branch 4 taken 438 times.
✓ Branch 5 taken 1406 times.
✓ Branch 6 taken 3162 times.
7738 terminal.get_type() == TERMINAL_TYPE_NAME ||
317
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 3162 times.
3170 terminal.get_type() == TERMINAL_NAMESPACE_NAME
318 ) {
319 2812 printf(" value='%s' fq='%s'",
320 2812 xml_escape_attribute(terminal.get_value()).c_str(),
321 2812 xml_escape_attribute(terminal.get_fully_qualified_name()).c_str()
322 );
323 }
324 else {
325 3162 printf(" value='%s'", xml_escape_attribute(terminal.get_value()).c_str());
326 }
327 }
328 }
329
330 12474 bool has_non_syntax_children = false;
331
2/2
✓ Branch 1 taken 4620 times.
✓ Branch 2 taken 7854 times.
12474 if (node.has_data<Terminal>()) {
332 4620 const Terminal & maybe_terminal = node.get_data<Terminal>();
333 4620 has_non_syntax_children = maybe_terminal.non_syntax.size() != 0;
334 }
335
336
6/6
✓ Branch 2 taken 5710 times.
✓ Branch 3 taken 6764 times.
✓ Branch 4 taken 3150 times.
✓ Branch 5 taken 2560 times.
✓ Branch 6 taken 3150 times.
✓ Branch 7 taken 9324 times.
12474 if (node.get_children().size() == 0 && !has_non_syntax_children) {
337 3150 printf("/>\n");
338 }
339 else {
340 9324 printf(">\n");
341 9324 indent++;
342
2/2
✓ Branch 1 taken 2560 times.
✓ Branch 2 taken 6764 times.
9324 if (node.has_data<Terminal>()) {
343 2560 const Terminal & terminal = node.get_data<Terminal>();
344
2/2
✓ Branch 5 taken 3938 times.
✓ Branch 6 taken 2560 times.
6498 for (const auto &non_syntax : terminal.non_syntax) {
345 3938 print_non_syntax(*non_syntax);
346 }
347 }
348
2/2
✓ Branch 6 taken 12426 times.
✓ Branch 7 taken 9324 times.
21750 for (auto child : node.get_children()) {
349 12426 process(child);
350 }
351 9324 indent--;
352 9324 print_indent();
353 9324 printf("</node>\n");
354 }
355 24948 return 0;
356 12474 }
357