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 |