GCC Code Coverage Report


Directory: src/
File: src/cmdline/jformat-tree.cpp
Date: 2025-10-15 09:43:47
Exec Total Coverage
Lines: 98 98 100.0%
Functions: 10 10 100.0%
Branches: 37 39 94.9%

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