File Coverage

lib/SPVM/Builder/src/spvm_toke.c
Criterion Covered Total %
statement 1469 1510 97.2
branch 888 970 91.5
condition n/a
subroutine n/a
pod n/a
total 2357 2480 95.0


line stmt bran cond sub pod time code
1             // Copyright (c) 2023 Yuki Kimoto
2             // MIT License
3              
4             #include
5             #include
6             #include
7             #include
8             #include
9             #include
10             #include
11              
12             #include "spvm_toke.h"
13             #include "spvm_compiler.h"
14             #include "spvm_yacc_util.h"
15             #include "spvm_yacc.h"
16             #include "spvm_op.h"
17             #include "spvm_allocator.h"
18             #include "spvm_constant.h"
19             #include "spvm_var.h"
20             #include "spvm_list.h"
21             #include "spvm_hash.h"
22             #include "spvm_attribute.h"
23             #include "spvm_type.h"
24             #include "spvm_use.h"
25             #include "spvm_basic_type.h"
26             #include "spvm_var_decl.h"
27             #include "spvm_string_buffer.h"
28             #include "spvm_method.h"
29             #include "spvm_string.h"
30             #include "spvm_class_file.h"
31              
32             // Get token
33 15607212           int SPVM_yylex(SPVM_YYSTYPE* yylvalp, SPVM_COMPILER* compiler) {
34            
35             // Default source is a empty string
36 15607212 100         if (compiler->ch_ptr == NULL) {
37 2111           compiler->ch_ptr = "";
38             }
39            
40             // Save buf pointer
41 15607212           compiler->token_begin_ch_ptr = compiler->ch_ptr;
42            
43             // Before character is "-". This is used by the numeric literal that has "-".
44 15607212           int32_t before_char_is_minus = 0;
45            
46             // Before token is arrow
47 15607212           int32_t before_token_is_arrow = compiler->before_token_is_arrow;
48 15607212           compiler->before_token_is_arrow = 0;
49            
50 15607212           int32_t previous_token_is_heredoc = compiler->previous_token_is_heredoc;
51 15607212           compiler->previous_token_is_heredoc = 0;
52            
53             // Expect method name
54 15607212           int32_t expect_method_name = compiler->expect_method_name;
55 15607212           compiler->expect_method_name = 0;
56            
57             // Expect field name
58 15607212           int32_t expect_field_name = compiler->expect_field_name;
59 15607212           compiler->expect_field_name = 0;
60            
61             // Variable expansion state
62 15607212           int32_t var_expansion_state = compiler->var_expansion_state;
63 15607212           compiler->var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_NOT_STARTED;
64            
65 15607212           int32_t end_of_file = compiler->end_of_file;
66 15607212           compiler->end_of_file = 0;
67            
68             while(1) {
69            
70             // Load class file
71 39730029           int32_t source_index = compiler->ch_ptr - compiler->current_class_content;
72 39730029 100         if (!compiler->current_class_content || source_index >= compiler->current_class_content_length) {
    100          
73            
74             // End of file
75 72377 100         if (!end_of_file) {
76 34392           compiler->end_of_file = 1;
77 34392           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_END_OF_FILE);
78 34392           yylvalp->opval = op;
79 34392           return END_OF_FILE;
80             }
81            
82             // Load class file
83 37985           int32_t success = SPVM_TOKE_load_class_file(compiler);
84            
85 37985 100         if (!success) {
86 3529           return success;
87             }
88            
89 34456 50         if (compiler->current_class_content) {
90 34456           continue;
91             }
92             else {
93 0           return 0;
94             }
95             }
96            
97             // "aaa $foo bar" is interupted "aaa $foo" . " bar"
98 39657652 100         if (compiler->ch_ptr == compiler->next_string_literal_ch_ptr) {
99 8526           compiler->next_string_literal_ch_ptr = NULL;
100 8526           var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_SECOND_CONCAT;
101             }
102            
103             // Current character
104 39657652           char ch = -1;
105            
106             // Variable expansion state
107 39657652 100         if (var_expansion_state > 0) {
108 34104           switch (var_expansion_state) {
109             case SPVM_TOKE_C_VAR_EXPANSION_STATE_NOT_STARTED: {
110 0           ch = *compiler->ch_ptr;
111 0           break;
112             }
113             case SPVM_TOKE_C_VAR_EXPANSION_STATE_FIRST_CONCAT: {
114 8526           ch = '.';
115 8526           break;
116             }
117             case SPVM_TOKE_C_VAR_EXPANSION_STATE_VAR: {
118 8526           ch = *compiler->ch_ptr;
119 8526           break;
120             }
121             case SPVM_TOKE_C_VAR_EXPANSION_STATE_SECOND_CONCAT: {
122 8526           ch = '.';
123 8526           break;
124             }
125             case SPVM_TOKE_C_VAR_EXPANSION_STATE_BEGIN_NEXT_STRING_LITERAL: {
126 8526           ch = '"';
127 8526           break;
128             }
129             default: {
130 34104           assert(0);
131             }
132             }
133             }
134 39623548 100         else if (previous_token_is_heredoc) {
135 21           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
136            
137 21           return (int) (uint8_t) ';';
138             }
139             else {
140 39623527           ch = *compiler->ch_ptr;
141             }
142            
143 39657631           switch (ch) {
144             // Skip space character
145             case ' ':
146             case '\t':
147             case '\f':
148             {
149 20929087           compiler->ch_ptr++;
150 20929087           compiler->token_begin_ch_ptr = compiler->ch_ptr;
151 20929087           continue;
152             break;
153             }
154             case '\r':
155             case '\n':
156             {
157 3047549 50         assert(SPVM_TOKE_is_line_terminator(compiler, compiler->ch_ptr));
158            
159 3047549           SPVM_TOKE_parse_line_terminator(compiler, &compiler->ch_ptr);
160            
161 3047549           SPVM_TOKE_increment_current_line(compiler);
162            
163 3047549           compiler->token_begin_ch_ptr = compiler->ch_ptr;
164 3047549           continue;
165             break;
166             }
167             // Cancat
168             case '.': {
169             // Variable expansion "." before the variable
170 36804 100         if (var_expansion_state == SPVM_TOKE_C_VAR_EXPANSION_STATE_FIRST_CONCAT) {
171 8526           compiler->var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_VAR;
172 8526           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CONCAT);
173 8526           return '.';
174             }
175             // Variable expansion second "." after the variable
176 28278 100         else if (var_expansion_state == SPVM_TOKE_C_VAR_EXPANSION_STATE_SECOND_CONCAT) {
177 8526           compiler->var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_BEGIN_NEXT_STRING_LITERAL;
178 8526           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CONCAT);
179 8526           return '.';
180             }
181             else {
182 19752           compiler->ch_ptr++;
183 19752 100         if (*compiler->ch_ptr == '=') {
184 8379           compiler->ch_ptr++;
185 8379           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
186 8379           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_CONCAT;
187            
188 8379           yylvalp->opval = op_special_assign;
189            
190 8379           return SPECIAL_ASSIGN;
191             }
192             else {
193 11373           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CONCAT);
194 11373           return '.';
195             }
196             }
197             break;
198             }
199             // Addition
200             case '+': {
201 186798           compiler->ch_ptr++;
202            
203 186798 100         if (*compiler->ch_ptr == '+') {
204 80994           compiler->ch_ptr++;
205 80994           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
206 80994           return INC;
207             }
208 105804 100         else if (*compiler->ch_ptr == '=') {
209 5867           compiler->ch_ptr++;
210 5867           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
211 5867           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_ADD;
212            
213 5867           yylvalp->opval = op_special_assign;
214            
215 5867           return SPECIAL_ASSIGN;
216             }
217             else {
218 99937           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
219 99937           return '+';
220             }
221             break;
222             }
223             // Subtract
224             case '-': {
225 602936           compiler->ch_ptr++;
226            
227             // "-" is the sign of a numeric literal
228 602936 100         if (isdigit(*compiler->ch_ptr)) {
229 45102           before_char_is_minus = 1;
230 45102           continue;
231             }
232 557834 100         else if (*compiler->ch_ptr == '>') {
233 486204           compiler->ch_ptr++;
234 486204           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
235 486204           compiler->expect_method_name = 1;
236 486204           compiler->before_token_is_arrow = 1;
237            
238 486204           return ARROW;
239             }
240 71630 100         else if (*compiler->ch_ptr == '-') {
241 10201           compiler->ch_ptr++;
242 10201           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
243 10201           return DEC;
244             }
245 61429 100         else if (*compiler->ch_ptr == '=') {
246 14           compiler->ch_ptr++;
247 14           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
248 14           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_SUBTRACT;
249            
250 14           yylvalp->opval = op_special_assign;
251            
252 14           return SPECIAL_ASSIGN;
253             }
254             else {
255 61415           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
256 61415           return '-';
257             }
258             break;
259             }
260             // Multiply
261             case '*': {
262 10516           compiler->ch_ptr++;
263            
264 10516 100         if (*compiler->ch_ptr == '=') {
265 537           compiler->ch_ptr++;
266 537           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
267 537           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_MULTIPLY;
268            
269 537           yylvalp->opval = op_special_assign;
270            
271 537           return SPECIAL_ASSIGN;
272             }
273             // * is used in MULTIPLY operator or type reference
274             else {
275 9979           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
276 9979           yylvalp->opval = op;
277 9979           return '*';
278             }
279             }
280             // Divide
281             case '/': {
282 5412           compiler->ch_ptr++;
283            
284 5412 100         if (*compiler->ch_ptr == '=') {
285 14           compiler->ch_ptr++;
286 14           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
287 14           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_DIVIDE;
288            
289 14           yylvalp->opval = op_special_assign;
290            
291 14           return SPECIAL_ASSIGN;
292             }
293             else {
294 5398           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DIVIDE);
295 5398           yylvalp->opval = op;
296 5398           return DIVIDE;
297             }
298             }
299             case '%': {
300 2182           compiler->ch_ptr++;
301 2182 100         if (*compiler->ch_ptr == '=') {
302 10           compiler->ch_ptr++;
303 10           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
304 10           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_REMAINDER;
305            
306 10           yylvalp->opval = op_special_assign;
307            
308 10           return SPECIAL_ASSIGN;
309             }
310             else {
311 2172           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_REMAINDER);
312 2172           yylvalp->opval = op;
313 2172           return REMAINDER;
314             }
315             }
316             case '^': {
317 46           compiler->ch_ptr++;
318 46 100         if (*compiler->ch_ptr == '=') {
319 10           compiler->ch_ptr++;
320 10           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
321 10           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_BIT_XOR;
322            
323 10           yylvalp->opval = op_special_assign;
324            
325 10           return SPECIAL_ASSIGN;
326             }
327             else {
328 36           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BIT_XOR);
329 36           yylvalp->opval = op;
330 36           return BIT_XOR;
331             }
332             }
333             case '|': {
334 8144           compiler->ch_ptr++;
335             // Or
336 8144 100         if (*compiler->ch_ptr == '|') {
337 8092           compiler->ch_ptr++;
338 8092           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LOGICAL_OR);
339 8092           yylvalp->opval = op;
340 8092           return LOGICAL_OR;
341             }
342 52 100         else if (*compiler->ch_ptr == '=') {
343 10           compiler->ch_ptr++;
344 10           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
345 10           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_BIT_OR;
346            
347 10           yylvalp->opval = op_special_assign;
348            
349 10           return SPECIAL_ASSIGN;
350             }
351             else {
352 42           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BIT_OR);
353 42           yylvalp->opval = op;
354 42           return BIT_OR;
355             }
356             break;
357             }
358             case '&': {
359 99972           compiler->ch_ptr++;
360             // &&
361 99972 100         if (*compiler->ch_ptr == '&') {
362 48421           compiler->ch_ptr++;
363 48421           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LOGICAL_AND);
364 48421           yylvalp->opval = op;
365 48421           return LOGICAL_AND;
366             }
367             // &=
368 51551 100         else if (*compiler->ch_ptr == '=') {
369 10           compiler->ch_ptr++;
370 10           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
371 10           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_BIT_AND;
372            
373 10           yylvalp->opval = op_special_assign;
374            
375 10           return SPECIAL_ASSIGN;
376             }
377             // &foo - Current module
378 51541 100         else if (isalpha(*compiler->ch_ptr) || *compiler->ch_ptr == '_') {
    100          
379 50437           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CURRENT_CLASS);
380 50437           compiler->expect_method_name = 1;
381 50437           return CURRENT_CLASS;
382             }
383             // &
384             else {
385 1104           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BIT_AND);
386 1104           yylvalp->opval = op;
387 1104           return BIT_AND;
388             }
389             break;
390             }
391             // Comment
392             case '#': {
393 66617           compiler->ch_ptr++;
394             while(1) {
395 1330217           int32_t is_line_terminator = SPVM_TOKE_is_line_terminator(compiler, compiler->ch_ptr);
396            
397 1330217 100         if (is_line_terminator) {
398 66611           SPVM_TOKE_parse_line_terminator(compiler, &compiler->ch_ptr);
399 66611           SPVM_TOKE_increment_current_line(compiler);
400             }
401            
402 1330217 100         if (is_line_terminator || *compiler->ch_ptr == '\0') {
    100          
403             break;
404             }
405             else {
406 1263600           compiler->ch_ptr++;
407             }
408 1263600           }
409            
410 66617           continue;
411             break;
412             }
413             case '=': {
414             // POD
415 703678 50         if (compiler->ch_ptr == compiler->current_class_content || *(compiler->ch_ptr - 1) == '\n') {
    100          
416             while (1) {
417 232           compiler->ch_ptr++;
418 232 100         if (*compiler->ch_ptr == '\n') {
419 22           compiler->current_line++;
420             }
421            
422 232 100         if (*compiler->ch_ptr == '\0') {
423 1           break;
424             }
425            
426 231 100         if (
427 231           *compiler->ch_ptr == '='
428 7 100         && strncmp(compiler->ch_ptr + 1, "cut", 3) == 0
429 5 50         && (*(compiler->ch_ptr + 4) == '\0' || SPVM_TOKE_is_white_space(compiler, *(compiler->ch_ptr + 4)))
    50          
430             )
431             {
432 5           compiler->ch_ptr += 4;
433            
434             while (1) {
435 11 100         if (*compiler->ch_ptr == '\n' || *compiler->ch_ptr == '\0') {
    50          
436             break;
437             }
438 6           compiler->ch_ptr++;
439 6           }
440 5           break;
441             }
442 226           }
443 6           continue;
444             }
445             else {
446 703672           compiler->ch_ptr++;
447            
448             // ==
449 703672 100         if (*compiler->ch_ptr == '=') {
450 68531           compiler->ch_ptr++;
451 68531           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_EQ);
452 68531           yylvalp->opval = op;
453 68531           return NUMEQ;
454             }
455             // =>
456 635141 100         if (*compiler->ch_ptr == '>') {
457 4973           compiler->ch_ptr++;
458 4973           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
459 4973           yylvalp->opval = op;
460 4973           return ',';
461             }
462             // =
463             else {
464 630168           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ASSIGN);
465 630168           yylvalp->opval = op;
466 630168           return ASSIGN;
467             }
468             }
469             break;
470             }
471             case '<': {
472 161827           compiler->ch_ptr++;
473            
474 161827 100         if (*compiler->ch_ptr == '<') {
475 79           compiler->ch_ptr++;
476             // <<=
477 79 100         if (*compiler->ch_ptr == '=') {
478 10           compiler->ch_ptr++;
479 10           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
480 10           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_LEFT_SHIFT;
481            
482 10           yylvalp->opval = op_special_assign;
483            
484 10           return SPECIAL_ASSIGN;
485             }
486             // Here document
487             // <<'
488 69 100         else if (*compiler->ch_ptr == '\'') {
489 25           compiler->ch_ptr++;
490            
491 25           const char* heredoc_name_start_ptr = compiler->ch_ptr;
492            
493 146 100         while(isalnum(*compiler->ch_ptr) || *compiler->ch_ptr == '_') {
    100          
494 121           compiler->ch_ptr++;
495             }
496            
497 25           int32_t heredoc_name_length = (compiler->ch_ptr - heredoc_name_start_ptr);
498            
499 25 100         if (heredoc_name_length == 0) {
500 1           SPVM_COMPILER_error(compiler, "The length of a here document name must be greater than or equal to 0.\n at %s line %d", compiler->current_file, compiler->current_line);
501 1           return 0;
502             }
503            
504 24           char* heredoc_name = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, heredoc_name_length + 1);
505 24           memcpy(heredoc_name, heredoc_name_start_ptr, heredoc_name_length);
506 24           heredoc_name[heredoc_name_length] = '\0';
507            
508 24           int32_t comile_error = 0;
509 24 100         if (isdigit(heredoc_name[0])) {
510 1           SPVM_COMPILER_error(compiler, "A here document name cannot start with a number.\n at %s line %d", compiler->current_file, compiler->current_line);
511             }
512 23 100         else if (strstr(heredoc_name, "__")) {
513 1           SPVM_COMPILER_error(compiler, "A here document name cannot contain \"__\".\n at %s line %d", compiler->current_file, compiler->current_line);
514             }
515 22 50         else if (!(*(compiler->ch_ptr) == '\'' && *(compiler->ch_ptr + 1) == ';' && SPVM_TOKE_is_line_terminator(compiler, compiler->ch_ptr + 2))) {
    100          
    50          
516 1           SPVM_COMPILER_error(compiler, "The first line of the here document must end with \"';\" + a line terminator.\n at %s line %d", compiler->current_file, compiler->current_line);
517             }
518            
519 24 100         if (compiler->error_messages->length == 0) {
520            
521 21           compiler->ch_ptr += 2;
522            
523 21           SPVM_TOKE_parse_line_terminator(compiler, &compiler->ch_ptr);
524 21           SPVM_TOKE_increment_current_line(compiler);
525            
526 21           char* heredoc_end_ch_ptr = compiler->ch_ptr;
527            
528 21           int32_t heredoc_length = 0;
529 21           int32_t previous_is_line_terminator = 1;
530 21           char* heredoc_ptr = compiler->ch_ptr;
531 21           int32_t heredoc_begin_line = compiler->current_line;
532             while (1) {
533 182 100         if (previous_is_line_terminator) {
534 53           int32_t end_of_heredoc = 0;
535 53 100         if (strncmp(compiler->ch_ptr, heredoc_name, heredoc_name_length) == 0 && SPVM_TOKE_is_line_terminator(compiler, compiler->ch_ptr + heredoc_name_length)) {
    50          
536 21           compiler->ch_ptr += heredoc_name_length;
537 21           SPVM_TOKE_parse_line_terminator(compiler, &compiler->ch_ptr);
538 21           SPVM_TOKE_increment_current_line(compiler);
539 21           break;
540             }
541             }
542            
543 161           int32_t is_line_terminator = SPVM_TOKE_is_line_terminator(compiler, compiler->ch_ptr);
544            
545 161 100         if (is_line_terminator) {
546 32           SPVM_TOKE_parse_line_terminator(compiler, &compiler->ch_ptr);
547 32           SPVM_TOKE_increment_current_line(compiler);
548            
549 32           heredoc_length++;
550 32           previous_is_line_terminator = 1;
551             }
552 129 50         else if (*compiler->ch_ptr == '\0') {
553 0           SPVM_COMPILER_error(compiler, "A here document must end with its here document name + a line terminator.\n at %s line %d", compiler->current_file, heredoc_begin_line);
554 0           break;
555             }
556             else {
557 129           heredoc_length++;
558 129           compiler->ch_ptr++;
559 129           previous_is_line_terminator = 0;
560             }
561 161           }
562            
563 21 50         if (compiler->error_messages->length == 0) {
564 21           char* heredoc = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, heredoc_length + 1);
565            
566 21           int32_t heredoc_index = 0;
567 182 100         while (heredoc_index < heredoc_length) {
568 161           int32_t is_line_terminator = SPVM_TOKE_is_line_terminator(compiler, heredoc_ptr);
569            
570 161 100         if (is_line_terminator) {
571 32           heredoc[heredoc_index] = '\n';
572            
573 32           SPVM_TOKE_parse_line_terminator(compiler, &heredoc_ptr);
574            
575 32           heredoc_index++;
576             }
577 129 50         else if (*heredoc_ptr == '\0') {
578 0           assert(0);
579             }
580             else {
581 129           heredoc[heredoc_index] = *heredoc_ptr;
582 129           heredoc_ptr++;
583 129           heredoc_index++;
584             }
585             }
586            
587 21           SPVM_OP* op_constant = SPVM_OP_new_op_constant_string(compiler, heredoc, heredoc_length, compiler->current_file, compiler->current_line);
588            
589 21           yylvalp->opval = op_constant;
590            
591 21           compiler->previous_token_is_heredoc = 1;
592            
593 21           SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, heredoc);
594             }
595             }
596            
597 24           SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, heredoc_name);
598            
599 24 100         if (compiler->error_messages->length > 0) {
600 3           return 0;
601             }
602            
603 21           return CONSTANT;
604             }
605             // <<
606             else {
607 44           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LEFT_SHIFT);
608 44           yylvalp->opval = op;
609 44           return SHIFT;
610             }
611             }
612             // <=
613 161748 100         else if (*compiler->ch_ptr == '=') {
614 81284           compiler->ch_ptr++;
615            
616             // <=>
617 81284 100         if (*compiler->ch_ptr == '>') {
618 6488           compiler->ch_ptr++;
619 6488           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_CMP);
620 6488           yylvalp->opval = op;
621 6488           return NUMERIC_CMP;
622             }
623             // <=
624             else {
625 74796           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_LE);
626 74796           yylvalp->opval = op;
627 74796           return NUMLE;
628             }
629             }
630             // <
631             else {
632 80464           compiler->ch_ptr++;
633 80464           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_LT);
634 80464           yylvalp->opval = op;
635 80464           return NUMLT;
636             }
637             break;
638             }
639             case '>': {
640 90950           compiler->ch_ptr++;
641            
642 90950 100         if (*compiler->ch_ptr == '>') {
643 76           compiler->ch_ptr++;
644 76 100         if (*compiler->ch_ptr == '>') {
645 38           compiler->ch_ptr++;
646             // >>>=
647 38 100         if (*compiler->ch_ptr == '=') {
648 10           compiler->ch_ptr++;
649 10           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
650 10           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_RIGHT_LOGICAL_SHIFT;
651            
652 10           yylvalp->opval = op_special_assign;
653            
654 10           return SPECIAL_ASSIGN;
655             }
656             // >>>
657             else {
658 28           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_RIGHT_LOGICAL_SHIFT);
659 28           yylvalp->opval = op;
660 28           return SHIFT;
661             }
662             }
663             else {
664             // >>=
665 38 100         if (*compiler->ch_ptr == '=') {
666 10           compiler->ch_ptr++;
667 10           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
668 10           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_RIGHT_ARITHMETIC_SHIFT;
669            
670 10           yylvalp->opval = op_special_assign;
671            
672 10           return SPECIAL_ASSIGN;
673             }
674             // >>
675             else {
676 28           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_RIGHT_ARITHMETIC_SHIFT);
677 28           yylvalp->opval = op;
678 28           return SHIFT;
679             }
680             }
681             }
682             // >=
683 90874 100         else if (*compiler->ch_ptr == '=') {
684 69734           compiler->ch_ptr++;
685 69734           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_GE);
686 69734           yylvalp->opval = op;
687 69734           return NUMGE;
688             }
689             // >
690             else {
691 21140           compiler->ch_ptr++;
692 21140           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_GT);
693 21140           yylvalp->opval = op;
694 21140           return NUMGT;
695             }
696             break;
697             }
698             case '!': {
699 21207           compiler->ch_ptr++;
700            
701 21207 100         if (*compiler->ch_ptr == '=') {
702 18050           compiler->ch_ptr++;
703 18050           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_NE);
704 18050           yylvalp->opval = op;
705 18050           return NUMNE;
706             }
707             else {
708 3157           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LOGICAL_NOT);
709 3157           yylvalp->opval = op;
710 3157           return LOGICAL_NOT;
711             }
712             break;
713             }
714             case '~': {
715 38           compiler->ch_ptr++;
716 38           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BIT_NOT);
717 38           yylvalp->opval = op;
718 38           return BIT_NOT;
719             break;
720             }
721             // Character literals
722             case '\'': {
723 49656           compiler->ch_ptr++;
724 49656           char ch = 0;
725            
726 49656 100         if (*compiler->ch_ptr == '\'') {
727 2           SPVM_COMPILER_error(compiler, "The character literal cannnot be empty.\n at %s line %d", compiler->current_file, compiler->current_line);
728 2           compiler->ch_ptr++;
729             }
730             else {
731 49654 100         if (*compiler->ch_ptr == '\\') {
732 3521           compiler->ch_ptr++;
733 3521 100         if (*compiler->ch_ptr == 'a') {
734 2           ch = 0x07; // BEL
735 2           compiler->ch_ptr++;
736             }
737 3519 100         else if (*compiler->ch_ptr == 't') {
738 7           ch = 0x09; // HT
739 7           compiler->ch_ptr++;
740             }
741 3512 100         else if (*compiler->ch_ptr == 'n') {
742 1051           ch = 0x0a; //
743 1051           compiler->ch_ptr++;
744             }
745 2461 100         else if (*compiler->ch_ptr == 'f') {
746 5           ch = 0x0c; // FF
747 5           compiler->ch_ptr++;
748             }
749 2456 100         else if (*compiler->ch_ptr == 'r') {
750 528           ch = 0x0d; // LF
751 528           compiler->ch_ptr++;
752             }
753 1928 100         else if (*compiler->ch_ptr == '\'') {
754 3           ch = 0x27; // '
755 3           compiler->ch_ptr++;
756             }
757 1925 100         else if (*compiler->ch_ptr == '"') {
758 3           ch = 0x22; // "
759 3           compiler->ch_ptr++;
760             }
761 1922 100         else if (*compiler->ch_ptr == '\\') {
762 211           ch = 0x5c; /* \ */
763 211           compiler->ch_ptr++;
764             }
765             // Octal escape character
766 1711 100         else if (SPVM_TOKE_is_octal_number(compiler, *compiler->ch_ptr) || *compiler->ch_ptr == 'o') {
    100          
767 602           ch = SPVM_TOKE_parse_octal_escape(compiler, &compiler->ch_ptr);
768             }
769             // Hex escape character
770 1109 100         else if (*compiler->ch_ptr == 'x') {
771 1107           ch = SPVM_TOKE_parse_hex_escape(compiler, &compiler->ch_ptr);
772             }
773             else {
774 2           SPVM_COMPILER_error(compiler, "\"\\%c\" is the invalid charater literal escape character.\n at %s line %d", *compiler->ch_ptr, compiler->current_file, compiler->current_line);
775 3521           compiler->ch_ptr++;
776             }
777             }
778             else {
779 46133           ch = *compiler->ch_ptr;
780 46133           compiler->ch_ptr++;
781             }
782            
783 49654 100         if (*compiler->ch_ptr == '\'') {
784 49645           compiler->ch_ptr++;
785             }
786             else {
787 9           SPVM_COMPILER_error(compiler, "The character literal must ends with \"'\".\n at %s line %d", compiler->current_file, compiler->current_line);
788             }
789             }
790            
791             // Constant
792 49656           SPVM_OP* op_constant = SPVM_OP_new_op_constant_byte(compiler, ch, compiler->current_file, compiler->current_line);
793            
794 49656           yylvalp->opval = op_constant;
795            
796 49656           return CONSTANT;
797             }
798             // String literal
799             case '"': {
800 195866 100         if (var_expansion_state == SPVM_TOKE_C_VAR_EXPANSION_STATE_BEGIN_NEXT_STRING_LITERAL) {
801 8526           compiler->var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_NOT_STARTED;
802             }
803             else {
804 187340           compiler->ch_ptr++;
805             }
806            
807             // Save current position
808 195866           const char* string_literal_begin_ch_ptr = compiler->ch_ptr;
809            
810 195866           int8_t next_var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_NOT_STARTED;
811            
812             char* string_literal_tmp;
813 195866           int32_t memory_blocks_count_tmp = compiler->current_each_compile_allocator->memory_blocks_count_tmp;
814 195866           int32_t string_literal_length = 0;
815 195866 100         if (*(compiler->ch_ptr) == '"') {
816 6617           string_literal_tmp = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, 1);
817 6617           string_literal_tmp[0] = '\0';
818 6617           compiler->ch_ptr++;
819             }
820             else {
821 189249           int32_t string_literal_finished = 0;
822            
823             while(1) {
824             // End of string literal
825 6180984 100         if (*compiler->ch_ptr == '"') {
826 180719           string_literal_finished = 1;
827             }
828             // Variable expansion
829 6000265 100         else if (*compiler->ch_ptr == '$') {
830 8534 100         if (*(compiler->ch_ptr + 1) == '"') {
831             // Last $ is allowed
832             }
833             else {
834 8529           string_literal_finished = 1;
835 8529           next_var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_FIRST_CONCAT;
836            
837             // Proceed through a variable expansion and find the position of the next string literal
838 8529           char* next_string_literal_ch_ptr = compiler->ch_ptr + 1;
839            
840             // Dereference
841 8529           int32_t var_is_ref = 0;
842 8529 100         if (*next_string_literal_ch_ptr == '$') {
843 8           next_string_literal_ch_ptr++;
844 8           var_is_ref = 1;
845             }
846            
847             // Open brace
848 8529           int32_t var_have_brace = 0;
849 8529 100         if (*next_string_literal_ch_ptr == '{') {
850 17           next_string_literal_ch_ptr++;
851 17           var_have_brace = 1;
852             }
853            
854             // Exception variable
855 8529 100         if (*next_string_literal_ch_ptr == '@') {
856 10           next_string_literal_ch_ptr++;
857 10 100         if (var_have_brace) {
858             // Close brace
859 4 50         if (*next_string_literal_ch_ptr == '}') {
860 10           next_string_literal_ch_ptr++;
861             }
862             }
863             }
864             else {
865            
866             // Proceed through a variable
867             while (1) {
868 70150 100         if (isalnum(*next_string_literal_ch_ptr) || *next_string_literal_ch_ptr == '_') {
    100          
869 61619           next_string_literal_ch_ptr++;
870             }
871 8531 100         else if (*next_string_literal_ch_ptr == ':' && *(next_string_literal_ch_ptr + 1) == ':') {
    100          
872 12           next_string_literal_ch_ptr += 2;
873             }
874 8519 100         else if (*next_string_literal_ch_ptr == '}') {
875 13 50         if (var_have_brace) {
876 13           next_string_literal_ch_ptr++;
877 13           break;
878             }
879             }
880             else {
881 8506           break;
882             }
883 61631           }
884            
885             // Proceed through getting field or getting array element
886             // Array index must be a constant value.
887             // Can't contain space character between "{" and "}" and between "[" and "]"
888 8519 100         if (!var_have_brace && !var_is_ref) {
    100          
889 8502           int32_t has_arrow = 0;
890 8502           int32_t open_getting_field_brace = 0;
891 8502           int32_t open_bracket = 0;
892 8502           int32_t is_first_allow = 1;
893             while (1) {
894 8514 100         if (!has_arrow) {
895 8502 100         if (*next_string_literal_ch_ptr == '-' && *(next_string_literal_ch_ptr + 1) == '>') {
    100          
896 137           has_arrow = 1;
897 137           next_string_literal_ch_ptr += 2;
898             }
899             else {
900             break;
901             }
902             }
903            
904 149 50         if (has_arrow) {
905 149           has_arrow = 0;
906 149 100         if (*next_string_literal_ch_ptr == '{') {
907 29           open_getting_field_brace = 1;
908 29           next_string_literal_ch_ptr++;
909             }
910 120 100         else if (*next_string_literal_ch_ptr == '[') {
911 119           open_bracket = 1;
912 119           next_string_literal_ch_ptr++;
913             }
914             else {
915 1           SPVM_COMPILER_error(compiler, "The character after \"->\" in a string literal must be \"[\" or \"{\".\n at %s line %d", compiler->current_file, compiler->current_line);
916 1           return 0;
917             }
918             }
919            
920 326 100         while (isalnum(*next_string_literal_ch_ptr) || *next_string_literal_ch_ptr == '_') {
    100          
921 178           next_string_literal_ch_ptr++;
922             }
923            
924 148 100         if (open_getting_field_brace) {
925 29 100         if (*next_string_literal_ch_ptr == '}') {
926 28           next_string_literal_ch_ptr++;
927 28           open_getting_field_brace = 0;
928             }
929             else {
930 1           SPVM_COMPILER_error(compiler, "The getting field in a string literal must be closed with \"}\".\n at %s line %d", compiler->current_file, compiler->current_line);
931 1           return 0;
932             }
933             }
934 119 50         else if (open_bracket) {
935 119 100         if (*next_string_literal_ch_ptr == ']') {
936 118           next_string_literal_ch_ptr++;
937 118           open_bracket = 0;
938             }
939             else {
940 1           SPVM_COMPILER_error(compiler, "The getting array element in a string literal must be closed with \"]\".\n at %s line %d", compiler->current_file, compiler->current_line);
941 1           return 0;
942             }
943             }
944             else {
945 0           assert(0);
946             }
947            
948 146 100         if (*next_string_literal_ch_ptr == '-' && *(next_string_literal_ch_ptr + 1) == '>') {
    50          
949 4           next_string_literal_ch_ptr += 2;
950             }
951            
952 146 100         if (!(*next_string_literal_ch_ptr == '{' || *next_string_literal_ch_ptr == '[')) {
    50          
953 134           break;
954             }
955            
956 12           has_arrow = 1;
957 12           }
958             }
959             }
960 8531           compiler->next_string_literal_ch_ptr = next_string_literal_ch_ptr;
961             }
962             }
963             // End of source file
964 5991731 100         else if (*compiler->ch_ptr == '\0') {
965 1           string_literal_finished = 1;
966             }
967 6180981 100         if (string_literal_finished) {
968 189246           break;
969             }
970             else {
971             // Escape is always 2 characters
972 5991735 100         if (*compiler->ch_ptr == '\\') {
973 196246           compiler->ch_ptr += 2;
974             }
975             else {
976 5795489           compiler->ch_ptr++;
977             }
978             }
979 5991735           }
980 189246 100         if (*compiler->ch_ptr == '\0') {
981 1           SPVM_COMPILER_error(compiler, "The string literal must be end with '\"'.\n at %s line %d", compiler->current_file, compiler->current_line);
982 1           return 0;
983             }
984            
985 189245           int32_t string_literal_tmp_len = (int32_t)(compiler->ch_ptr - string_literal_begin_ch_ptr) * 4;
986            
987 189245           compiler->ch_ptr++;
988            
989 189245           string_literal_tmp = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, string_literal_tmp_len + 1);
990             {
991 189245           char* string_literal_ch_ptr = (char*)string_literal_begin_ch_ptr;
992 189245           const char* string_literal_end_ch_ptr = compiler->ch_ptr - 1;
993 6180084 100         while (string_literal_ch_ptr != string_literal_end_ch_ptr) {
994 5990839 100         if (*string_literal_ch_ptr == '\\') {
995 196246           string_literal_ch_ptr++;
996 196246 100         if (*string_literal_ch_ptr == 'a') {
997 8           string_literal_tmp[string_literal_length] = 0x07;
998 8           string_literal_length++;
999 8           string_literal_ch_ptr++;
1000             }
1001 196238 100         else if (*string_literal_ch_ptr == 't') {
1002 17           string_literal_tmp[string_literal_length] = 0x09;
1003 17           string_literal_length++;
1004 17           string_literal_ch_ptr++;
1005             }
1006 196221 100         else if (*string_literal_ch_ptr == 'n') {
1007 6825           string_literal_tmp[string_literal_length] = 0x0a;
1008 6825           string_literal_length++;
1009 6825           string_literal_ch_ptr++;
1010             }
1011 189396 100         else if (*string_literal_ch_ptr == 'f') {
1012 9           string_literal_tmp[string_literal_length] = 0x0c;
1013 9           string_literal_length++;
1014 9           string_literal_ch_ptr++;
1015             }
1016 189387 100         else if (*string_literal_ch_ptr == 'r') {
1017 15           string_literal_tmp[string_literal_length] = 0x0d;
1018 15           string_literal_length++;
1019 15           string_literal_ch_ptr++;
1020             }
1021 189372 100         else if (*string_literal_ch_ptr == '"') {
1022 3155           string_literal_tmp[string_literal_length] = 0x22;
1023 3155           string_literal_length++;
1024 3155           string_literal_ch_ptr++;
1025             }
1026 186217 100         else if (*string_literal_ch_ptr == '$') {
1027 185613           string_literal_tmp[string_literal_length] = 0x24;
1028 185613           string_literal_length++;
1029 185613           string_literal_ch_ptr++;
1030             }
1031 604 100         else if (*string_literal_ch_ptr == '\'') {
1032 9           string_literal_tmp[string_literal_length] = 0x27;
1033 9           string_literal_length++;
1034 9           string_literal_ch_ptr++;
1035             }
1036 595 100         else if (*string_literal_ch_ptr == '\\') {
1037 21           string_literal_tmp[string_literal_length] = 0x5c;
1038 21           string_literal_length++;
1039 21           string_literal_ch_ptr++;
1040             }
1041             // Octal escape character
1042 574 100         else if (SPVM_TOKE_is_octal_number(compiler, *string_literal_ch_ptr) || *string_literal_ch_ptr == 'o') {
    100          
1043 202           ch = SPVM_TOKE_parse_octal_escape(compiler, &string_literal_ch_ptr);
1044            
1045 202           string_literal_tmp[string_literal_length] = ch;
1046 202           string_literal_length++;
1047             }
1048             // A hexadecimal escape character
1049 372 100         else if (*string_literal_ch_ptr == 'x') {
1050 138           ch = SPVM_TOKE_parse_hex_escape(compiler, &string_literal_ch_ptr);
1051            
1052 138           string_literal_tmp[string_literal_length] = ch;
1053 138           string_literal_length++;
1054             }
1055             // Unicode escape character
1056             // Note: "\N" is raw escape character, "\N{" is Unicode escape character
1057 234 100         else if (*string_literal_ch_ptr == 'N' && *(string_literal_ch_ptr + 1) == '{') {
    100          
1058 24           string_literal_ch_ptr++;
1059            
1060 48 50         if (*string_literal_ch_ptr == '{' && *(string_literal_ch_ptr + 1) == 'U' && *(string_literal_ch_ptr + 2) == '+') {
    50          
    50          
1061 24           string_literal_ch_ptr += 3;
1062 24           char* char_start_ptr = string_literal_ch_ptr;
1063 24           int32_t unicode_chars_length = 0;
1064            
1065 125 100         while (SPVM_TOKE_is_hex_number(compiler, *string_literal_ch_ptr)) {
1066 101           string_literal_ch_ptr++;
1067 101           unicode_chars_length++;
1068             }
1069 24 50         if (*string_literal_ch_ptr == '}') {
1070 24           string_literal_ch_ptr++;
1071 24 100         if (unicode_chars_length < 1) {
1072 1           SPVM_COMPILER_error(compiler, "One or more than one hexadecimal numbers must be followed by \"\\N{U+\" of the Unicode escape character.\n at %s line %d", compiler->current_file, compiler->current_line);
1073             }
1074 23 100         else if (unicode_chars_length > 8) {
1075 1           SPVM_COMPILER_error(compiler, "Too big Unicode escape character.\n at %s line %d", compiler->current_file, compiler->current_line);
1076             }
1077             else {
1078 22           int32_t memory_blocks_count_tmp = compiler->current_each_compile_allocator->memory_blocks_count_tmp;
1079 22           char* unicode_chars = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, unicode_chars_length + 1);
1080 22           memcpy(unicode_chars, char_start_ptr, unicode_chars_length);
1081             char *end;
1082 22           int64_t unicode = (int64_t)strtoll(unicode_chars, &end, 16);
1083            
1084 22           int32_t is_valid_utf8_code_point = SPVM_TOKE_is_valid_utf8_code_point(unicode);
1085 22 100         if (is_valid_utf8_code_point) {
1086             char utf8_chars[4];
1087 19           int32_t byte_length = SPVM_TOKE_convert_unicode_codepoint_to_utf8_character(unicode, (uint8_t*)utf8_chars);
1088 80 100         for (int32_t byte_index = 0; byte_index < byte_length; byte_index++) {
1089 61           string_literal_tmp[string_literal_length] = utf8_chars[byte_index];
1090 61           string_literal_length++;
1091             }
1092             }
1093             else {
1094 3           SPVM_COMPILER_error(compiler, "The code point of Unicode escape character must be a Unicode scalar value.\n at %s line %d", compiler->current_file, compiler->current_line);
1095             }
1096 22           SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, unicode_chars);
1097 24 50         assert(compiler->current_each_compile_allocator->memory_blocks_count_tmp == memory_blocks_count_tmp);
1098             }
1099             }
1100             else {
1101 0           SPVM_COMPILER_error(compiler, "A Unicode escape character must be closed by \"}\".\n at %s line %d", compiler->current_file, compiler->current_line);
1102             }
1103             }
1104             else {
1105 0           SPVM_COMPILER_error(compiler, "Invalid Unicode escape character.\n at %s line %d", compiler->current_file, compiler->current_line);
1106             }
1107             }
1108             else {
1109 210 100         switch(*string_literal_ch_ptr) {
1110             case '!':
1111             case '#':
1112             case '%':
1113             case '&':
1114             case '(':
1115             case ')':
1116             case '*':
1117             case '+':
1118             case ',':
1119             case '-':
1120             case '.':
1121             case '/':
1122             case '1':
1123             case '2':
1124             case '3':
1125             case '4':
1126             case '5':
1127             case '6':
1128             case '7':
1129             case '8':
1130             case '9':
1131             case ':':
1132             case ';':
1133             case '<':
1134             case '=':
1135             case '>':
1136             case '?':
1137             case '@':
1138             case 'A':
1139             case 'B':
1140             case 'D':
1141             case 'G':
1142             case 'H':
1143             case 'K':
1144             case 'N':
1145             case 'P':
1146             case 'R':
1147             case 'S':
1148             case 'V':
1149             case 'W':
1150             case 'X':
1151             case 'Z':
1152             case '[':
1153             case ']':
1154             case '^':
1155             case '_':
1156             case '`':
1157             case 'b':
1158             case 'd':
1159             case 'g':
1160             case 'h':
1161             case 'k':
1162             case 'p':
1163             case 's':
1164             case 'v':
1165             case 'w':
1166             case 'z':
1167             case '{':
1168             case '|':
1169             case '}':
1170             case '~':
1171             {
1172 209           string_literal_tmp[string_literal_length] = '\\';
1173 209           string_literal_length++;
1174 209           string_literal_tmp[string_literal_length] = *string_literal_ch_ptr;
1175 209           string_literal_length++;
1176 209           string_literal_ch_ptr++;
1177 209           break;
1178             }
1179             default: {
1180 196246           SPVM_COMPILER_error(compiler, "Invalid string literal escape character \"\\%c\".\n at %s line %d", *string_literal_ch_ptr, compiler->current_file, compiler->current_line);
1181             }
1182             }
1183             }
1184             }
1185             else {
1186 5794593           int32_t is_line_terminator = SPVM_TOKE_is_line_terminator(compiler, string_literal_ch_ptr);
1187            
1188 5794593 100         if (is_line_terminator) {
1189 30           SPVM_TOKE_parse_line_terminator(compiler, &string_literal_ch_ptr);
1190 30           SPVM_TOKE_increment_current_line(compiler);
1191            
1192 30           string_literal_tmp[string_literal_length] = '\n';
1193 30           string_literal_length++;
1194             }
1195             else {
1196 5794563           string_literal_tmp[string_literal_length] = *string_literal_ch_ptr;
1197 5794563           string_literal_length++;
1198 5794563           string_literal_ch_ptr++;
1199             }
1200             }
1201             }
1202             }
1203 189245           string_literal_tmp[string_literal_length] = '\0';
1204             }
1205            
1206 195862           SPVM_STRING* string_literal_string = SPVM_STRING_new(compiler, string_literal_tmp, string_literal_length);
1207 195862           const char* string_literal = string_literal_string->value;
1208            
1209 195862           SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, string_literal_tmp);
1210 195862 50         assert(compiler->current_each_compile_allocator->memory_blocks_count_tmp == memory_blocks_count_tmp);
1211            
1212 195862           SPVM_OP* op_constant = SPVM_OP_new_op_constant_string(compiler, string_literal, string_literal_length, compiler->current_file, compiler->current_line);
1213            
1214 195862           yylvalp->opval = op_constant;
1215            
1216             // Next is start from $
1217 195862 100         if (next_var_expansion_state == SPVM_TOKE_C_VAR_EXPANSION_STATE_FIRST_CONCAT) {
1218 8526           compiler->var_expansion_state = next_var_expansion_state;
1219 8526           compiler->ch_ptr--;
1220             }
1221            
1222 195862           return CONSTANT;
1223             }
1224             case '\\': {
1225 5054           compiler->ch_ptr++;
1226 5054           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CREATE_REF);
1227 5054           yylvalp->opval = op;
1228 5054           return CREATE_REF;
1229             }
1230             case '$': {
1231             // A derefernece operator
1232 2843085 100         if (*(compiler->ch_ptr + 1) == '$') {
1233 2496           compiler->ch_ptr++;
1234 2496           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DEREF);
1235 2496           yylvalp->opval = op;
1236 2496           return DEREF;
1237             }
1238             // A exception variable
1239 2840589 100         else if (*(compiler->ch_ptr + 1) == '@') {
1240 3217           compiler->ch_ptr += 2;
1241 3217           SPVM_OP* op_exception_var = SPVM_OP_new_op(compiler, SPVM_OP_C_ID_EXCEPTION_VAR, compiler->current_file, compiler->current_line);
1242 3217           yylvalp->opval = op_exception_var;
1243 3217           return EXCEPTION_VAR;
1244             }
1245             // A exception variable with {}
1246 2837372 100         else if (*(compiler->ch_ptr + 1) == '{' && *(compiler->ch_ptr + 2) == '@' && *(compiler->ch_ptr + 3) == '}') {
    100          
    50          
1247 4           compiler->ch_ptr += 4;
1248 4           SPVM_OP* op_exception_var = SPVM_OP_new_op(compiler, SPVM_OP_C_ID_EXCEPTION_VAR, compiler->current_file, compiler->current_line);
1249 4           yylvalp->opval = op_exception_var;
1250 4           return EXCEPTION_VAR;
1251             }
1252             // A local variable name or a class variable name
1253             else {
1254 2837368           compiler->ch_ptr++;
1255            
1256             // ${var} is allowed
1257 2837368           int8_t have_brace = 0;
1258 2837368 100         if (*compiler->ch_ptr == '{') {
1259 30           have_brace = 1;
1260 30           compiler->ch_ptr++;
1261             }
1262            
1263             // Save the starting position of the symbol name part of the variable name
1264 2837368           const char* var_name_symbol_name_part_start_ptr = compiler->ch_ptr;
1265            
1266             // Go forward to the end of the variable name
1267 23267842 100         while (
1268 20430474           isalnum(*compiler->ch_ptr)
1269 3599616 100         || (*compiler->ch_ptr) == '_'
1270 2838084 100         || (*compiler->ch_ptr == ':' && *(compiler->ch_ptr + 1) == ':')
    100          
1271             )
1272             {
1273 17593106 100         if (*compiler->ch_ptr == ':' && *(compiler->ch_ptr + 1) == ':') {
    50          
1274 716           compiler->ch_ptr += 2;
1275             }
1276             else {
1277 17592390           compiler->ch_ptr++;
1278             }
1279             }
1280            
1281             // Create a variable name that doesn't contain "{" and "}"
1282 2837368           int32_t var_name_symbol_name_part_length = compiler->ch_ptr - var_name_symbol_name_part_start_ptr;
1283 2837368           int32_t var_name_length = var_name_symbol_name_part_length + 1;
1284 2837368           const char* var_name = NULL;
1285             {
1286 2837368           int32_t memory_blocks_count_tmp_var_name_tmp = compiler->current_each_compile_allocator->memory_blocks_count_tmp;
1287 2837368           char* var_name_tmp = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, var_name_length + 1);
1288 2837368           var_name_tmp[0] = '$';
1289 2837368           memcpy(&var_name_tmp[1], var_name_symbol_name_part_start_ptr, var_name_symbol_name_part_length);
1290 2837368           var_name_tmp[1 + var_name_symbol_name_part_length] = '\0';
1291            
1292 2837368           SPVM_STRING* var_name_string = SPVM_STRING_new(compiler, var_name_tmp, 1 + var_name_symbol_name_part_length);
1293 2837368           var_name = var_name_string->value;
1294            
1295 2837368           SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, var_name_tmp);
1296 2837368 50         assert(compiler->current_each_compile_allocator->memory_blocks_count_tmp == memory_blocks_count_tmp_var_name_tmp);
1297             }
1298            
1299             // Check the closing brace
1300 2837368 100         if (have_brace) {
1301 30 100         if (*compiler->ch_ptr == '}') {
1302 29           compiler->ch_ptr++;
1303             }
1304             else {
1305 1           SPVM_COMPILER_error(compiler, "The variable name is not closed by \"}\".\n at %s line %d", compiler->current_file, compiler->current_line);
1306             }
1307             }
1308            
1309             // Check the variable name
1310             {
1311             // A variable name cannnot conatain "__"
1312 2837368 100         if (strstr(var_name, "__")) {
1313 1           SPVM_COMPILER_error(compiler, "The variable name \"%s\" cannnot contain \"__\".\n at %s line %d", var_name, compiler->current_file, compiler->current_line);
1314             }
1315            
1316             // A variable name cannnot begin with \"$::\"
1317 2837368 100         if (var_name_symbol_name_part_length >= 2 && var_name[1] == ':' && var_name[2] == ':') {
    100          
    50          
1318 1           SPVM_COMPILER_error(compiler, "The variable name \"%s\" cannnot begin with \"$::\".\n at %s line %d", var_name, compiler->current_file, compiler->current_line);
1319             }
1320            
1321             // A variable name cannnot end with \"::\"
1322 2837368 100         if (var_name_symbol_name_part_length >= 2 && var_name[var_name_length - 1] == ':' && var_name[var_name_length - 2] == ':') {
    100          
    50          
1323 2           SPVM_COMPILER_error(compiler, "The variable name \"%s\" cannnot end with \"::\".\n at %s line %d", var_name, compiler->current_file, compiler->current_line);
1324             }
1325            
1326             // A variable name \"%s\" cannnot contain \"::::\"
1327 2837368 100         if (strstr(var_name, "::::")) {
1328 2           SPVM_COMPILER_error(compiler, "The variable name \"%s\" cannnot contain \"::::\".\n at %s line %d", var_name, compiler->current_file, compiler->current_line);
1329             }
1330            
1331             // A variable name cannnot begin with a number
1332 2837368 50         if (var_name_symbol_name_part_length >= 1 && isdigit(var_name[1])) {
    100          
1333 2           SPVM_COMPILER_error(compiler, "The symbol name part of the variable name \"%s\" cannnot begin with a number.\n at %s line %d", var_name, compiler->current_file, compiler->current_line);
1334             }
1335             }
1336            
1337             // Name op
1338 2837368           SPVM_OP* op_name = SPVM_OP_new_op_name(compiler, var_name, compiler->current_file, compiler->current_line);
1339 2837368           yylvalp->opval = op_name;
1340            
1341 2837368           return VAR_NAME;
1342             }
1343             }
1344             case '(' :
1345             case ')' :
1346             case '[' :
1347             case ']' :
1348             case '{' :
1349             case '}' :
1350             case ',' :
1351             case ':' :
1352             case ';' :
1353             case '@' :
1354             {
1355             // Return character
1356 6571434           compiler->ch_ptr++;
1357 6571434           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
1358            
1359             // Expect field name
1360 6571434 100         if (before_token_is_arrow && ch == '{') {
    100          
1361 149514           compiler->expect_field_name = 1;
1362             }
1363            
1364 6571434           return (int) (uint8_t) ch;
1365             }
1366             default: {
1367             // Numeric literal
1368 4018773 100         if (isdigit(ch)) {
1369 520859           const char* number_literal_begin_ptr = compiler->ch_ptr;
1370            
1371             // The before character is "-"
1372 520859           int32_t minus = 0;
1373 520859 100         if (before_char_is_minus) {
1374 45102           before_char_is_minus = 0;
1375 45102           minus = 1;
1376             }
1377            
1378 520859           int32_t digit = 0;
1379 520859 100         if (*(compiler->ch_ptr) == '0') {
1380             // Hex Literal
1381 314665 100         if (*(compiler->ch_ptr + 1) == 'x' || *(compiler->ch_ptr + 1) == 'X') {
    100          
1382 20574           digit = 16;
1383             }
1384             // Binary Literal
1385 294091 100         else if (*(compiler->ch_ptr + 1) == 'b' || *(compiler->ch_ptr + 1) == 'B') {
    100          
1386 32           digit = 2;
1387             }
1388             // Octal Literal
1389 294059 100         else if (isdigit(*(compiler->ch_ptr + 1)) || *(compiler->ch_ptr + 1) == '_') {
    100          
1390 31           digit = 8;
1391             }
1392             // 0...
1393             else {
1394 314665           digit = 10;
1395             }
1396             }
1397             // Decimal Literal
1398             else {
1399 206194           digit = 10;
1400             }
1401            
1402 520859           int32_t is_floating_number = 0;
1403 520859           int32_t is_hex_floating_number = 0;
1404            
1405 520859           compiler->ch_ptr++;
1406             // Scan Hex number
1407 520859 100         if (digit == 16) {
1408 20574           compiler->ch_ptr += 2;
1409 92674 100         while(
1410 92834 100         SPVM_TOKE_is_hex_number(compiler, *compiler->ch_ptr) || *compiler->ch_ptr == '_'
1411 20689 100         || *compiler->ch_ptr == '.' || *compiler->ch_ptr == 'p' || *compiler->ch_ptr == 'P' || *compiler->ch_ptr == '-' || *compiler->ch_ptr == '+'
    100          
    100          
    100          
    100          
1412             )
1413             {
1414             // Floating point literal
1415 51526 100         if (*compiler->ch_ptr == '.' || *compiler->ch_ptr == 'p' || *compiler->ch_ptr == 'P') {
    100          
    100          
1416 107           is_floating_number = 1;
1417             }
1418 51526 100         if (*compiler->ch_ptr == 'p' || *compiler->ch_ptr == 'P') {
    100          
1419 55           is_hex_floating_number = 1;
1420             }
1421 51526           compiler->ch_ptr++;
1422             }
1423             }
1424             // Scan octal or binary number
1425 500348 100         else if (digit == 8 || digit == 2) {
    100          
1426 63           compiler->ch_ptr += 1;
1427 1105 100         while(
1428 1042           isdigit(*compiler->ch_ptr)
1429 93 100         || *compiler->ch_ptr == '_'
1430             )
1431             {
1432 979           compiler->ch_ptr++;
1433             }
1434             }
1435             // Scan Decimal number
1436             else {
1437 1101047 100         while(
1438 600825           isdigit(*compiler->ch_ptr)
1439 503397 100         || *compiler->ch_ptr == '.' || *compiler->ch_ptr == '-' || *compiler->ch_ptr == '+' || *compiler->ch_ptr == 'e' || *compiler->ch_ptr == 'E'
    100          
    100          
    100          
    100          
1440 500270 100         || *compiler->ch_ptr == '_'
1441             )
1442             {
1443             // Floating point literal
1444 100603 100         if (*compiler->ch_ptr == '.' || *compiler->ch_ptr == 'e' || *compiler->ch_ptr == 'E') {
    100          
    100          
1445 2974           is_floating_number = 1;
1446             }
1447 100603           compiler->ch_ptr++;
1448             }
1449             }
1450            
1451             // First is space for + or -
1452 520859           int32_t str_len = (compiler->ch_ptr - number_literal_begin_ptr);
1453            
1454             // Ignore under line
1455 520859           int32_t numeric_literal_memoyr_blocks_count = compiler->current_each_compile_allocator->memory_blocks_count_tmp;
1456 520859           char* numeric_literal = (char*)SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, str_len + 1);
1457 520859           int32_t pos = 0;
1458             {
1459             int32_t i;
1460 1236037 100         for (i = 0; i < str_len; i++) {
1461 715178 100         if (*(number_literal_begin_ptr + i) != '_') {
1462 715046           *(numeric_literal + pos) = *(number_literal_begin_ptr + i);
1463 715046           pos++;
1464             }
1465             }
1466 520859           numeric_literal[pos] = '\0';
1467             }
1468             // Back suffix such as "f" or "F" when hex floating number
1469 520859 100         if (is_hex_floating_number && !isdigit(*(compiler->ch_ptr - 1))) {
    100          
1470 13           compiler->ch_ptr--;
1471 13           numeric_literal[pos - 1] = '\0';
1472             }
1473            
1474             // Constant
1475             SPVM_TYPE* constant_type;
1476            
1477             // suffix
1478             char suffix[2];
1479 520859           suffix[1] = '\0';
1480            
1481             // long suffix
1482 520859 100         if (*compiler->ch_ptr == 'l' || *compiler->ch_ptr == 'L') {
    100          
1483 5494           suffix[0] = *compiler->ch_ptr;
1484 5494           constant_type = SPVM_TYPE_new_long_type(compiler);
1485 5494           compiler->ch_ptr++;
1486             }
1487             // float suffix
1488 515365 100         else if (*compiler->ch_ptr == 'f' || *compiler->ch_ptr == 'F') {
    100          
1489 1367           suffix[0] = *compiler->ch_ptr;
1490 1367           constant_type = SPVM_TYPE_new_float_type(compiler);
1491 1367           compiler->ch_ptr++;
1492             }
1493             // double suffix
1494 513998 100         else if (*compiler->ch_ptr == 'd' || *compiler->ch_ptr == 'D') {
    100          
1495 57           suffix[0] = *compiler->ch_ptr;
1496 57           constant_type = SPVM_TYPE_new_double_type(compiler);
1497 57           compiler->ch_ptr++;
1498             }
1499             // no suffix
1500             else {
1501 513941           suffix[0] = '\0';
1502            
1503             // floating point
1504 513941 100         if (is_floating_number) {
1505 2081           constant_type = SPVM_TYPE_new_double_type(compiler);
1506             }
1507             // integer
1508             else {
1509 511860           constant_type = SPVM_TYPE_new_int_type(compiler);
1510             }
1511             }
1512            
1513             SPVM_VALUE num;
1514            
1515             // Parse Interger literal - int
1516 520859 100         if (constant_type->basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_INT) {
1517            
1518 511860           errno = 0;
1519 511860           int32_t out_of_range = 0;
1520            
1521             int32_t parse_start_offset;
1522 511860 100         if (digit == 16) {
1523 19344           parse_start_offset = 2;
1524             }
1525 492516 100         else if (digit == 8) {
1526 19           parse_start_offset = 1;
1527             }
1528 492497 100         else if (digit == 2) {
1529 18           parse_start_offset = 2;
1530             }
1531 492479 50         else if (digit == 10) {
1532 492479           parse_start_offset = 0;
1533             }
1534             else {
1535 0           assert(0);
1536             }
1537            
1538             char *end;
1539 511860           uint64_t num_uint64_nosign = strtoull(numeric_literal + parse_start_offset, &end, digit);
1540 511860 50         if (*end != '\0') {
1541 0           out_of_range = 1;
1542             }
1543 511860 50         else if (errno == ERANGE) {
1544 0           out_of_range = 1;
1545             }
1546             else {
1547 511860 100         if (digit == 16 || digit == 8 || digit == 2) {
    100          
    100          
1548 19384 100         if (num_uint64_nosign > UINT32_MAX) {
1549 3           out_of_range = 1;
1550             }
1551             }
1552             else {
1553 492479 100         if (minus) {
1554 43822 100         if (num_uint64_nosign > ((uint32_t)INT32_MAX + 1)) {
1555 43822           out_of_range = 1;
1556             }
1557             }
1558             else {
1559 448657 100         if (num_uint64_nosign > INT32_MAX) {
1560 2           out_of_range = 1;
1561             }
1562             }
1563             }
1564             }
1565            
1566 511860 100         if (out_of_range) {
1567 6 100         SPVM_COMPILER_error(compiler, "The numeric literal \"%s%s\" is out of range of maximum and minimum values of int type.\n at %s line %d", minus ? "-" : "", numeric_literal, compiler->current_file, compiler->current_line);
1568             }
1569            
1570 511860 100         if (digit == 16 || digit == 8 || digit == 2) {
    100          
    100          
1571 19381           num.ival = (int32_t)(uint32_t)num_uint64_nosign;
1572 19393 100         if (minus) {
1573 12           num.ival = -num.ival;
1574             }
1575             }
1576             else {
1577 511860 100         num.ival = minus ? (int32_t)-num_uint64_nosign : (int32_t)num_uint64_nosign;
1578             }
1579             }
1580             // Parse Interger literal - long
1581 8999 100         else if (constant_type->basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_LONG) {
1582 5494           errno = 0;
1583 5494           int32_t invalid = 0;
1584            
1585             int32_t parse_start_offset;
1586 5494 100         if (digit == 16) {
1587 1174           parse_start_offset = 2;
1588             }
1589 4320 100         else if (digit == 8) {
1590 12           parse_start_offset = 1;
1591             }
1592 4308 100         else if (digit == 2) {
1593 14           parse_start_offset = 2;
1594             }
1595 4294 50         else if (digit == 10) {
1596 4294           parse_start_offset = 0;
1597             }
1598             else {
1599 0           assert(0);
1600             }
1601            
1602             char *end;
1603 5494           uint64_t num_uint64_nosign = strtoull(numeric_literal + parse_start_offset, &end, digit);
1604 5494 50         if (*end != '\0') {
1605 0           invalid = 1;
1606             }
1607 5494 100         else if (errno == ERANGE) {
1608 3           invalid = 1;
1609             }
1610             else {
1611 5491 100         if (digit == 16 || digit == 8 || digit == 2) {
    100          
    100          
1612 1197           if (num_uint64_nosign > UINT64_MAX) {
1613             invalid = 1;
1614             }
1615             }
1616             else {
1617 4294 100         if (minus) {
1618 1190 100         if (num_uint64_nosign > ((uint64_t)INT64_MAX + 1)) {
1619 1190           invalid = 1;
1620             }
1621             }
1622             else {
1623 3104 100         if (num_uint64_nosign > INT64_MAX) {
1624 1           invalid = 1;
1625             }
1626             }
1627             }
1628             }
1629            
1630 5494 100         if (invalid) {
1631 5 100         SPVM_COMPILER_error(compiler, "The numeric literal \"%s%s%s\" is out of range of maximum and minimum values of long type.\n at %s line %d", minus ? "-" : "", numeric_literal, suffix, compiler->current_file, compiler->current_line);
1632             }
1633            
1634 5494 100         if (digit == 16 || digit == 8 || digit == 2) {
    100          
    100          
1635 1200           num.lval = (int64_t)(uint64_t)num_uint64_nosign;
1636 1212 100         if (minus) {
1637 12           num.lval = -num.lval;
1638             }
1639             }
1640             else {
1641 5494 100         num.lval = minus ? (int64_t)-num_uint64_nosign : (int64_t)num_uint64_nosign;
1642             }
1643             }
1644             // Parse floating point literal - float
1645 3505 100         else if (constant_type->basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT) {
1646             char *end;
1647 1367           num.fval = strtof(numeric_literal, &end);
1648 1367 50         if (*end != '\0') {
1649 0           SPVM_COMPILER_error(compiler, "Invalid float literal.\n at %s line %d", compiler->current_file, compiler->current_line);
1650             }
1651            
1652 1367 100         if (minus) {
1653 1367           num.fval = -num.fval;
1654             }
1655             }
1656             // Parse floating point literal - double
1657 2138 50         else if (constant_type->basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE) {
1658             char *end;
1659 2138           num.dval = strtod(numeric_literal, &end);
1660 2138 50         if (*end != '\0') {
1661 0           SPVM_COMPILER_error(compiler, "Invalid double literal.\n at %s line %d", compiler->current_file, compiler->current_line);
1662             }
1663 2138 100         if (minus) {
1664 2138           num.dval = -num.dval;
1665             }
1666             }
1667             else {
1668 0           assert(0);
1669             }
1670 520859           SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, numeric_literal);
1671 520859 50         assert(compiler->current_each_compile_allocator->memory_blocks_count_tmp == numeric_literal_memoyr_blocks_count);
1672            
1673             // Constant op
1674             SPVM_OP* op_constant;
1675 520859           switch (constant_type->basic_type->id) {
1676             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
1677 511860           op_constant = SPVM_OP_new_op_constant_int(compiler, num.ival, compiler->current_file, compiler->current_line);
1678 511860           break;
1679             }
1680             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
1681 5494           op_constant = SPVM_OP_new_op_constant_long(compiler, num.lval, compiler->current_file, compiler->current_line);
1682 5494           break;
1683             }
1684             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
1685 1367           op_constant = SPVM_OP_new_op_constant_float(compiler, num.fval, compiler->current_file, compiler->current_line);
1686 1367           break;
1687             }
1688             case SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
1689 2138           op_constant = SPVM_OP_new_op_constant_double(compiler, num.dval, compiler->current_file, compiler->current_line);
1690 2138           break;
1691             }
1692             default: {
1693 0           assert(0);
1694             }
1695             }
1696            
1697 520859           yylvalp->opval = op_constant;
1698            
1699 520859           return CONSTANT;
1700             }
1701             // A symbol name
1702 3497914 100         else if (isalpha(ch) || ch == '_') {
    100          
1703             // Column
1704 3497913           int32_t column = compiler->ch_ptr - compiler->line_begin_ch_ptr;
1705            
1706             // The staring position of the symbol name
1707 3497913           const char* symbol_name_start_ptr = compiler->ch_ptr;
1708            
1709             // Go foward by one character
1710 3497913           compiler->ch_ptr++;
1711            
1712             // Go forward to the end of the symbol name
1713 19702174 100         while(isalnum(*compiler->ch_ptr)
1714 4144788 100         || *compiler->ch_ptr == '_'
1715 3560835 100         || (*compiler->ch_ptr == ':' && *(compiler->ch_ptr + 1) == ':'))
    100          
1716             {
1717 16204261 100         if (*compiler->ch_ptr == ':' && *(compiler->ch_ptr + 1) == ':') {
    50          
1718 62922           compiler->ch_ptr += 2;
1719             }
1720             else {
1721 16141339           compiler->ch_ptr++;
1722             }
1723             }
1724            
1725             // Symbol name
1726 3497913           int32_t symbol_name_length = (compiler->ch_ptr - symbol_name_start_ptr);
1727 3497913           char* symbol_name = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, symbol_name_length + 1);
1728 3497913           memcpy(symbol_name, symbol_name_start_ptr, symbol_name_length);
1729 3497913           symbol_name[symbol_name_length] = '\0';
1730            
1731             // If following token is fat comma, the symbol name is manipulated as a string literal
1732 3497913           int32_t next_is_fat_camma = 0;
1733 3497913           char* fat_camma_check_ptr = compiler->ch_ptr;
1734 5931198 100         while (SPVM_TOKE_is_white_space(compiler, *fat_camma_check_ptr)) {
1735 2433285           fat_camma_check_ptr++;
1736             }
1737 3497913 100         if (*fat_camma_check_ptr == '=' && *(fat_camma_check_ptr + 1) == '>') {
    100          
1738 91           next_is_fat_camma = 1;
1739             }
1740             else {
1741 3497822           next_is_fat_camma = 0;
1742             }
1743            
1744             // Check if the symbol is symbol_name
1745 3497913           int32_t keyword_token = 0;
1746 3497913 100         if (next_is_fat_camma) {
1747             // None
1748             }
1749 3497822 100         else if (expect_method_name) {
1750             // None
1751             }
1752 3049416 100         else if (expect_field_name) {
1753             // None
1754             }
1755             else {
1756             // Keywords
1757 2872443           switch (symbol_name[0]) {
1758             // Keyword
1759             case 'a' : {
1760 556 100         if (strcmp(symbol_name, "alias") == 0) {
1761 2           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ALIAS);
1762 2           keyword_token = ALIAS;
1763             }
1764 554 100         else if (strcmp(symbol_name, "allow") == 0) {
1765 525           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ALLOW);
1766 525           keyword_token = ALLOW;
1767             }
1768 29 100         else if (strcmp(symbol_name, "args_width") == 0) {
1769 11           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ARGS_WIDTH);
1770 11           keyword_token = ARGS_WIDTH;
1771             }
1772 18 100         else if (strcmp(symbol_name, "as") == 0) {
1773 17           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_AS);
1774 17           keyword_token = AS;
1775             }
1776 556           break;
1777             }
1778             case 'b' : {
1779 33295 100         if (strcmp(symbol_name, "basic_type_id") == 0) {
1780 64           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BASIC_TYPE_ID);
1781 64           keyword_token = BASIC_TYPE_ID;
1782             }
1783 33231 100         else if (strcmp(symbol_name, "break") == 0) {
1784 7988           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BREAK);
1785 7988           keyword_token = BREAK;
1786             }
1787 25243 100         else if (strcmp(symbol_name, "byte") == 0) {
1788 25242           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BYTE);
1789 25242           keyword_token = BYTE;
1790             }
1791 33295           break;
1792             }
1793             case 'c' : {
1794 47333 100         if (strcmp(symbol_name, "can") == 0) {
1795 20           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CAN);
1796 20           keyword_token = CAN;
1797             }
1798 47313 100         else if (strcmp(symbol_name, "case") == 0) {
1799 9575           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CASE);
1800 9575           keyword_token = CASE;
1801             }
1802 37738 100         else if (strcmp(symbol_name, "cmp") == 0) {
1803 1633           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_CMP);
1804 1633           keyword_token = STRING_CMP;
1805             }
1806 36105 100         else if (strcmp(symbol_name, "class") == 0) {
1807 34457           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CLASS);
1808 34457           keyword_token = CLASS;
1809             }
1810 1648 100         else if (strcmp(symbol_name, "compile_type_name") == 0) {
1811 14           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_COMPILE_TYPE_NAME);
1812 14           keyword_token = COMPILE_TYPE_NAME;
1813             }
1814 1634 100         else if (strcmp(symbol_name, "copy") == 0) {
1815 1633           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_COPY);
1816 1633           keyword_token = COPY;
1817             }
1818 47333           break;
1819             }
1820             case 'd' : {
1821 172481 100         if (strcmp(symbol_name, "default") == 0) {
1822 570           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DEFAULT);
1823 570           keyword_token = DEFAULT;
1824             }
1825 171911 100         else if (strcmp(symbol_name, "die") == 0) {
1826 140561           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DIE);
1827 140561           keyword_token = DIE;
1828             }
1829 31350 100         else if (strcmp(symbol_name, "divui") == 0) {
1830 7           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DIVIDE_UNSIGNED_INT);
1831 7           keyword_token = DIVIDE_UNSIGNED_INT;
1832             }
1833 31343 100         else if (strcmp(symbol_name, "divul") == 0) {
1834 7           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DIVIDE_UNSIGNED_LONG);
1835 7           keyword_token = DIVIDE_UNSIGNED_LONG;
1836             }
1837 31336 100         else if (strcmp(symbol_name, "double") == 0) {
1838 31278           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DOUBLE);
1839 31278           keyword_token = DOUBLE;
1840             }
1841 58 50         else if (strcmp(symbol_name, "dump") == 0) {
1842 58           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DUMP);
1843 58           keyword_token = DUMP;
1844             }
1845 172481           break;
1846             }
1847             case 'e' : {
1848 91382 100         if (strcmp(symbol_name, "elsif") == 0) {
1849 25232           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ELSIF);
1850 25232           keyword_token = ELSIF;
1851             }
1852 66150 100         else if (strcmp(symbol_name, "else") == 0) {
1853 47236           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ELSE);
1854 47236           keyword_token = ELSE;
1855             }
1856 18914 100         else if (strcmp(symbol_name, "enum") == 0) {
1857 3203           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ENUM);
1858 3203           keyword_token = ENUM;
1859             }
1860 15711 100         else if (strcmp(symbol_name, "eq") == 0) {
1861 10455           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_EQ);
1862 10455           keyword_token = STREQ;
1863             }
1864 5256 100         else if (strcmp(symbol_name, "eval") == 0) {
1865 2153           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_EVAL);
1866 2153           keyword_token = EVAL;
1867             }
1868 3103 100         else if (strcmp(symbol_name, "eval_error_id") == 0) {
1869 10           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_EVAL_ERROR_ID);
1870 10           keyword_token = EVAL_ERROR_ID;
1871             }
1872 3093 50         else if (strcmp(symbol_name, "extends") == 0) {
1873 3093           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_EXTENDS);
1874 3093           keyword_token = EXTENDS;
1875             }
1876 91382           break;
1877             }
1878             case 'f' : {
1879 67934 100         if (strcmp(symbol_name, "for") == 0) {
1880 42609           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_FOR);
1881 42609           keyword_token = FOR;
1882             }
1883 25325 100         else if (strcmp(symbol_name, "float") == 0) {
1884 25295           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_FLOAT);
1885 25295           keyword_token = FLOAT;
1886             }
1887 30 50         else if (strcmp(symbol_name, "false") == 0) {
1888 30           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_FALSE);
1889 30           keyword_token = FALSE;
1890             }
1891 67934           break;
1892             }
1893             case 'g' : {
1894 95 100         if (strcmp(symbol_name, "gt") == 0) {
1895 46           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_GT);
1896 46           keyword_token = STRGT;
1897             }
1898 49 100         else if (strcmp(symbol_name, "ge") == 0) {
1899 46           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_GE);
1900 46           keyword_token = STRGE;
1901             }
1902 95           break;
1903             }
1904             case 'h' : {
1905 27460 50         if (strcmp(symbol_name, "has") == 0) {
1906 27460           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_FIELD);
1907 27460           compiler->expect_field_name = 1;
1908 27460           keyword_token = HAS;
1909             }
1910 27460           break;
1911             }
1912             case 'i' : {
1913 453363 100         if (strcmp(symbol_name, "if") == 0) {
1914 138840           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IF);
1915 138840           keyword_token = IF;
1916             }
1917 314523 100         else if (strcmp(symbol_name, "interface") == 0) {
1918 1394           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_INTERFACE);
1919 1394           keyword_token = INTERFACE;
1920             }
1921 313129 100         else if (strcmp(symbol_name, "int") == 0) {
1922 297836           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_INT);
1923 297836           keyword_token = INT;
1924             }
1925 15293 100         else if (strcmp(symbol_name, "interface_t") == 0) {
1926 5790           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_INTERFACE_T, compiler->current_file, compiler->current_line);
1927 5790           yylvalp->opval = op_attribute;
1928 5790           keyword_token = ATTRIBUTE;
1929             }
1930 9503 100         else if (strcmp(symbol_name, "isa") == 0) {
1931 4599           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ISA);
1932 4599           keyword_token = ISA;
1933             }
1934 4904 100         else if (strcmp(symbol_name, "isa_error") == 0) {
1935 20           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ISA_ERROR);
1936 20           keyword_token = ISA_ERROR;
1937             }
1938 4884 100         else if (strcmp(symbol_name, "isweak") == 0) {
1939 8           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ISWEAK);
1940 8           keyword_token = ISWEAK;
1941             }
1942 4876 100         else if (strcmp(symbol_name, "is_compile_type") == 0) {
1943 16           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IS_COMPILE_TYPE);
1944 16           keyword_token = IS_COMPILE_TYPE;
1945             }
1946 4860 100         else if (strcmp(symbol_name, "is_type") == 0) {
1947 3753           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IS_TYPE);
1948 3753           keyword_token = IS_TYPE;
1949             }
1950 1107 100         else if (strcmp(symbol_name, "is_error") == 0) {
1951 18           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IS_ERROR);
1952 18           keyword_token = IS_ERROR;
1953             }
1954 1089 100         else if (strcmp(symbol_name, "is_read_only") == 0) {
1955 1057           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IS_READ_ONLY);
1956 1057           keyword_token = IS_READ_ONLY;
1957             }
1958 453363           break;
1959             }
1960             case 'l' : {
1961 68319 100         if (strcmp(symbol_name, "last") == 0) {
1962 12058           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LAST);
1963 12058           keyword_token = LAST;
1964             }
1965 56261 100         else if (strcmp(symbol_name, "length") == 0) {
1966 20434           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_LENGTH);
1967 20434           keyword_token = STRING_LENGTH;
1968             }
1969 35827 100         else if (strcmp(symbol_name, "lt") == 0) {
1970 46           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_LT);
1971 46           yylvalp->opval = op;
1972            
1973 46           keyword_token = STRLT;
1974             }
1975 35781 100         else if (strcmp(symbol_name, "le") == 0) {
1976 46           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_LE);
1977 46           yylvalp->opval = op;
1978            
1979 46           keyword_token = STRLE;
1980             }
1981 35735 50         else if (strcmp(symbol_name, "long") == 0) {
1982 35735           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LONG);
1983 35735           keyword_token = LONG;
1984             }
1985 68319           break;
1986             }
1987             case 'm' : {
1988 607035 100         if (strcmp(symbol_name, "make_read_only") == 0) {
1989 1052           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_MAKE_READ_ONLY);
1990 1052           keyword_token = MAKE_READ_ONLY;
1991             }
1992 605983 100         else if (strcmp(symbol_name, "my") == 0) {
1993 355845           SPVM_OP* op_var_decl = SPVM_OP_new_op_var_decl(compiler, compiler->current_file, compiler->current_line);
1994 355845           yylvalp->opval = op_var_decl;
1995 355845           keyword_token = MY;
1996             }
1997 250138 100         else if (strcmp(symbol_name, "mulnum_t") == 0) {
1998 285           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_MULNUM_T, compiler->current_file, compiler->current_line);
1999 285           yylvalp->opval = op_attribute;
2000 285           keyword_token = ATTRIBUTE;
2001             }
2002 249853 100         else if (strcmp(symbol_name, "method") == 0) {
2003 240336           SPVM_OP* op_method = SPVM_TOKE_new_op_with_column(compiler, SPVM_OP_C_ID_METHOD, column);
2004 240336           yylvalp->opval = op_method;
2005            
2006 240336           compiler->expect_method_name = 1;
2007            
2008 240336           keyword_token = METHOD;
2009             }
2010 9517 50         else if (strcmp(symbol_name, "mutable") == 0) {
2011 9517           SPVM_OP* op_mutable = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_MUTABLE);
2012 9517           keyword_token = MUTABLE;
2013             }
2014 607035           break;
2015             }
2016             case 'n' : {
2017 109713 100         if (strcmp(symbol_name, "native") == 0) {
2018 64989           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_NATIVE, compiler->current_file, compiler->current_line);
2019 64989           yylvalp->opval = op_attribute;
2020            
2021 64989           keyword_token = ATTRIBUTE;
2022             }
2023 44724 100         else if (strcmp(symbol_name, "ne") == 0) {
2024 568           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_NE);
2025 568           keyword_token = STRNE;
2026             }
2027 44156 100         else if (strcmp(symbol_name, "next") == 0) {
2028 23           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NEXT);
2029 23           keyword_token = NEXT;
2030             }
2031 44133 100         else if (strcmp(symbol_name, "new") == 0) {
2032 39405           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NEW);
2033 39405           keyword_token = NEW;
2034             }
2035 4728 100         else if (strcmp(symbol_name, "new_string_len") == 0) {
2036 4725           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NEW_STRING_LEN);
2037 4725           keyword_token = NEW_STRING_LEN;
2038             }
2039 109713           break;
2040             }
2041             case 'o' : {
2042 59075 100         if (strcmp(symbol_name, "of") == 0) {
2043 20           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_OF);
2044 20           keyword_token = OF;
2045             }
2046 59055 100         else if (strcmp(symbol_name, "our") == 0) {
2047 8116           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CLASS_VAR);
2048 8116           keyword_token = OUR;
2049             }
2050 50939 100         else if (strcmp(symbol_name, "object") == 0) {
2051 50937           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_OBJECT);
2052 50937           keyword_token = OBJECT;
2053             }
2054 59075           break;
2055             }
2056             case 'p' : {
2057 59412 100         if (strcmp(symbol_name, "print") == 0) {
2058 203           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_PRINT);
2059 203           keyword_token = PRINT;
2060             }
2061 59209 100         else if (strcmp(symbol_name, "private") == 0) {
2062 15301           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_PRIVATE, compiler->current_file, compiler->current_line);
2063 15301           yylvalp->opval = op_attribute;
2064            
2065 15301           keyword_token = ATTRIBUTE;
2066             }
2067 43908 100         else if (strcmp(symbol_name, "protected") == 0) {
2068 231           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_PROTECTED, compiler->current_file, compiler->current_line);
2069 231           yylvalp->opval = op_attribute;
2070            
2071 231           keyword_token = ATTRIBUTE;
2072             }
2073 43677 100         else if (strcmp(symbol_name, "public") == 0) {
2074 1676           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_PUBLIC, compiler->current_file, compiler->current_line);
2075 1676           yylvalp->opval = op_attribute;
2076            
2077 1676           keyword_token = ATTRIBUTE;
2078             }
2079 42001 100         else if (strcmp(symbol_name, "precompile") == 0) {
2080 39032           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_PRECOMPILE, compiler->current_file, compiler->current_line);
2081 39032           yylvalp->opval = op_attribute;
2082            
2083 39032           keyword_token = ATTRIBUTE;
2084             }
2085 2969 100         else if (strcmp(symbol_name, "pointer") == 0) {
2086 2968           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_POINTER, compiler->current_file, compiler->current_line);
2087 2968           yylvalp->opval = op_attribute;
2088            
2089 2968           keyword_token = ATTRIBUTE;
2090             }
2091 59412           break;
2092             }
2093             case 'r' : {
2094 201384 100         if (strcmp(symbol_name, "remui") == 0) {
2095 7           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_REMAINDER_UNSIGNED_INT);
2096 7           keyword_token = REMAINDER_UNSIGNED_INT;
2097             }
2098 201377 100         else if (strcmp(symbol_name, "remul") == 0) {
2099 530           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_REMAINDER_UNSIGNED_LONG);
2100 530           keyword_token = REMAINDER_UNSIGNED_LONG;
2101             }
2102 200847 100         else if (strcmp(symbol_name, "return") == 0) {
2103 170154           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_RETURN);
2104 170154           keyword_token = RETURN;
2105             }
2106 30693 100         else if (strcmp(symbol_name, "require") == 0) {
2107 12           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_REQUIRE);
2108 12           keyword_token = REQUIRE;
2109             }
2110 30681 100         else if (strcmp(symbol_name, "required") == 0) {
2111 5773           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_REQUIRED, compiler->current_file, compiler->current_line);
2112 5773           yylvalp->opval = op_attribute;
2113 5773           keyword_token = ATTRIBUTE;
2114             }
2115 24908 100         else if (strcmp(symbol_name, "rw") == 0) {
2116 1572           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_RW, compiler->current_file, compiler->current_line);
2117 1572           yylvalp->opval = op_attribute;
2118 1572           keyword_token = ATTRIBUTE;
2119             }
2120 23336 100         else if (strcmp(symbol_name, "ro") == 0) {
2121 23301           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_RO, compiler->current_file, compiler->current_line);
2122 23301           yylvalp->opval = op_attribute;
2123 23301           keyword_token = ATTRIBUTE;
2124             }
2125 201384           break;
2126             }
2127             case 's' : {
2128 295231 100         if (strcmp(symbol_name, "say") == 0) {
2129 60           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SAY);
2130 60           keyword_token = SAY;
2131             }
2132 295171 100         else if (strcmp(symbol_name, "static") == 0) {
2133 144897           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_STATIC, compiler->current_file, compiler->current_line);
2134 144897           yylvalp->opval = op_attribute;
2135 144897           keyword_token = ATTRIBUTE;
2136             }
2137 150274 100         else if (strcmp(symbol_name, "switch") == 0) {
2138 1652           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SWITCH);
2139 1652           keyword_token = SWITCH;
2140             }
2141 148622 100         else if (strcmp(symbol_name, "string") == 0) {
2142 129056           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING);
2143 129056           keyword_token = STRING;
2144             }
2145 19566 100         else if (strcmp(symbol_name, "short") == 0) {
2146 19552           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SHORT);
2147 19552           keyword_token = SHORT;
2148             }
2149 14 100         else if (strcmp(symbol_name, "scalar") == 0) {
2150 10           compiler->ch_ptr++;
2151 10           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SCALAR);
2152 10           yylvalp->opval = op;
2153            
2154 10           keyword_token = SCALAR;
2155             }
2156 295231           break;
2157             }
2158             case 't' : {
2159 2139 100         if (strcmp(symbol_name, "true") == 0) {
2160 32           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_TRUE);
2161 32           keyword_token = TRUE;
2162             }
2163 2107 100         else if (strcmp(symbol_name, "type_name") == 0) {
2164 2105           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_TYPE_NAME);
2165 2105           keyword_token = TYPE_NAME;
2166             }
2167 2139           break;
2168             }
2169             case 'u' : {
2170 227318 100         if (strcmp(symbol_name, "undef") == 0) {
2171 41405           yylvalp->opval = SPVM_OP_new_op_undef(compiler, compiler->current_file, compiler->current_line);
2172 41405           keyword_token = UNDEF;
2173             }
2174 185913 100         else if (strcmp(symbol_name, "unless") == 0) {
2175 156994           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_UNLESS);
2176 156994           keyword_token = UNLESS;
2177             }
2178 28919 100         else if (strcmp(symbol_name, "unweaken") == 0) {
2179 4           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_UNLESS);
2180 4           keyword_token = UNWEAKEN;
2181             }
2182 28915 50         else if (strcmp(symbol_name, "use") == 0) {
2183 28915           yylvalp->opval = SPVM_OP_new_op_use(compiler, compiler->current_file, compiler->current_line);
2184 28915           keyword_token = USE;
2185             }
2186 227318           break;
2187             }
2188             case 'v' : {
2189 68460 100         if (strcmp(symbol_name, "version") == 0) {
2190 210           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_VERSION_DECL);
2191 210           keyword_token = VERSION_DECL;
2192             }
2193 68250 50         else if (strcmp(symbol_name, "void") == 0) {
2194 68250           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_VOID);
2195 68250           keyword_token = VOID;
2196             }
2197 68460           break;
2198             }
2199             case 'w' : {
2200 26483 100         if (strcmp(symbol_name, "warn") == 0) {
2201 264           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_WARN);
2202 264           keyword_token = WARN;
2203             }
2204 26219 100         else if (strcmp(symbol_name, "while") == 0) {
2205 26172           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_WHILE);
2206 26172           keyword_token = WHILE;
2207             }
2208 47 100         else if (strcmp(symbol_name, "weaken") == 0) {
2209 45           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_WEAKEN);
2210 45           keyword_token = WEAKEN;
2211             }
2212 2 50         else if (strcmp(symbol_name, "wo") == 0) {
2213 2           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_WO, compiler->current_file, compiler->current_line);
2214 2           yylvalp->opval = op_attribute;
2215 2           keyword_token = ATTRIBUTE;
2216             }
2217 26483           break;
2218             }
2219             case 'I' : {
2220 14012 100         if (strcmp(symbol_name, "INIT") == 0) {
2221 1530           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_INIT);
2222 1530           keyword_token = INIT;
2223             }
2224 14012           break;
2225             }
2226             case '_': {
2227 48 100         if (strcmp(symbol_name, "__END__") == 0) {
2228 3           compiler->ch_ptr = compiler->current_class_content + compiler->current_class_content_length;
2229 3           compiler->token_begin_ch_ptr = compiler->ch_ptr;
2230 3           compiler->end_of_file = 1;
2231 3           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_END_OF_FILE);
2232 3           yylvalp->opval = op;
2233 3           keyword_token = END_OF_FILE;
2234             }
2235 45 100         else if (strcmp(symbol_name, "__PACKAGE__") == 0) {
2236 3           yylvalp->opval = SPVM_OP_new_op(compiler, SPVM_OP_C_ID_CURRENT_CLASS_NAME, compiler->current_file, compiler->current_line);
2237 3           keyword_token = CURRENT_CLASS_NAME;
2238             }
2239 42 100         else if (strcmp(symbol_name, "__FILE__") == 0) {
2240 4           SPVM_OP* op_constant = SPVM_OP_new_op_constant_string(compiler, compiler->current_class_rel_file, strlen(compiler->current_class_rel_file), compiler->current_file, compiler->current_line);
2241 4           yylvalp->opval = op_constant;
2242 4           keyword_token = CONSTANT;
2243             }
2244 38 100         else if (strcmp(symbol_name, "__LINE__") == 0) {
2245 23           SPVM_OP* op_constant = SPVM_OP_new_op_constant_int(compiler, compiler->current_line, compiler->current_file, compiler->current_line);
2246 23           yylvalp->opval = op_constant;
2247 23           keyword_token = CONSTANT;
2248             }
2249 48           break;
2250             }
2251             }
2252             }
2253            
2254             // The symbol name is a keyword
2255             int32_t token;
2256 3497913 100         if (keyword_token > 0) {
2257 2619946           token = keyword_token;
2258             }
2259             // The symbol name is not a keyword
2260             else {
2261             // Check the symbol name
2262             {
2263             // A symbol name cannnot conatain "__"
2264 877967 100         if (strstr(symbol_name, "__")) {
2265 3           SPVM_COMPILER_error(compiler, "The symbol name \"%s\" cannnot constain \"__\".\n at %s line %d", symbol_name, compiler->current_file, compiler->current_line);
2266             }
2267            
2268             // A symbol name cannnot end with "::"
2269 877967 100         if (symbol_name_length >= 2 && symbol_name[symbol_name_length - 2] == ':' && symbol_name[symbol_name_length - 1] == ':' ) {
    100          
    100          
2270 1           SPVM_COMPILER_error(compiler, "The symbol name \"%s\" cannnot end with \"::\".\n at %s line %d", symbol_name, compiler->current_file, compiler->current_line);
2271             }
2272            
2273             // A symbol name cannnot contains "::::".
2274 877967 100         if (strstr(symbol_name, "::::")) {
2275 1           SPVM_COMPILER_error(compiler, "The symbol name \"%s\" cannnot contains \"::::\".\n at %s line %d", symbol_name, compiler->current_file, compiler->current_line);
2276             }
2277            
2278             // A symbol name cannnot begin with "::"
2279 877967 50         assert(!(symbol_name[0] == ':' && symbol_name[1] == ':'));
    0          
2280            
2281             // A symbol name cannnot begin with a number "0-9".
2282 877967 50         assert(!isdigit(symbol_name[0]));
2283             }
2284            
2285             // A string literal of the left operand of the fat camma
2286 877967 100         if (next_is_fat_camma) {
2287             // The string literal of the left operand of the fat camma cannnot contains "::".
2288 91 50         if (symbol_name_length >= 2 && strstr(symbol_name, "::")) {
    100          
2289 1           SPVM_COMPILER_error(compiler, "The string literal \"%s\" of the left operand of the fat camma cannnot contains \"::\".\n at %s line %d", symbol_name, compiler->current_file, compiler->current_line);
2290             }
2291            
2292 91           SPVM_OP* op_constant = SPVM_OP_new_op_constant_string(compiler, symbol_name, symbol_name_length, compiler->current_file, compiler->current_line);
2293 91           yylvalp->opval = op_constant;
2294 91           token = CONSTANT;
2295             }
2296             // A symbol name
2297             else {
2298 877876           SPVM_OP* op_name = SPVM_OP_new_op_name(compiler, symbol_name, compiler->current_file, compiler->current_line);
2299 877876           yylvalp->opval = op_name;
2300 877876           token = SYMBOL_NAME;
2301             }
2302             }
2303            
2304             // Free symbol name
2305 3497913           SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, symbol_name);
2306            
2307 3497913           return token;
2308             }
2309             else {
2310 1           SPVM_COMPILER_error(compiler, "The character %d in a 8bit signed integer is not expected.\n at %s line %d", ch, compiler->current_file, compiler->current_line);
2311 1           return (int) (uint8_t) ch;
2312             }
2313             }
2314             }
2315 24122817           }
2316             }
2317              
2318 37985           int32_t SPVM_TOKE_load_class_file(SPVM_COMPILER* compiler) {
2319              
2320             // Start parsing a source code
2321 37985           compiler->current_file = NULL;
2322 37985           compiler->current_class_content = NULL;
2323 37985           compiler->current_tmp_vars_length = 0;
2324 37985           compiler->ch_ptr = NULL;
2325 37985           compiler->token_begin_ch_ptr = NULL;
2326 37985           compiler->line_begin_ch_ptr = NULL;
2327 37985           compiler->current_anon_op_types = SPVM_LIST_new_list_permanent(compiler->current_each_compile_allocator, 128);
2328            
2329             // If there are more module, load it
2330 37985           SPVM_LIST* op_use_stack = compiler->op_use_stack;
2331            
2332             while (1) {
2333 129963 100         if (op_use_stack->length == 0) {
2334 3516           return 0;
2335             }
2336 126447 50         else if (op_use_stack->length > 0) {
2337 126447           SPVM_OP* op_use = SPVM_LIST_shift(op_use_stack);
2338            
2339 126447           const char* basic_type_name = op_use->uv.use->op_type->uv.type->unresolved_basic_type_name;
2340 126447           int32_t basic_type_name_length = strlen(basic_type_name);
2341            
2342             // Check the class name
2343             {
2344             // A class name must begin with an upper case character
2345 126447 100         if (islower(basic_type_name[0])) {
2346 2           SPVM_COMPILER_error(compiler, "The class name \"%s\" must begin with an upper case character.\n at %s line %d", basic_type_name, op_use->file, op_use->line);
2347 2           return 0;
2348             }
2349            
2350             // Part names of the class name begin with lower case
2351 126445           int32_t module_part_name_is_invalid = 0;
2352 126445           int32_t basic_type_name_length = strlen(basic_type_name);
2353 1151485 100         for (int32_t i = 0; i < basic_type_name_length; i++) {
2354 1025042 100         if (i > 1) {
2355 772152 100         if (basic_type_name[i - 2] == ':' && basic_type_name[i - 1] == ':') {
    100          
2356 32290 100         if (islower(basic_type_name[i])) {
2357 2           SPVM_COMPILER_error(compiler, "The part names of the \"%s\" module must begin with an upper case character.\n at %s line %d", basic_type_name, op_use->file, op_use->line);
2358 2           return 0;
2359             }
2360             }
2361             }
2362             }
2363            
2364             // A class name cannnot conatain "__"
2365 126443 100         if (strstr(basic_type_name, "__")) {
2366 1           SPVM_COMPILER_error(compiler, "The class name \"%s\" cannnot constain \"__\".\n at %s line %d", basic_type_name, op_use->file, op_use->line);
2367 1           return 0;
2368             }
2369            
2370             // A class name cannnot end with "::"
2371 126442 50         if (basic_type_name_length >= 2 && basic_type_name[basic_type_name_length - 2] == ':' && basic_type_name[basic_type_name_length - 1] == ':' ) {
    100          
    50          
2372 1           SPVM_COMPILER_error(compiler, "The class name \"%s\" cannnot end with \"::\".\n at %s line %d", basic_type_name, op_use->file, op_use->line);
2373 1           return 0;
2374             }
2375            
2376             // A class name cannnot contains "::::".
2377 126441 100         if (strstr(basic_type_name, "::::")) {
2378 1           SPVM_COMPILER_error(compiler, "The class name \"%s\" cannnot contains \"::::\".\n at %s line %d", basic_type_name, op_use->file, op_use->line);
2379 1           return 0;
2380             }
2381            
2382             // A class name cannnot begin with \"$::\"
2383 126440 50         if (basic_type_name_length >= 2 && basic_type_name[0] == ':' && basic_type_name[1] == ':') {
    100          
    50          
2384 1           SPVM_COMPILER_error(compiler, "The class name \"%s\" cannnot begin with \"::\".\n at %s line %d", basic_type_name, op_use->file, op_use->line);
2385 1           return 0;
2386             }
2387            
2388             // A class name cannnot begin with a number
2389 126439 50         if (basic_type_name_length >= 1 && isdigit(basic_type_name[0])) {
    100          
2390 1           SPVM_COMPILER_error(compiler, "The class name \"%s\" cannnot begin with a number.\n at %s line %d", basic_type_name, op_use->file, op_use->line);
2391 1           return 0;
2392             }
2393             }
2394            
2395 126438           SPVM_BASIC_TYPE* basic_type = SPVM_HASH_get(compiler->basic_type_symtable, basic_type_name, strlen(basic_type_name));
2396            
2397 126438 100         if (basic_type) {
2398 91973           continue;
2399             }
2400             else {
2401             // Create moudle relative file name from class name by changing :: to / and add ".spvm"
2402 34465           int32_t current_class_rel_file_length = (int32_t)(strlen(basic_type_name) + 6);
2403 34465           char* current_class_rel_file = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->current_each_compile_allocator, current_class_rel_file_length + 1);
2404 34465           const char* ch_ptr_orig = basic_type_name;
2405 34465           char* ch_ptr_to = current_class_rel_file;
2406 343131 100         while (*ch_ptr_orig) {
2407 308666 100         if (*ch_ptr_orig == ':' && *(ch_ptr_orig + 1) == ':') {
    50          
2408 11087           *ch_ptr_to = '/';
2409 11087           ch_ptr_orig += 2;
2410 11087           ch_ptr_to++;
2411             }
2412             else {
2413 297579           *ch_ptr_to = *ch_ptr_orig;
2414 297579           ch_ptr_orig++;
2415 297579           ch_ptr_to++;
2416             }
2417             }
2418 34465           strncpy(ch_ptr_to, ".spvm", 5);
2419 34465           ch_ptr_to += 5;
2420 34465           *ch_ptr_to = '\0';
2421            
2422 34465           char* current_file = NULL;
2423            
2424 34465           SPVM_CLASS_FILE* class_file = SPVM_COMPILER_get_class_file(compiler, basic_type_name);
2425            
2426 34465           const char* include_dir = NULL;
2427 34465 100         if (!class_file) {
2428            
2429             // Search class file
2430 16692           FILE* fh = NULL;
2431 16692           int32_t include_dirs_length = SPVM_COMPILER_get_include_dirs_length(compiler);
2432 60253 100         for (int32_t i = 0; i < include_dirs_length; i++) {
2433 60244           include_dir = SPVM_COMPILER_get_include_dir(compiler, i);
2434            
2435             // File name
2436 60244           int32_t file_name_length = (int32_t)(strlen(include_dir) + 1 + strlen(current_class_rel_file));
2437 60244           current_file = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->current_each_compile_allocator, file_name_length + 1);
2438 60244           sprintf(current_file, "%s/%s", include_dir, current_class_rel_file);
2439 60244           current_file[file_name_length] = '\0';
2440            
2441             // \ is replaced to /
2442 2997387 100         for (int32_t i = 0; i < file_name_length; i++) {
2443 2937143 50         if (current_file[i] == '\\') {
2444 0           current_file[i] = '/';
2445             }
2446             }
2447            
2448             // Open source file
2449 60244           fh = fopen(current_file, "rb");
2450 60244 100         if (fh) {
2451 16683           break;
2452             }
2453 43561           errno = 0;
2454             }
2455            
2456             // Module not found
2457 16692 100         if (!fh) {
2458 9 100         if (!op_use->uv.use->is_require) {
2459 4           int32_t include_dirs_str_length = 0;
2460 45 100         for (int32_t i = 0; i < include_dirs_length; i++) {
2461 41           const char* include_dir = SPVM_COMPILER_get_include_dir(compiler, i);
2462 41           include_dirs_str_length += 1 + strlen(include_dir);
2463             }
2464 4           char* include_dirs_str = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->current_each_compile_allocator, include_dirs_str_length + 1);
2465 4           int32_t include_dirs_str_offset = 0;
2466 45 100         for (int32_t i = 0; i < include_dirs_length; i++) {
2467 41           const char* include_dir = SPVM_COMPILER_get_include_dir(compiler, i);
2468 41           sprintf(include_dirs_str + include_dirs_str_offset, "%s", include_dir);
2469 41           include_dirs_str_offset += strlen(include_dir);
2470 41 100         if (i != include_dirs_length - 1) {
2471 37           include_dirs_str[include_dirs_str_offset] = ' ';
2472 37           include_dirs_str_offset++;
2473             }
2474             }
2475            
2476 4           SPVM_COMPILER_error(compiler, "Failed to load the \"%s\" module. The class file \"%s\" is not found in (%s).\n at %s line %d", basic_type_name, current_class_rel_file, include_dirs_str, op_use->file, op_use->line);
2477            
2478 4           return 0;
2479             }
2480             }
2481             // Module found
2482             else {
2483             // Read file content
2484 16683           fseek(fh, 0, SEEK_END);
2485 16683           int32_t source_length = (int32_t)ftell(fh);
2486 16683 50         if (source_length < 0) {
2487 0           SPVM_COMPILER_error(compiler, "[System Error]Failed to tell the class file \"%s\".\n at %s line %d", current_file, op_use->file, op_use->line);
2488 0           return 0;
2489             }
2490 16683           fseek(fh, 0, SEEK_SET);
2491 16683           char* source = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->current_each_compile_allocator, source_length + 1);
2492 16683           int32_t read_error = 0;
2493 16683 50         if ((int32_t)fread(source, 1, source_length, fh) < source_length) {
2494 0           SPVM_COMPILER_error(compiler, "[System Error]Failed to read the class file \"%s\".\n at %s line %d", current_file, op_use->file, op_use->line);
2495 0           SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, source);
2496 0           read_error = 1;
2497             }
2498            
2499 16683 50         if (!read_error) {
2500 16683           fclose(fh);
2501 16683           source[source_length] = '\0';
2502            
2503 16683           SPVM_CLASS_FILE* found_class_file = SPVM_COMPILER_get_class_file(compiler, basic_type_name);
2504            
2505 16683 50         if (!found_class_file) {
2506 16683           SPVM_COMPILER_add_class_file(compiler, basic_type_name);
2507 16683           SPVM_CLASS_FILE* class_file = SPVM_COMPILER_get_class_file(compiler, basic_type_name);
2508 16683           SPVM_CLASS_FILE_set_file(compiler, class_file, current_file);
2509 16683           SPVM_CLASS_FILE_set_rel_file(compiler, class_file, current_class_rel_file);
2510 16683           SPVM_CLASS_FILE_set_dir(compiler, class_file, include_dir);
2511 16683           SPVM_CLASS_FILE_set_content(compiler, class_file, source);
2512 16683           SPVM_CLASS_FILE_set_content_length(compiler, class_file, source_length);
2513             }
2514             }
2515             }
2516             }
2517            
2518 34461           class_file = SPVM_COMPILER_get_class_file(compiler, basic_type_name);
2519            
2520 34461 100         if (class_file) {
2521 34456 50         if (!class_file->content) {
2522 0           SPVM_COMPILER_error(compiler, "The content of the class file in the \"%s\" module must be defined.\n at %s line %d", basic_type_name, op_use->file, op_use->line);
2523 0           return 0;
2524             }
2525            
2526 34456           compiler->current_class_content = (char*)class_file->content;
2527            
2528 34456 50         if (!(class_file->content_length >= 0)) {
2529 0           SPVM_COMPILER_error(compiler, "The content length of the class file in the \"%s\" must be greater than 0.\n at %s line %d", basic_type_name, op_use->file, op_use->line);
2530 0           return 0;
2531             }
2532            
2533 34456           compiler->current_class_content_length = class_file->content_length;
2534            
2535 34456           compiler->current_class_dir = class_file->dir;
2536            
2537 34456 50         if (!class_file->rel_file) {
2538 0           SPVM_COMPILER_error(compiler, "The relative file path of the class file in the \"%s\" must be defined.\n at %s line %d", basic_type_name, op_use->file, op_use->line);
2539 0           return 0;
2540             }
2541            
2542 34456           compiler->current_class_rel_file = class_file->rel_file;
2543            
2544 34456           compiler->current_outer_class_name = class_file->class_name;
2545            
2546             // If we get current class file path, set it, otherwise set module relative file path
2547 34456 100         if (class_file->file) {
2548 16684           compiler->current_file = class_file->file;
2549             }
2550             else {
2551 17772           compiler->current_file = class_file->rel_file;
2552             }
2553            
2554             // Set initial information for tokenization
2555 34456           compiler->token_begin_ch_ptr = compiler->current_class_content;
2556 34456           compiler->ch_ptr = compiler->token_begin_ch_ptr;
2557 34456           compiler->line_begin_ch_ptr = compiler->token_begin_ch_ptr;
2558 34456           compiler->current_line = 1;
2559             }
2560             else {
2561             // If module is not found and the module is used in require syntax, compilation errors don't occur.
2562 5 50         if (op_use->uv.use->is_require) {
2563 5           SPVM_HASH_set(compiler->if_require_not_found_basic_type_name_symtable, basic_type_name, strlen(basic_type_name), (void*)basic_type_name);
2564 5           continue;
2565             }
2566             }
2567            
2568 34456           break;
2569             }
2570             }
2571             else {
2572 0           assert(0);
2573             }
2574 91978           }
2575            
2576 34456           return 1;
2577             }
2578              
2579 10146372           SPVM_OP* SPVM_TOKE_new_op(SPVM_COMPILER* compiler, int32_t type) {
2580            
2581 10146372           SPVM_OP* op = SPVM_OP_new_op(compiler, type, compiler->current_file, compiler->current_line);
2582            
2583 10146372           return op;
2584             }
2585              
2586 240336           SPVM_OP* SPVM_TOKE_new_op_with_column(SPVM_COMPILER* compiler, int32_t type, int32_t column) {
2587            
2588 240336           SPVM_OP* op = SPVM_OP_new_op(compiler, type, compiler->current_file, compiler->current_line);
2589            
2590             // column is only used to decide anon method uniquness
2591 240336           op->column = column;
2592            
2593 240336           return op;
2594             }
2595              
2596 5931203           int32_t SPVM_TOKE_is_white_space(SPVM_COMPILER* compiler, char ch) {
2597             (void)compiler;
2598             // SP, CR, LF, HT, FF
2599 5931203 100         if (ch == 0x20 || ch == 0x0D || ch == 0x0A || ch == 0x09 || ch == 0x0C) {
    50          
    100          
    50          
    50          
2600 2433290           return 1;
2601             }
2602             else {
2603 3497913           return 0;
2604             }
2605             }
2606              
2607 4256           int32_t SPVM_TOKE_is_octal_number(SPVM_COMPILER* compiler, char ch) {
2608             (void)compiler;
2609             // SP, CR, LF, HT, FF
2610 4256 100         if (ch >= '0' && ch <= '7') {
    100          
2611 1861           return 1;
2612             }
2613             else {
2614 2395           return 0;
2615             }
2616             }
2617              
2618 75419           int32_t SPVM_TOKE_is_hex_number(SPVM_COMPILER* compiler, char ch) {
2619             (void)compiler;
2620             // SP, CR, LF, HT, FF
2621 75419 100         if (isdigit(ch) || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
    100          
    100          
    100          
    100          
2622 53420           return 1;
2623             }
2624             else {
2625 21999           return 0;
2626             }
2627             }
2628              
2629 804           char SPVM_TOKE_parse_octal_escape(SPVM_COMPILER* compiler, char** ch_ptr_ptr) {
2630 804           char ch = -1;
2631 804           char* ch_ptr = *ch_ptr_ptr;
2632            
2633 804           int32_t is_o_escape_character = 0;
2634 804           int32_t has_brace = 0;
2635 804 100         if (*ch_ptr == 'o') {
2636 111           is_o_escape_character = 1;
2637 111           ch_ptr++;
2638 111 50         if (*ch_ptr == '{') {
2639 111           has_brace = 1;
2640 111           ch_ptr++;
2641 111 100         if (!SPVM_TOKE_is_octal_number(compiler, *ch_ptr)) {
2642 1           SPVM_COMPILER_error(compiler, "At least one octal number must be followed by \"\\o{\" of the octal escape character.\n at %s line %d", compiler->current_file, compiler->current_line);
2643 1           return ch;
2644             }
2645             }
2646             else {
2647 0           SPVM_COMPILER_error(compiler, "\"\\o\" of the octal escape character must have its brace.\n at %s line %d", compiler->current_file, compiler->current_line);
2648 0           return ch;
2649             }
2650             }
2651            
2652 803           char octal_escape_char[4] = {0};
2653 803           int32_t octal_escape_char_index = 0;
2654 1860 100         while (SPVM_TOKE_is_octal_number(compiler, *ch_ptr)) {
2655 1058 100         if (octal_escape_char_index >= 3) {
2656 1           break;
2657             }
2658 1057           octal_escape_char[octal_escape_char_index] = *ch_ptr;
2659 1057           ch_ptr++;
2660 1057           octal_escape_char_index++;
2661             }
2662            
2663 803 50         if (strlen(octal_escape_char) > 0) {
2664             char* end;
2665 803           int32_t number = strtol(octal_escape_char, &end, 8);
2666 803 100         if (number > 255) {
2667 1           SPVM_COMPILER_error(compiler, "The maxmum number of the octal escape charcater is 377.\n at %s line %d", compiler->current_file, compiler->current_line);
2668 1           return ch;
2669             }
2670 802           ch = (char)number;
2671             }
2672            
2673 802 100         if (has_brace) {
2674 109 100         if (*ch_ptr == '}') {
2675 108           ch_ptr++;
2676             }
2677             else {
2678 1           SPVM_COMPILER_error(compiler, "The octal escape character is not closed by \"}\".\n at %s line %d", compiler->current_file, compiler->current_line);
2679             }
2680             }
2681            
2682 802           *ch_ptr_ptr = ch_ptr;
2683            
2684 804           return ch;
2685             }
2686              
2687 1245           char SPVM_TOKE_parse_hex_escape(SPVM_COMPILER* compiler, char** ch_ptr_ptr) {
2688             char ch;
2689 1245           char* ch_ptr = *ch_ptr_ptr;
2690              
2691 1245           ch_ptr++;
2692            
2693             // {
2694 1245           int32_t has_brace = 0;
2695 1245 100         if (*ch_ptr == '{') {
2696 16           has_brace = 1;
2697 16           ch_ptr++;
2698             }
2699            
2700 1245           char hex_escape_char[9] = {0};
2701 1245           int32_t hex_escape_char_index = 0;
2702 3194 100         while (SPVM_TOKE_is_hex_number(compiler, *ch_ptr)) {
2703 1953 100         if (hex_escape_char_index >= 2) {
2704 4           break;
2705             }
2706 1949           hex_escape_char[hex_escape_char_index] = *ch_ptr;
2707 1949           ch_ptr++;
2708 1949           hex_escape_char_index++;
2709             }
2710            
2711 1245 100         if (strlen(hex_escape_char) > 0) {
2712             char* end;
2713 1241           ch = (char)strtol(hex_escape_char, &end, 16);
2714             }
2715             else {
2716 4           SPVM_COMPILER_error(compiler, "One or tow hexadecimal numbers must be followed by \"\\x\" of the hexadecimal escape character.\n at %s line %d", compiler->current_file, compiler->current_line);
2717             }
2718            
2719 1245 100         if (has_brace) {
2720 16 100         if (*ch_ptr == '}') {
2721 14           ch_ptr++;
2722             }
2723             else {
2724 2           SPVM_COMPILER_error(compiler, "The hexadecimal escape character is not closed by \"}\".\n at %s line %d", compiler->current_file, compiler->current_line);
2725             }
2726             }
2727            
2728 1245           *ch_ptr_ptr = ch_ptr;
2729            
2730 1245           return ch;
2731             }
2732              
2733 22           int32_t SPVM_TOKE_is_valid_utf8_code_point(int32_t code_point) {
2734 22           return SPVM_TOKE_is_unicode_scalar_value(code_point);
2735             }
2736              
2737 22           int32_t SPVM_TOKE_is_unicode_scalar_value(int32_t code_point) {
2738 22           int32_t is_unicode_scalar_value = 0;
2739 22 50         if (code_point >= 0 && code_point <= 0x10FFFF) {
    50          
2740 22 100         if (!(code_point >= 0xD800 && code_point <= 0xDFFF)) {
    100          
2741 19           is_unicode_scalar_value = 1;
2742             }
2743             }
2744            
2745 22           return is_unicode_scalar_value;
2746             }
2747              
2748 19           int32_t SPVM_TOKE_convert_unicode_codepoint_to_utf8_character(int32_t uc, uint8_t* dst) {
2749 19 50         if (uc < 0x00) {
2750 0           return 0;
2751 19 50         } else if (uc < 0x80) {
2752 0           dst[0] = (uint8_t)uc;
2753 0           return 1;
2754 19 50         } else if (uc < 0x800) {
2755 0           dst[0] = (uint8_t)(0xC0 + (uc >> 6));
2756 0           dst[1] = (uint8_t)(0x80 + (uc & 0x3F));
2757 0           return 2;
2758             // Note: we allow encoding 0xd800-0xdfff here, so as not to change
2759             // the API, however, these are actually invalid in UTF-8
2760 19 100         } else if (uc < 0x10000) {
2761 15           dst[0] = (uint8_t)(0xE0 + (uc >> 12));
2762 15           dst[1] = (uint8_t)(0x80 + ((uc >> 6) & 0x3F));
2763 15           dst[2] = (uint8_t)(0x80 + (uc & 0x3F));
2764 15           return 3;
2765 4 50         } else if (uc < 0x110000) {
2766 4           dst[0] = (uint8_t)(0xF0 + (uc >> 18));
2767 4           dst[1] = (uint8_t)(0x80 + ((uc >> 12) & 0x3F));
2768 4           dst[2] = (uint8_t)(0x80 + ((uc >> 6) & 0x3F));
2769 4           dst[3] = (uint8_t)(0x80 + (uc & 0x3F));
2770 4           return 4;
2771             }
2772             else {
2773 0           return 0;
2774             }
2775             }
2776              
2777 10172723           int32_t SPVM_TOKE_is_line_terminator(SPVM_COMPILER* compiler, char* ch) {
2778            
2779 10172723           int32_t is_line_terminator = 0;
2780            
2781 10172723 100         if (*ch == '\n' || *ch == '\r') {
    100          
2782 3114296           is_line_terminator = 1;
2783             }
2784            
2785 10172723           return is_line_terminator;
2786             }
2787              
2788 3114296           int32_t SPVM_TOKE_parse_line_terminator(SPVM_COMPILER* compiler, char** ch_ptr_ptr) {
2789            
2790 3114296           int32_t is_line_terminator = 0;
2791            
2792 3114296 100         if (**ch_ptr_ptr == '\r' && *(*ch_ptr_ptr + 1) == '\n') {
    100          
2793 679           is_line_terminator = 1;
2794 679           *ch_ptr_ptr += 2;
2795             }
2796 3113617 100         else if (**ch_ptr_ptr == '\n' || **ch_ptr_ptr == '\r') {
    50          
2797 3113617           is_line_terminator = 1;
2798 3113617           (*ch_ptr_ptr)++;
2799             }
2800             else {
2801 0           assert(0);
2802             }
2803            
2804 3114296           return is_line_terminator;
2805             }
2806              
2807 3114264           void SPVM_TOKE_increment_current_line(SPVM_COMPILER* compiler) {
2808            
2809 3114264           compiler->current_line++;
2810 3114264           compiler->line_begin_ch_ptr = compiler->ch_ptr;
2811 3114264           }