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 15822558           int SPVM_yylex(SPVM_YYSTYPE* yylvalp, SPVM_COMPILER* compiler) {
34            
35             // Default source is a empty string
36 15822558 100         if (compiler->ch_ptr == NULL) {
37 2169           compiler->ch_ptr = "";
38             }
39            
40             // Save buf pointer
41 15822558           compiler->token_begin_ch_ptr = compiler->ch_ptr;
42            
43             // Before character is "-". This is used by the numeric literal that has "-".
44 15822558           int32_t before_char_is_minus = 0;
45            
46             // Before token is arrow
47 15822558           int32_t before_token_is_arrow = compiler->before_token_is_arrow;
48 15822558           compiler->before_token_is_arrow = 0;
49            
50 15822558           int32_t previous_token_is_heredoc = compiler->previous_token_is_heredoc;
51 15822558           compiler->previous_token_is_heredoc = 0;
52            
53             // Expect method name
54 15822558           int32_t expect_method_name = compiler->expect_method_name;
55 15822558           compiler->expect_method_name = 0;
56            
57             // Expect field name
58 15822558           int32_t expect_field_name = compiler->expect_field_name;
59 15822558           compiler->expect_field_name = 0;
60            
61             // Variable expansion state
62 15822558           int32_t var_expansion_state = compiler->var_expansion_state;
63 15822558           compiler->var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_NOT_STARTED;
64            
65 15822558           int32_t end_of_file = compiler->end_of_file;
66 15822558           compiler->end_of_file = 0;
67            
68             while(1) {
69            
70             // Load class file
71 40277461           int32_t source_index = compiler->ch_ptr - compiler->current_class_content;
72 40277461 100         if (!compiler->current_class_content || source_index >= compiler->current_class_content_length) {
    100          
73            
74             // End of file
75 73415 100         if (!end_of_file) {
76 34872           compiler->end_of_file = 1;
77 34872           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_END_OF_FILE);
78 34872           yylvalp->opval = op;
79 34872           return END_OF_FILE;
80             }
81            
82             // Load class file
83 38543           int32_t success = SPVM_TOKE_load_class_file(compiler);
84            
85 38543 100         if (!success) {
86 3607           return success;
87             }
88            
89 34936 50         if (compiler->current_class_content) {
90 34936           continue;
91             }
92             else {
93 0           return 0;
94             }
95             }
96            
97             // "aaa $foo bar" is interupted "aaa $foo" . " bar"
98 40204046 100         if (compiler->ch_ptr == compiler->next_string_literal_ch_ptr) {
99 8634           compiler->next_string_literal_ch_ptr = NULL;
100 8634           var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_SECOND_CONCAT;
101             }
102            
103             // Current character
104 40204046           char ch = -1;
105            
106             // Variable expansion state
107 40204046 100         if (var_expansion_state > 0) {
108 34536           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 8634           ch = '.';
115 8634           break;
116             }
117             case SPVM_TOKE_C_VAR_EXPANSION_STATE_VAR: {
118 8634           ch = *compiler->ch_ptr;
119 8634           break;
120             }
121             case SPVM_TOKE_C_VAR_EXPANSION_STATE_SECOND_CONCAT: {
122 8634           ch = '.';
123 8634           break;
124             }
125             case SPVM_TOKE_C_VAR_EXPANSION_STATE_BEGIN_NEXT_STRING_LITERAL: {
126 8634           ch = '"';
127 8634           break;
128             }
129             default: {
130 34536           assert(0);
131             }
132             }
133             }
134 40169510 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 40169489           ch = *compiler->ch_ptr;
141             }
142            
143 40204025           switch (ch) {
144             // Skip space character
145             case ' ':
146             case '\t':
147             case '\f':
148             {
149 21217537           compiler->ch_ptr++;
150 21217537           compiler->token_begin_ch_ptr = compiler->ch_ptr;
151 21217537           continue;
152             break;
153             }
154             case '\r':
155             case '\n':
156             {
157 3089019 50         assert(SPVM_TOKE_is_line_terminator(compiler, compiler->ch_ptr));
158            
159 3089019           SPVM_TOKE_parse_line_terminator(compiler, &compiler->ch_ptr);
160            
161 3089019           SPVM_TOKE_increment_current_line(compiler);
162            
163 3089019           compiler->token_begin_ch_ptr = compiler->ch_ptr;
164 3089019           continue;
165             break;
166             }
167             // Cancat
168             case '.': {
169             // Variable expansion "." before the variable
170 37292 100         if (var_expansion_state == SPVM_TOKE_C_VAR_EXPANSION_STATE_FIRST_CONCAT) {
171 8634           compiler->var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_VAR;
172 8634           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CONCAT);
173 8634           return '.';
174             }
175             // Variable expansion second "." after the variable
176 28658 100         else if (var_expansion_state == SPVM_TOKE_C_VAR_EXPANSION_STATE_SECOND_CONCAT) {
177 8634           compiler->var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_BEGIN_NEXT_STRING_LITERAL;
178 8634           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CONCAT);
179 8634           return '.';
180             }
181             else {
182 20024           compiler->ch_ptr++;
183 20024 100         if (*compiler->ch_ptr == '=') {
184 8507           compiler->ch_ptr++;
185 8507           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
186 8507           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_CONCAT;
187            
188 8507           yylvalp->opval = op_special_assign;
189            
190 8507           return SPECIAL_ASSIGN;
191             }
192             else {
193 11517           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CONCAT);
194 11517           return '.';
195             }
196             }
197             break;
198             }
199             // Addition
200             case '+': {
201 189602           compiler->ch_ptr++;
202            
203 189602 100         if (*compiler->ch_ptr == '+') {
204 82238           compiler->ch_ptr++;
205 82238           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
206 82238           return INC;
207             }
208 107364 100         else if (*compiler->ch_ptr == '=') {
209 5955           compiler->ch_ptr++;
210 5955           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
211 5955           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_ADD;
212            
213 5955           yylvalp->opval = op_special_assign;
214            
215 5955           return SPECIAL_ASSIGN;
216             }
217             else {
218 101409           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
219 101409           return '+';
220             }
221             break;
222             }
223             // Subtract
224             case '-': {
225 611090           compiler->ch_ptr++;
226            
227             // "-" is the sign of a numeric literal
228 611090 100         if (isdigit(*compiler->ch_ptr)) {
229 45756           before_char_is_minus = 1;
230 45756           continue;
231             }
232 565334 100         else if (*compiler->ch_ptr == '>') {
233 492624           compiler->ch_ptr++;
234 492624           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
235 492624           compiler->expect_method_name = 1;
236 492624           compiler->before_token_is_arrow = 1;
237            
238 492624           return ARROW;
239             }
240 72710 100         else if (*compiler->ch_ptr == '-') {
241 10353           compiler->ch_ptr++;
242 10353           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
243 10353           return DEC;
244             }
245 62357 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 62343           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
256 62343           return '-';
257             }
258             break;
259             }
260             // Multiply
261             case '*': {
262 10654           compiler->ch_ptr++;
263            
264 10654 100         if (*compiler->ch_ptr == '=') {
265 545           compiler->ch_ptr++;
266 545           SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
267 545           op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_MULTIPLY;
268            
269 545           yylvalp->opval = op_special_assign;
270            
271 545           return SPECIAL_ASSIGN;
272             }
273             // * is used in MULTIPLY operator or type reference
274             else {
275 10109           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
276 10109           yylvalp->opval = op;
277 10109           return '*';
278             }
279             }
280             // Divide
281             case '/': {
282 5492           compiler->ch_ptr++;
283            
284 5492 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 5478           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DIVIDE);
295 5478           yylvalp->opval = op;
296 5478           return DIVIDE;
297             }
298             }
299             case '%': {
300 2214           compiler->ch_ptr++;
301 2214 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 2204           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_REMAINDER);
312 2204           yylvalp->opval = op;
313 2204           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 8262           compiler->ch_ptr++;
335             // Or
336 8262 100         if (*compiler->ch_ptr == '|') {
337 8210           compiler->ch_ptr++;
338 8210           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LOGICAL_OR);
339 8210           yylvalp->opval = op;
340 8210           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 101456           compiler->ch_ptr++;
360             // &&
361 101456 100         if (*compiler->ch_ptr == '&') {
362 49161           compiler->ch_ptr++;
363 49161           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LOGICAL_AND);
364 49161           yylvalp->opval = op;
365 49161           return LOGICAL_AND;
366             }
367             // &=
368 52295 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 52285 100         else if (isalpha(*compiler->ch_ptr) || *compiler->ch_ptr == '_') {
    100          
379 51165           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CURRENT_CLASS);
380 51165           compiler->expect_method_name = 1;
381 51165           return CURRENT_CLASS;
382             }
383             // &
384             else {
385 1120           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BIT_AND);
386 1120           yylvalp->opval = op;
387 1120           return BIT_AND;
388             }
389             break;
390             }
391             // Comment
392             case '#': {
393 67649           compiler->ch_ptr++;
394             while(1) {
395 1351103           int32_t is_line_terminator = SPVM_TOKE_is_line_terminator(compiler, compiler->ch_ptr);
396            
397 1351103 100         if (is_line_terminator) {
398 67643           SPVM_TOKE_parse_line_terminator(compiler, &compiler->ch_ptr);
399 67643           SPVM_TOKE_increment_current_line(compiler);
400             }
401            
402 1351103 100         if (is_line_terminator || *compiler->ch_ptr == '\0') {
    100          
403             break;
404             }
405             else {
406 1283454           compiler->ch_ptr++;
407             }
408 1283454           }
409            
410 67649           continue;
411             break;
412             }
413             case '=': {
414             // POD
415 713236 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 713230           compiler->ch_ptr++;
447            
448             // ==
449 713230 100         if (*compiler->ch_ptr == '=') {
450 69271           compiler->ch_ptr++;
451 69271           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_EQ);
452 69271           yylvalp->opval = op;
453 69271           return NUMEQ;
454             }
455             // =>
456 643959 100         if (*compiler->ch_ptr == '>') {
457 5045           compiler->ch_ptr++;
458 5045           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
459 5045           yylvalp->opval = op;
460 5045           return ',';
461             }
462             // =
463             else {
464 638914           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ASSIGN);
465 638914           yylvalp->opval = op;
466 638914           return ASSIGN;
467             }
468             }
469             break;
470             }
471             case '<': {
472 164305           compiler->ch_ptr++;
473            
474 164305 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 164226 100         else if (*compiler->ch_ptr == '=') {
614 82526           compiler->ch_ptr++;
615            
616             // <=>
617 82526 100         if (*compiler->ch_ptr == '>') {
618 6584           compiler->ch_ptr++;
619 6584           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_CMP);
620 6584           yylvalp->opval = op;
621 6584           return NUMERIC_CMP;
622             }
623             // <=
624             else {
625 75942           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_LE);
626 75942           yylvalp->opval = op;
627 75942           return NUMLE;
628             }
629             }
630             // <
631             else {
632 81700           compiler->ch_ptr++;
633 81700           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_LT);
634 81700           yylvalp->opval = op;
635 81700           return NUMLT;
636             }
637             break;
638             }
639             case '>': {
640 92336           compiler->ch_ptr++;
641            
642 92336 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 92260 100         else if (*compiler->ch_ptr == '=') {
684 70800           compiler->ch_ptr++;
685 70800           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_GE);
686 70800           yylvalp->opval = op;
687 70800           return NUMGE;
688             }
689             // >
690             else {
691 21460           compiler->ch_ptr++;
692 21460           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_GT);
693 21460           yylvalp->opval = op;
694 21460           return NUMGT;
695             }
696             break;
697             }
698             case '!': {
699 21517           compiler->ch_ptr++;
700            
701 21517 100         if (*compiler->ch_ptr == '=') {
702 18314           compiler->ch_ptr++;
703 18314           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_NE);
704 18314           yylvalp->opval = op;
705 18314           return NUMNE;
706             }
707             else {
708 3203           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LOGICAL_NOT);
709 3203           yylvalp->opval = op;
710 3203           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 50412           compiler->ch_ptr++;
724 50412           char ch = 0;
725            
726 50412 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 50410 100         if (*compiler->ch_ptr == '\\') {
732 3569           compiler->ch_ptr++;
733 3569 100         if (*compiler->ch_ptr == 'a') {
734 2           ch = 0x07; // BEL
735 2           compiler->ch_ptr++;
736             }
737 3567 100         else if (*compiler->ch_ptr == 't') {
738 7           ch = 0x09; // HT
739 7           compiler->ch_ptr++;
740             }
741 3560 100         else if (*compiler->ch_ptr == 'n') {
742 1067           ch = 0x0a; //
743 1067           compiler->ch_ptr++;
744             }
745 2493 100         else if (*compiler->ch_ptr == 'f') {
746 5           ch = 0x0c; // FF
747 5           compiler->ch_ptr++;
748             }
749 2488 100         else if (*compiler->ch_ptr == 'r') {
750 536           ch = 0x0d; // LF
751 536           compiler->ch_ptr++;
752             }
753 1952 100         else if (*compiler->ch_ptr == '\'') {
754 3           ch = 0x27; // '
755 3           compiler->ch_ptr++;
756             }
757 1949 100         else if (*compiler->ch_ptr == '"') {
758 3           ch = 0x22; // "
759 3           compiler->ch_ptr++;
760             }
761 1946 100         else if (*compiler->ch_ptr == '\\') {
762 211           ch = 0x5c; /* \ */
763 211           compiler->ch_ptr++;
764             }
765             // Octal escape character
766 1735 100         else if (SPVM_TOKE_is_octal_number(compiler, *compiler->ch_ptr) || *compiler->ch_ptr == 'o') {
    100          
767 610           ch = SPVM_TOKE_parse_octal_escape(compiler, &compiler->ch_ptr);
768             }
769             // Hex escape character
770 1125 100         else if (*compiler->ch_ptr == 'x') {
771 1123           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 3569           compiler->ch_ptr++;
776             }
777             }
778             else {
779 46841           ch = *compiler->ch_ptr;
780 46841           compiler->ch_ptr++;
781             }
782            
783 50410 100         if (*compiler->ch_ptr == '\'') {
784 50401           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 50412           SPVM_OP* op_constant = SPVM_OP_new_op_constant_byte(compiler, ch, compiler->current_file, compiler->current_line);
793            
794 50412           yylvalp->opval = op_constant;
795            
796 50412           return CONSTANT;
797             }
798             // String literal
799             case '"': {
800 198726 100         if (var_expansion_state == SPVM_TOKE_C_VAR_EXPANSION_STATE_BEGIN_NEXT_STRING_LITERAL) {
801 8634           compiler->var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_NOT_STARTED;
802             }
803             else {
804 190092           compiler->ch_ptr++;
805             }
806            
807             // Save current position
808 198726           const char* string_literal_begin_ch_ptr = compiler->ch_ptr;
809            
810 198726           int8_t next_var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_NOT_STARTED;
811            
812             char* string_literal_tmp;
813 198726           int32_t memory_blocks_count_tmp = compiler->current_each_compile_allocator->memory_blocks_count_tmp;
814 198726           int32_t string_literal_length = 0;
815 198726 100         if (*(compiler->ch_ptr) == '"') {
816 6715           string_literal_tmp = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, 1);
817 6715           string_literal_tmp[0] = '\0';
818 6715           compiler->ch_ptr++;
819             }
820             else {
821 192011           int32_t string_literal_finished = 0;
822            
823             while(1) {
824             // End of string literal
825 6275120 100         if (*compiler->ch_ptr == '"') {
826 183373           string_literal_finished = 1;
827             }
828             // Variable expansion
829 6091747 100         else if (*compiler->ch_ptr == '$') {
830 8642 100         if (*(compiler->ch_ptr + 1) == '"') {
831             // Last $ is allowed
832             }
833             else {
834 8637           string_literal_finished = 1;
835 8637           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 8637           char* next_string_literal_ch_ptr = compiler->ch_ptr + 1;
839            
840             // Dereference
841 8637           int32_t var_is_ref = 0;
842 8637 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 8637           int32_t var_have_brace = 0;
849 8637 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 8637 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 71210 100         if (isalnum(*next_string_literal_ch_ptr) || *next_string_literal_ch_ptr == '_') {
    100          
869 62571           next_string_literal_ch_ptr++;
870             }
871 8639 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 8627 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 8614           break;
882             }
883 62583           }
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 8627 100         if (!var_have_brace && !var_is_ref) {
    100          
889 8610           int32_t has_arrow = 0;
890 8610           int32_t open_getting_field_brace = 0;
891 8610           int32_t open_bracket = 0;
892 8610           int32_t is_first_allow = 1;
893             while (1) {
894 8622 100         if (!has_arrow) {
895 8610 100         if (*next_string_literal_ch_ptr == '-' && *(next_string_literal_ch_ptr + 1) == '>') {
    100          
896 133           has_arrow = 1;
897 133           next_string_literal_ch_ptr += 2;
898             }
899             else {
900             break;
901             }
902             }
903            
904 145 50         if (has_arrow) {
905 145           has_arrow = 0;
906 145 100         if (*next_string_literal_ch_ptr == '{') {
907 29           open_getting_field_brace = 1;
908 29           next_string_literal_ch_ptr++;
909             }
910 116 100         else if (*next_string_literal_ch_ptr == '[') {
911 115           open_bracket = 1;
912 115           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 318 100         while (isalnum(*next_string_literal_ch_ptr) || *next_string_literal_ch_ptr == '_') {
    100          
921 174           next_string_literal_ch_ptr++;
922             }
923            
924 144 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 115 50         else if (open_bracket) {
935 115 100         if (*next_string_literal_ch_ptr == ']') {
936 114           next_string_literal_ch_ptr++;
937 114           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 142 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 142 100         if (!(*next_string_literal_ch_ptr == '{' || *next_string_literal_ch_ptr == '[')) {
    50          
953 130           break;
954             }
955            
956 12           has_arrow = 1;
957 12           }
958             }
959             }
960 8639           compiler->next_string_literal_ch_ptr = next_string_literal_ch_ptr;
961             }
962             }
963             // End of source file
964 6083105 100         else if (*compiler->ch_ptr == '\0') {
965 1           string_literal_finished = 1;
966             }
967 6275117 100         if (string_literal_finished) {
968 192008           break;
969             }
970             else {
971             // Escape is always 2 characters
972 6083109 100         if (*compiler->ch_ptr == '\\') {
973 199268           compiler->ch_ptr += 2;
974             }
975             else {
976 5883841           compiler->ch_ptr++;
977             }
978             }
979 6083109           }
980 192008 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 192007           int32_t string_literal_tmp_len = (int32_t)(compiler->ch_ptr - string_literal_begin_ch_ptr) * 4;
986            
987 192007           compiler->ch_ptr++;
988            
989 192007           string_literal_tmp = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, string_literal_tmp_len + 1);
990             {
991 192007           char* string_literal_ch_ptr = (char*)string_literal_begin_ch_ptr;
992 192007           const char* string_literal_end_ch_ptr = compiler->ch_ptr - 1;
993 6274220 100         while (string_literal_ch_ptr != string_literal_end_ch_ptr) {
994 6082213 100         if (*string_literal_ch_ptr == '\\') {
995 199268           string_literal_ch_ptr++;
996 199268 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 199260 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 199243 100         else if (*string_literal_ch_ptr == 'n') {
1007 6991           string_literal_tmp[string_literal_length] = 0x0a;
1008 6991           string_literal_length++;
1009 6991           string_literal_ch_ptr++;
1010             }
1011 192252 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 192243 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 192228 100         else if (*string_literal_ch_ptr == '"') {
1022 3203           string_literal_tmp[string_literal_length] = 0x22;
1023 3203           string_literal_length++;
1024 3203           string_literal_ch_ptr++;
1025             }
1026 189025 100         else if (*string_literal_ch_ptr == '$') {
1027 188421           string_literal_tmp[string_literal_length] = 0x24;
1028 188421           string_literal_length++;
1029 188421           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 199268           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 5882945           int32_t is_line_terminator = SPVM_TOKE_is_line_terminator(compiler, string_literal_ch_ptr);
1187            
1188 5882945 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 5882915           string_literal_tmp[string_literal_length] = *string_literal_ch_ptr;
1197 5882915           string_literal_length++;
1198 5882915           string_literal_ch_ptr++;
1199             }
1200             }
1201             }
1202             }
1203 192007           string_literal_tmp[string_literal_length] = '\0';
1204             }
1205            
1206 198722           SPVM_STRING* string_literal_string = SPVM_STRING_new(compiler, string_literal_tmp, string_literal_length);
1207 198722           const char* string_literal = string_literal_string->value;
1208            
1209 198722           SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, string_literal_tmp);
1210 198722 50         assert(compiler->current_each_compile_allocator->memory_blocks_count_tmp == memory_blocks_count_tmp);
1211            
1212 198722           SPVM_OP* op_constant = SPVM_OP_new_op_constant_string(compiler, string_literal, string_literal_length, compiler->current_file, compiler->current_line);
1213            
1214 198722           yylvalp->opval = op_constant;
1215            
1216             // Next is start from $
1217 198722 100         if (next_var_expansion_state == SPVM_TOKE_C_VAR_EXPANSION_STATE_FIRST_CONCAT) {
1218 8634           compiler->var_expansion_state = next_var_expansion_state;
1219 8634           compiler->ch_ptr--;
1220             }
1221            
1222 198722           return CONSTANT;
1223             }
1224             case '\\': {
1225 5114           compiler->ch_ptr++;
1226 5114           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CREATE_REF);
1227 5114           yylvalp->opval = op;
1228 5114           return CREATE_REF;
1229             }
1230             case '$': {
1231             // A derefernece operator
1232 2884255 100         if (*(compiler->ch_ptr + 1) == '$') {
1233 2516           compiler->ch_ptr++;
1234 2516           SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DEREF);
1235 2516           yylvalp->opval = op;
1236 2516           return DEREF;
1237             }
1238             // A exception variable
1239 2881739 100         else if (*(compiler->ch_ptr + 1) == '@') {
1240 3085           compiler->ch_ptr += 2;
1241 3085           SPVM_OP* op_exception_var = SPVM_OP_new_op(compiler, SPVM_OP_C_ID_EXCEPTION_VAR, compiler->current_file, compiler->current_line);
1242 3085           yylvalp->opval = op_exception_var;
1243 3085           return EXCEPTION_VAR;
1244             }
1245             // A exception variable with {}
1246 2878654 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 2878650           compiler->ch_ptr++;
1255            
1256             // ${var} is allowed
1257 2878650           int8_t have_brace = 0;
1258 2878650 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 2878650           const char* var_name_symbol_name_part_start_ptr = compiler->ch_ptr;
1265            
1266             // Go forward to the end of the variable name
1267 23608894 100         while (
1268 20730244           isalnum(*compiler->ch_ptr)
1269 3652302 100         || (*compiler->ch_ptr) == '_'
1270 2879332 100         || (*compiler->ch_ptr == ':' && *(compiler->ch_ptr + 1) == ':')
    100          
1271             )
1272             {
1273 17851594 100         if (*compiler->ch_ptr == ':' && *(compiler->ch_ptr + 1) == ':') {
    50          
1274 682           compiler->ch_ptr += 2;
1275             }
1276             else {
1277 17850912           compiler->ch_ptr++;
1278             }
1279             }
1280            
1281             // Create a variable name that doesn't contain "{" and "}"
1282 2878650           int32_t var_name_symbol_name_part_length = compiler->ch_ptr - var_name_symbol_name_part_start_ptr;
1283 2878650           int32_t var_name_length = var_name_symbol_name_part_length + 1;
1284 2878650           const char* var_name = NULL;
1285             {
1286 2878650           int32_t memory_blocks_count_tmp_var_name_tmp = compiler->current_each_compile_allocator->memory_blocks_count_tmp;
1287 2878650           char* var_name_tmp = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, var_name_length + 1);
1288 2878650           var_name_tmp[0] = '$';
1289 2878650           memcpy(&var_name_tmp[1], var_name_symbol_name_part_start_ptr, var_name_symbol_name_part_length);
1290 2878650           var_name_tmp[1 + var_name_symbol_name_part_length] = '\0';
1291            
1292 2878650           SPVM_STRING* var_name_string = SPVM_STRING_new(compiler, var_name_tmp, 1 + var_name_symbol_name_part_length);
1293 2878650           var_name = var_name_string->value;
1294            
1295 2878650           SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, var_name_tmp);
1296 2878650 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 2878650 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 2878650 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 2878650 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 2878650 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 2878650 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 2878650 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 2878650           SPVM_OP* op_name = SPVM_OP_new_op_name(compiler, var_name, compiler->current_file, compiler->current_line);
1339 2878650           yylvalp->opval = op_name;
1340            
1341 2878650           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 6662013           compiler->ch_ptr++;
1357 6662013           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
1358            
1359             // Expect field name
1360 6662013 100         if (before_token_is_arrow && ch == '{') {
    100          
1361 151566           compiler->expect_field_name = 1;
1362             }
1363            
1364 6662013           return (int) (uint8_t) ch;
1365             }
1366             default: {
1367             // Numeric literal
1368 4071760 100         if (isdigit(ch)) {
1369 527223           const char* number_literal_begin_ptr = compiler->ch_ptr;
1370            
1371             // The before character is "-"
1372 527223           int32_t minus = 0;
1373 527223 100         if (before_char_is_minus) {
1374 45756           before_char_is_minus = 0;
1375 45756           minus = 1;
1376             }
1377            
1378 527223           int32_t digit = 0;
1379 527223 100         if (*(compiler->ch_ptr) == '0') {
1380             // Hex Literal
1381 318833 100         if (*(compiler->ch_ptr + 1) == 'x' || *(compiler->ch_ptr + 1) == 'X') {
    100          
1382 20876           digit = 16;
1383             }
1384             // Binary Literal
1385 297957 100         else if (*(compiler->ch_ptr + 1) == 'b' || *(compiler->ch_ptr + 1) == 'B') {
    100          
1386 32           digit = 2;
1387             }
1388             // Octal Literal
1389 297925 100         else if (isdigit(*(compiler->ch_ptr + 1)) || *(compiler->ch_ptr + 1) == '_') {
    100          
1390 31           digit = 8;
1391             }
1392             // 0...
1393             else {
1394 318833           digit = 10;
1395             }
1396             }
1397             // Decimal Literal
1398             else {
1399 208390           digit = 10;
1400             }
1401            
1402 527223           int32_t is_floating_number = 0;
1403 527223           int32_t is_hex_floating_number = 0;
1404            
1405 527223           compiler->ch_ptr++;
1406             // Scan Hex number
1407 527223 100         if (digit == 16) {
1408 20876           compiler->ch_ptr += 2;
1409 94008 100         while(
1410 94168 100         SPVM_TOKE_is_hex_number(compiler, *compiler->ch_ptr) || *compiler->ch_ptr == '_'
1411 20991 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 52256 100         if (*compiler->ch_ptr == '.' || *compiler->ch_ptr == 'p' || *compiler->ch_ptr == 'P') {
    100          
    100          
1416 107           is_floating_number = 1;
1417             }
1418 52256 100         if (*compiler->ch_ptr == 'p' || *compiler->ch_ptr == 'P') {
    100          
1419 55           is_hex_floating_number = 1;
1420             }
1421 52256           compiler->ch_ptr++;
1422             }
1423             }
1424             // Scan octal or binary number
1425 506410 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 1114247 100         while(
1438 607963           isdigit(*compiler->ch_ptr)
1439 509439 100         || *compiler->ch_ptr == '.' || *compiler->ch_ptr == '-' || *compiler->ch_ptr == '+' || *compiler->ch_ptr == 'e' || *compiler->ch_ptr == 'E'
    100          
    100          
    100          
    100          
1440 506332 100         || *compiler->ch_ptr == '_'
1441             )
1442             {
1443             // Floating point literal
1444 101679 100         if (*compiler->ch_ptr == '.' || *compiler->ch_ptr == 'e' || *compiler->ch_ptr == 'E') {
    100          
    100          
1445 2956           is_floating_number = 1;
1446             }
1447 101679           compiler->ch_ptr++;
1448             }
1449             }
1450            
1451             // First is space for + or -
1452 527223           int32_t str_len = (compiler->ch_ptr - number_literal_begin_ptr);
1453            
1454             // Ignore under line
1455 527223           int32_t numeric_literal_memoyr_blocks_count = compiler->current_each_compile_allocator->memory_blocks_count_tmp;
1456 527223           char* numeric_literal = (char*)SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, str_len + 1);
1457 527223           int32_t pos = 0;
1458             {
1459             int32_t i;
1460 1251175 100         for (i = 0; i < str_len; i++) {
1461 723952 100         if (*(number_literal_begin_ptr + i) != '_') {
1462 723820           *(numeric_literal + pos) = *(number_literal_begin_ptr + i);
1463 723820           pos++;
1464             }
1465             }
1466 527223           numeric_literal[pos] = '\0';
1467             }
1468             // Back suffix such as "f" or "F" when hex floating number
1469 527223 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 527223           suffix[1] = '\0';
1480            
1481             // long suffix
1482 527223 100         if (*compiler->ch_ptr == 'l' || *compiler->ch_ptr == 'L') {
    100          
1483 5560           suffix[0] = *compiler->ch_ptr;
1484 5560           constant_type = SPVM_TYPE_new_long_type(compiler);
1485 5560           compiler->ch_ptr++;
1486             }
1487             // float suffix
1488 521663 100         else if (*compiler->ch_ptr == 'f' || *compiler->ch_ptr == 'F') {
    100          
1489 1359           suffix[0] = *compiler->ch_ptr;
1490 1359           constant_type = SPVM_TYPE_new_float_type(compiler);
1491 1359           compiler->ch_ptr++;
1492             }
1493             // double suffix
1494 520304 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 520247           suffix[0] = '\0';
1502            
1503             // floating point
1504 520247 100         if (is_floating_number) {
1505 2081           constant_type = SPVM_TYPE_new_double_type(compiler);
1506             }
1507             // integer
1508             else {
1509 518166           constant_type = SPVM_TYPE_new_int_type(compiler);
1510             }
1511             }
1512            
1513             SPVM_VALUE num;
1514            
1515             // Parse Interger literal - int
1516 527223 100         if (constant_type->basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_INT) {
1517            
1518 518166           errno = 0;
1519 518166           int32_t out_of_range = 0;
1520            
1521             int32_t parse_start_offset;
1522 518166 100         if (digit == 16) {
1523 19630           parse_start_offset = 2;
1524             }
1525 498536 100         else if (digit == 8) {
1526 19           parse_start_offset = 1;
1527             }
1528 498517 100         else if (digit == 2) {
1529 18           parse_start_offset = 2;
1530             }
1531 498499 50         else if (digit == 10) {
1532 498499           parse_start_offset = 0;
1533             }
1534             else {
1535 0           assert(0);
1536             }
1537            
1538             char *end;
1539 518166           uint64_t num_uint64_nosign = strtoull(numeric_literal + parse_start_offset, &end, digit);
1540 518166 50         if (*end != '\0') {
1541 0           out_of_range = 1;
1542             }
1543 518166 50         else if (errno == ERANGE) {
1544 0           out_of_range = 1;
1545             }
1546             else {
1547 518166 100         if (digit == 16 || digit == 8 || digit == 2) {
    100          
    100          
1548 19670 100         if (num_uint64_nosign > UINT32_MAX) {
1549 3           out_of_range = 1;
1550             }
1551             }
1552             else {
1553 498499 100         if (minus) {
1554 44464 100         if (num_uint64_nosign > ((uint32_t)INT32_MAX + 1)) {
1555 44464           out_of_range = 1;
1556             }
1557             }
1558             else {
1559 454035 100         if (num_uint64_nosign > INT32_MAX) {
1560 2           out_of_range = 1;
1561             }
1562             }
1563             }
1564             }
1565            
1566 518166 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 518166 100         if (digit == 16 || digit == 8 || digit == 2) {
    100          
    100          
1571 19667           num.ival = (int32_t)(uint32_t)num_uint64_nosign;
1572 19679 100         if (minus) {
1573 12           num.ival = -num.ival;
1574             }
1575             }
1576             else {
1577 518166 100         num.ival = minus ? (int32_t)-num_uint64_nosign : (int32_t)num_uint64_nosign;
1578             }
1579             }
1580             // Parse Interger literal - long
1581 9057 100         else if (constant_type->basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_LONG) {
1582 5560           errno = 0;
1583 5560           int32_t invalid = 0;
1584            
1585             int32_t parse_start_offset;
1586 5560 100         if (digit == 16) {
1587 1190           parse_start_offset = 2;
1588             }
1589 4370 100         else if (digit == 8) {
1590 12           parse_start_offset = 1;
1591             }
1592 4358 100         else if (digit == 2) {
1593 14           parse_start_offset = 2;
1594             }
1595 4344 50         else if (digit == 10) {
1596 4344           parse_start_offset = 0;
1597             }
1598             else {
1599 0           assert(0);
1600             }
1601            
1602             char *end;
1603 5560           uint64_t num_uint64_nosign = strtoull(numeric_literal + parse_start_offset, &end, digit);
1604 5560 50         if (*end != '\0') {
1605 0           invalid = 1;
1606             }
1607 5560 100         else if (errno == ERANGE) {
1608 3           invalid = 1;
1609             }
1610             else {
1611 5557 100         if (digit == 16 || digit == 8 || digit == 2) {
    100          
    100          
1612 1213           if (num_uint64_nosign > UINT64_MAX) {
1613             invalid = 1;
1614             }
1615             }
1616             else {
1617 4344 100         if (minus) {
1618 1204 100         if (num_uint64_nosign > ((uint64_t)INT64_MAX + 1)) {
1619 1204           invalid = 1;
1620             }
1621             }
1622             else {
1623 3140 100         if (num_uint64_nosign > INT64_MAX) {
1624 1           invalid = 1;
1625             }
1626             }
1627             }
1628             }
1629            
1630 5560 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 5560 100         if (digit == 16 || digit == 8 || digit == 2) {
    100          
    100          
1635 1216           num.lval = (int64_t)(uint64_t)num_uint64_nosign;
1636 1228 100         if (minus) {
1637 12           num.lval = -num.lval;
1638             }
1639             }
1640             else {
1641 5560 100         num.lval = minus ? (int64_t)-num_uint64_nosign : (int64_t)num_uint64_nosign;
1642             }
1643             }
1644             // Parse floating point literal - float
1645 3497 100         else if (constant_type->basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT) {
1646             char *end;
1647 1359           num.fval = strtof(numeric_literal, &end);
1648 1359 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 1359 100         if (minus) {
1653 1359           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 527223           SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, numeric_literal);
1671 527223 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 527223           switch (constant_type->basic_type->id) {
1676             case SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
1677 518166           op_constant = SPVM_OP_new_op_constant_int(compiler, num.ival, compiler->current_file, compiler->current_line);
1678 518166           break;
1679             }
1680             case SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
1681 5560           op_constant = SPVM_OP_new_op_constant_long(compiler, num.lval, compiler->current_file, compiler->current_line);
1682 5560           break;
1683             }
1684             case SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
1685 1359           op_constant = SPVM_OP_new_op_constant_float(compiler, num.fval, compiler->current_file, compiler->current_line);
1686 1359           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 527223           yylvalp->opval = op_constant;
1698            
1699 527223           return CONSTANT;
1700             }
1701             // A symbol name
1702 3544537 100         else if (isalpha(ch) || ch == '_') {
    100          
1703             // Column
1704 3544536           int32_t column = compiler->ch_ptr - compiler->line_begin_ch_ptr;
1705            
1706             // The staring position of the symbol name
1707 3544536           const char* symbol_name_start_ptr = compiler->ch_ptr;
1708            
1709             // Go foward by one character
1710 3544536           compiler->ch_ptr++;
1711            
1712             // Go forward to the end of the symbol name
1713 19949854 100         while(isalnum(*compiler->ch_ptr)
1714 4197515 100         || *compiler->ch_ptr == '_'
1715 3608110 100         || (*compiler->ch_ptr == ':' && *(compiler->ch_ptr + 1) == ':'))
    100          
1716             {
1717 16405318 100         if (*compiler->ch_ptr == ':' && *(compiler->ch_ptr + 1) == ':') {
    50          
1718 63574           compiler->ch_ptr += 2;
1719             }
1720             else {
1721 16341744           compiler->ch_ptr++;
1722             }
1723             }
1724            
1725             // Symbol name
1726 3544536           int32_t symbol_name_length = (compiler->ch_ptr - symbol_name_start_ptr);
1727 3544536           char* symbol_name = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, symbol_name_length + 1);
1728 3544536           memcpy(symbol_name, symbol_name_start_ptr, symbol_name_length);
1729 3544536           symbol_name[symbol_name_length] = '\0';
1730            
1731             // If following token is fat comma, the symbol name is manipulated as a string literal
1732 3544536           int32_t next_is_fat_camma = 0;
1733 3544536           char* fat_camma_check_ptr = compiler->ch_ptr;
1734 6010474 100         while (SPVM_TOKE_is_white_space(compiler, *fat_camma_check_ptr)) {
1735 2465938           fat_camma_check_ptr++;
1736             }
1737 3544536 100         if (*fat_camma_check_ptr == '=' && *(fat_camma_check_ptr + 1) == '>') {
    100          
1738 91           next_is_fat_camma = 1;
1739             }
1740             else {
1741 3544445           next_is_fat_camma = 0;
1742             }
1743            
1744             // Check if the symbol is symbol_name
1745 3544536           int32_t keyword_token = 0;
1746 3544536 100         if (next_is_fat_camma) {
1747             // None
1748             }
1749 3544445 100         else if (expect_method_name) {
1750             // None
1751             }
1752 3090289 100         else if (expect_field_name) {
1753             // None
1754             }
1755             else {
1756             // Keywords
1757 2910928           switch (symbol_name[0]) {
1758             // Keyword
1759             case 'a' : {
1760 564 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 562 100         else if (strcmp(symbol_name, "allow") == 0) {
1765 533           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ALLOW);
1766 533           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 564           break;
1777             }
1778             case 'b' : {
1779 33709 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 33645 100         else if (strcmp(symbol_name, "break") == 0) {
1784 8108           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BREAK);
1785 8108           keyword_token = BREAK;
1786             }
1787 25537 100         else if (strcmp(symbol_name, "byte") == 0) {
1788 25536           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BYTE);
1789 25536           keyword_token = BYTE;
1790             }
1791 33709           break;
1792             }
1793             case 'c' : {
1794 48005 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 47985 100         else if (strcmp(symbol_name, "case") == 0) {
1799 9719           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CASE);
1800 9719           keyword_token = CASE;
1801             }
1802 38266 100         else if (strcmp(symbol_name, "cmp") == 0) {
1803 1657           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_CMP);
1804 1657           keyword_token = STRING_CMP;
1805             }
1806 36609 100         else if (strcmp(symbol_name, "class") == 0) {
1807 34937           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CLASS);
1808 34937           keyword_token = CLASS;
1809             }
1810 1672 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 1658 100         else if (strcmp(symbol_name, "copy") == 0) {
1815 1657           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_COPY);
1816 1657           keyword_token = COPY;
1817             }
1818 48005           break;
1819             }
1820             case 'd' : {
1821 175025 100         if (strcmp(symbol_name, "default") == 0) {
1822 578           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DEFAULT);
1823 578           keyword_token = DEFAULT;
1824             }
1825 174447 100         else if (strcmp(symbol_name, "die") == 0) {
1826 142703           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DIE);
1827 142703           keyword_token = DIE;
1828             }
1829 31744 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 31737 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 31730 100         else if (strcmp(symbol_name, "double") == 0) {
1838 31672           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DOUBLE);
1839 31672           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 175025           break;
1846             }
1847             case 'e' : {
1848 92626 100         if (strcmp(symbol_name, "elsif") == 0) {
1849 25614           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ELSIF);
1850 25614           keyword_token = ELSIF;
1851             }
1852 67012 100         else if (strcmp(symbol_name, "else") == 0) {
1853 47948           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ELSE);
1854 47948           keyword_token = ELSE;
1855             }
1856 19064 100         else if (strcmp(symbol_name, "enum") == 0) {
1857 3249           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ENUM);
1858 3249           keyword_token = ENUM;
1859             }
1860 15815 100         else if (strcmp(symbol_name, "eq") == 0) {
1861 10599           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_EQ);
1862 10599           keyword_token = STREQ;
1863             }
1864 5216 100         else if (strcmp(symbol_name, "eval") == 0) {
1865 2075           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_EVAL);
1866 2075           keyword_token = EVAL;
1867             }
1868 3141 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 3131 50         else if (strcmp(symbol_name, "extends") == 0) {
1873 3131           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_EXTENDS);
1874 3131           keyword_token = EXTENDS;
1875             }
1876 92626           break;
1877             }
1878             case 'f' : {
1879 68904 100         if (strcmp(symbol_name, "for") == 0) {
1880 43269           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_FOR);
1881 43269           keyword_token = FOR;
1882             }
1883 25635 100         else if (strcmp(symbol_name, "float") == 0) {
1884 25607           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_FLOAT);
1885 25607           keyword_token = FLOAT;
1886             }
1887 28 50         else if (strcmp(symbol_name, "false") == 0) {
1888 28           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_FALSE);
1889 28           keyword_token = FALSE;
1890             }
1891 68904           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 27796 50         if (strcmp(symbol_name, "has") == 0) {
1906 27796           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_FIELD);
1907 27796           compiler->expect_field_name = 1;
1908 27796           keyword_token = HAS;
1909             }
1910 27796           break;
1911             }
1912             case 'i' : {
1913 459423 100         if (strcmp(symbol_name, "if") == 0) {
1914 140746           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IF);
1915 140746           keyword_token = IF;
1916             }
1917 318677 100         else if (strcmp(symbol_name, "interface") == 0) {
1918 1386           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_INTERFACE);
1919 1386           keyword_token = INTERFACE;
1920             }
1921 317291 100         else if (strcmp(symbol_name, "int") == 0) {
1922 301806           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_INT);
1923 301806           keyword_token = INT;
1924             }
1925 15485 100         else if (strcmp(symbol_name, "interface_t") == 0) {
1926 5864           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_INTERFACE_T, compiler->current_file, compiler->current_line);
1927 5864           yylvalp->opval = op_attribute;
1928 5864           keyword_token = ATTRIBUTE;
1929             }
1930 9621 100         else if (strcmp(symbol_name, "isa") == 0) {
1931 4645           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ISA);
1932 4645           keyword_token = ISA;
1933             }
1934 4976 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 4956 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 4948 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 4932 100         else if (strcmp(symbol_name, "is_type") == 0) {
1947 3809           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IS_TYPE);
1948 3809           keyword_token = IS_TYPE;
1949             }
1950 1123 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 1105 100         else if (strcmp(symbol_name, "is_read_only") == 0) {
1955 1073           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IS_READ_ONLY);
1956 1073           keyword_token = IS_READ_ONLY;
1957             }
1958 459423           break;
1959             }
1960             case 'l' : {
1961 69275 100         if (strcmp(symbol_name, "last") == 0) {
1962 12242           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LAST);
1963 12242           keyword_token = LAST;
1964             }
1965 57033 100         else if (strcmp(symbol_name, "length") == 0) {
1966 20746           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_LENGTH);
1967 20746           keyword_token = STRING_LENGTH;
1968             }
1969 36287 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 36241 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 36195 50         else if (strcmp(symbol_name, "long") == 0) {
1982 36195           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LONG);
1983 36195           keyword_token = LONG;
1984             }
1985 69275           break;
1986             }
1987             case 'm' : {
1988 615373 100         if (strcmp(symbol_name, "make_read_only") == 0) {
1989 1068           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_MAKE_READ_ONLY);
1990 1068           keyword_token = MAKE_READ_ONLY;
1991             }
1992 614305 100         else if (strcmp(symbol_name, "my") == 0) {
1993 360735           SPVM_OP* op_var_decl = SPVM_OP_new_op_var_decl(compiler, compiler->current_file, compiler->current_line);
1994 360735           yylvalp->opval = op_var_decl;
1995 360735           keyword_token = MY;
1996             }
1997 253570 100         else if (strcmp(symbol_name, "mulnum_t") == 0) {
1998 283           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_MULNUM_T, compiler->current_file, compiler->current_line);
1999 283           yylvalp->opval = op_attribute;
2000 283           keyword_token = ATTRIBUTE;
2001             }
2002 253287 100         else if (strcmp(symbol_name, "method") == 0) {
2003 243626           SPVM_OP* op_method = SPVM_TOKE_new_op_with_column(compiler, SPVM_OP_C_ID_METHOD, column);
2004 243626           yylvalp->opval = op_method;
2005            
2006 243626           compiler->expect_method_name = 1;
2007            
2008 243626           keyword_token = METHOD;
2009             }
2010 9661 50         else if (strcmp(symbol_name, "mutable") == 0) {
2011 9661           SPVM_OP* op_mutable = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_MUTABLE);
2012 9661           keyword_token = MUTABLE;
2013             }
2014 615373           break;
2015             }
2016             case 'n' : {
2017 111373 100         if (strcmp(symbol_name, "native") == 0) {
2018 66059           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_NATIVE, compiler->current_file, compiler->current_line);
2019 66059           yylvalp->opval = op_attribute;
2020            
2021 66059           keyword_token = ATTRIBUTE;
2022             }
2023 45314 100         else if (strcmp(symbol_name, "ne") == 0) {
2024 576           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_NE);
2025 576           keyword_token = STRNE;
2026             }
2027 44738 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 44715 100         else if (strcmp(symbol_name, "new") == 0) {
2032 39915           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NEW);
2033 39915           keyword_token = NEW;
2034             }
2035 4800 100         else if (strcmp(symbol_name, "new_string_len") == 0) {
2036 4797           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NEW_STRING_LEN);
2037 4797           keyword_token = NEW_STRING_LEN;
2038             }
2039 111373           break;
2040             }
2041             case 'o' : {
2042 59887 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 59867 100         else if (strcmp(symbol_name, "our") == 0) {
2047 8180           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CLASS_VAR);
2048 8180           keyword_token = OUR;
2049             }
2050 51687 100         else if (strcmp(symbol_name, "object") == 0) {
2051 51685           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_OBJECT);
2052 51685           keyword_token = OBJECT;
2053             }
2054 59887           break;
2055             }
2056             case 'p' : {
2057 60279 100         if (strcmp(symbol_name, "print") == 0) {
2058 253           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_PRINT);
2059 253           keyword_token = PRINT;
2060             }
2061 60026 100         else if (strcmp(symbol_name, "private") == 0) {
2062 15529           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_PRIVATE, compiler->current_file, compiler->current_line);
2063 15529           yylvalp->opval = op_attribute;
2064            
2065 15529           keyword_token = ATTRIBUTE;
2066             }
2067 44497 100         else if (strcmp(symbol_name, "protected") == 0) {
2068 229           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_PROTECTED, compiler->current_file, compiler->current_line);
2069 229           yylvalp->opval = op_attribute;
2070            
2071 229           keyword_token = ATTRIBUTE;
2072             }
2073 44268 100         else if (strcmp(symbol_name, "public") == 0) {
2074 1624           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_PUBLIC, compiler->current_file, compiler->current_line);
2075 1624           yylvalp->opval = op_attribute;
2076            
2077 1624           keyword_token = ATTRIBUTE;
2078             }
2079 42644 100         else if (strcmp(symbol_name, "precompile") == 0) {
2080 39621           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_PRECOMPILE, compiler->current_file, compiler->current_line);
2081 39621           yylvalp->opval = op_attribute;
2082            
2083 39621           keyword_token = ATTRIBUTE;
2084             }
2085 3023 100         else if (strcmp(symbol_name, "pointer") == 0) {
2086 3022           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_POINTER, compiler->current_file, compiler->current_line);
2087 3022           yylvalp->opval = op_attribute;
2088            
2089 3022           keyword_token = ATTRIBUTE;
2090             }
2091 60279           break;
2092             }
2093             case 'r' : {
2094 203508 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 203501 100         else if (strcmp(symbol_name, "remul") == 0) {
2099 538           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_REMAINDER_UNSIGNED_LONG);
2100 538           keyword_token = REMAINDER_UNSIGNED_LONG;
2101             }
2102 202963 100         else if (strcmp(symbol_name, "return") == 0) {
2103 171938           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_RETURN);
2104 171938           keyword_token = RETURN;
2105             }
2106 31025 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 31013 100         else if (strcmp(symbol_name, "required") == 0) {
2111 5847           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_REQUIRED, compiler->current_file, compiler->current_line);
2112 5847           yylvalp->opval = op_attribute;
2113 5847           keyword_token = ATTRIBUTE;
2114             }
2115 25166 100         else if (strcmp(symbol_name, "rw") == 0) {
2116 1512           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_RW, compiler->current_file, compiler->current_line);
2117 1512           yylvalp->opval = op_attribute;
2118 1512           keyword_token = ATTRIBUTE;
2119             }
2120 23654 100         else if (strcmp(symbol_name, "ro") == 0) {
2121 23619           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_RO, compiler->current_file, compiler->current_line);
2122 23619           yylvalp->opval = op_attribute;
2123 23619           keyword_token = ATTRIBUTE;
2124             }
2125 203508           break;
2126             }
2127             case 's' : {
2128 299029 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 298969 100         else if (strcmp(symbol_name, "static") == 0) {
2133 146419           SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_STATIC, compiler->current_file, compiler->current_line);
2134 146419           yylvalp->opval = op_attribute;
2135 146419           keyword_token = ATTRIBUTE;
2136             }
2137 152550 100         else if (strcmp(symbol_name, "switch") == 0) {
2138 1676           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SWITCH);
2139 1676           keyword_token = SWITCH;
2140             }
2141 150874 100         else if (strcmp(symbol_name, "string") == 0) {
2142 131102           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING);
2143 131102           keyword_token = STRING;
2144             }
2145 19772 100         else if (strcmp(symbol_name, "short") == 0) {
2146 19758           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SHORT);
2147 19758           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 299029           break;
2157             }
2158             case 't' : {
2159 2169 100         if (strcmp(symbol_name, "true") == 0) {
2160 30           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_TRUE);
2161 30           keyword_token = TRUE;
2162             }
2163 2139 100         else if (strcmp(symbol_name, "type_name") == 0) {
2164 2137           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_TYPE_NAME);
2165 2137           keyword_token = TYPE_NAME;
2166             }
2167 2169           break;
2168             }
2169             case 'u' : {
2170 230456 100         if (strcmp(symbol_name, "undef") == 0) {
2171 41949           yylvalp->opval = SPVM_OP_new_op_undef(compiler, compiler->current_file, compiler->current_line);
2172 41949           keyword_token = UNDEF;
2173             }
2174 188507 100         else if (strcmp(symbol_name, "unless") == 0) {
2175 159090           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_UNLESS);
2176 159090           keyword_token = UNLESS;
2177             }
2178 29417 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 29413 50         else if (strcmp(symbol_name, "use") == 0) {
2183 29413           yylvalp->opval = SPVM_OP_new_op_use(compiler, compiler->current_file, compiler->current_line);
2184 29413           keyword_token = USE;
2185             }
2186 230456           break;
2187             }
2188             case 'v' : {
2189 69502 100         if (strcmp(symbol_name, "version") == 0) {
2190 206           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_VERSION_DECL);
2191 206           keyword_token = VERSION_DECL;
2192             }
2193 69296 50         else if (strcmp(symbol_name, "void") == 0) {
2194 69296           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_VOID);
2195 69296           keyword_token = VOID;
2196             }
2197 69502           break;
2198             }
2199             case 'w' : {
2200 26881 100         if (strcmp(symbol_name, "warn") == 0) {
2201 262           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_WARN);
2202 262           keyword_token = WARN;
2203             }
2204 26619 100         else if (strcmp(symbol_name, "while") == 0) {
2205 26572           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_WHILE);
2206 26572           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 26881           break;
2218             }
2219             case 'I' : {
2220 14200 100         if (strcmp(symbol_name, "INIT") == 0) {
2221 1548           yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_INIT);
2222 1548           keyword_token = INIT;
2223             }
2224 14200           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 3544536 100         if (keyword_token > 0) {
2257 2655375           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 889161 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 889161 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 889161 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 889161 50         assert(!(symbol_name[0] == ':' && symbol_name[1] == ':'));
    0          
2280            
2281             // A symbol name cannnot begin with a number "0-9".
2282 889161 50         assert(!isdigit(symbol_name[0]));
2283             }
2284            
2285             // A string literal of the left operand of the fat camma
2286 889161 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 889070           SPVM_OP* op_name = SPVM_OP_new_op_name(compiler, symbol_name, compiler->current_file, compiler->current_line);
2299 889070           yylvalp->opval = op_name;
2300 889070           token = SYMBOL_NAME;
2301             }
2302             }
2303            
2304             // Free symbol name
2305 3544536           SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, symbol_name);
2306            
2307 3544536           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 24454903           }
2316             }
2317              
2318 38543           int32_t SPVM_TOKE_load_class_file(SPVM_COMPILER* compiler) {
2319              
2320             // Start parsing a source code
2321 38543           compiler->current_file = NULL;
2322 38543           compiler->current_class_content = NULL;
2323 38543           compiler->current_tmp_vars_length = 0;
2324 38543           compiler->ch_ptr = NULL;
2325 38543           compiler->token_begin_ch_ptr = NULL;
2326 38543           compiler->line_begin_ch_ptr = NULL;
2327 38543           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 38543           SPVM_LIST* op_use_stack = compiler->op_use_stack;
2331            
2332             while (1) {
2333 132585 100         if (op_use_stack->length == 0) {
2334 3594           return 0;
2335             }
2336 128991 50         else if (op_use_stack->length > 0) {
2337 128991           SPVM_OP* op_use = SPVM_LIST_shift(op_use_stack);
2338            
2339 128991           const char* basic_type_name = op_use->uv.use->op_type->uv.type->unresolved_basic_type_name;
2340 128991           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 128991 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 128989           int32_t module_part_name_is_invalid = 0;
2352 128989           int32_t basic_type_name_length = strlen(basic_type_name);
2353 1174507 100         for (int32_t i = 0; i < basic_type_name_length; i++) {
2354 1045520 100         if (i > 1) {
2355 787542 100         if (basic_type_name[i - 2] == ':' && basic_type_name[i - 1] == ':') {
    100          
2356 32988 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 128987 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 128986 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 128985 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 128984 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 128983 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 128982           SPVM_BASIC_TYPE* basic_type = SPVM_HASH_get(compiler->basic_type_symtable, basic_type_name, strlen(basic_type_name));
2396            
2397 128982 100         if (basic_type) {
2398 94037           continue;
2399             }
2400             else {
2401             // Create moudle relative file name from class name by changing :: to / and add ".spvm"
2402 34945           int32_t current_class_rel_file_length = (int32_t)(strlen(basic_type_name) + 6);
2403 34945           char* current_class_rel_file = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->current_each_compile_allocator, current_class_rel_file_length + 1);
2404 34945           const char* ch_ptr_orig = basic_type_name;
2405 34945           char* ch_ptr_to = current_class_rel_file;
2406 347679 100         while (*ch_ptr_orig) {
2407 312734 100         if (*ch_ptr_orig == ':' && *(ch_ptr_orig + 1) == ':') {
    50          
2408 11257           *ch_ptr_to = '/';
2409 11257           ch_ptr_orig += 2;
2410 11257           ch_ptr_to++;
2411             }
2412             else {
2413 301477           *ch_ptr_to = *ch_ptr_orig;
2414 301477           ch_ptr_orig++;
2415 301477           ch_ptr_to++;
2416             }
2417             }
2418 34945           strncpy(ch_ptr_to, ".spvm", 5);
2419 34945           ch_ptr_to += 5;
2420 34945           *ch_ptr_to = '\0';
2421            
2422 34945           char* current_file = NULL;
2423            
2424 34945           SPVM_CLASS_FILE* class_file = SPVM_COMPILER_get_class_file(compiler, basic_type_name);
2425            
2426 34945           const char* include_dir = NULL;
2427 34945 100         if (!class_file) {
2428            
2429             // Search class file
2430 16932           FILE* fh = NULL;
2431 16932           int32_t include_dirs_length = SPVM_COMPILER_get_include_dirs_length(compiler);
2432 61255 100         for (int32_t i = 0; i < include_dirs_length; i++) {
2433 61246           include_dir = SPVM_COMPILER_get_include_dir(compiler, i);
2434            
2435             // File name
2436 61246           int32_t file_name_length = (int32_t)(strlen(include_dir) + 1 + strlen(current_class_rel_file));
2437 61246           current_file = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->current_each_compile_allocator, file_name_length + 1);
2438 61246           sprintf(current_file, "%s/%s", include_dir, current_class_rel_file);
2439 61246           current_file[file_name_length] = '\0';
2440            
2441             // \ is replaced to /
2442 3047699 100         for (int32_t i = 0; i < file_name_length; i++) {
2443 2986453 50         if (current_file[i] == '\\') {
2444 0           current_file[i] = '/';
2445             }
2446             }
2447            
2448             // Open source file
2449 61246           fh = fopen(current_file, "rb");
2450 61246 100         if (fh) {
2451 16923           break;
2452             }
2453 44323           errno = 0;
2454             }
2455            
2456             // Module not found
2457 16932 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 16923           fseek(fh, 0, SEEK_END);
2485 16923           int32_t source_length = (int32_t)ftell(fh);
2486 16923 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 16923           fseek(fh, 0, SEEK_SET);
2491 16923           char* source = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->current_each_compile_allocator, source_length + 1);
2492 16923           int32_t read_error = 0;
2493 16923 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 16923 50         if (!read_error) {
2500 16923           fclose(fh);
2501 16923           source[source_length] = '\0';
2502            
2503 16923           SPVM_CLASS_FILE* found_class_file = SPVM_COMPILER_get_class_file(compiler, basic_type_name);
2504            
2505 16923 50         if (!found_class_file) {
2506 16923           SPVM_COMPILER_add_class_file(compiler, basic_type_name);
2507 16923           SPVM_CLASS_FILE* class_file = SPVM_COMPILER_get_class_file(compiler, basic_type_name);
2508 16923           SPVM_CLASS_FILE_set_file(compiler, class_file, current_file);
2509 16923           SPVM_CLASS_FILE_set_rel_file(compiler, class_file, current_class_rel_file);
2510 16923           SPVM_CLASS_FILE_set_dir(compiler, class_file, include_dir);
2511 16923           SPVM_CLASS_FILE_set_content(compiler, class_file, source);
2512 16923           SPVM_CLASS_FILE_set_content_length(compiler, class_file, source_length);
2513             }
2514             }
2515             }
2516             }
2517            
2518 34941           class_file = SPVM_COMPILER_get_class_file(compiler, basic_type_name);
2519            
2520 34941 100         if (class_file) {
2521 34936 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 34936           compiler->current_class_content = (char*)class_file->content;
2527            
2528 34936 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 34936           compiler->current_class_content_length = class_file->content_length;
2534            
2535 34936           compiler->current_class_dir = class_file->dir;
2536            
2537 34936 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 34936           compiler->current_class_rel_file = class_file->rel_file;
2543            
2544 34936           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 34936 100         if (class_file->file) {
2548 16924           compiler->current_file = class_file->file;
2549             }
2550             else {
2551 18012           compiler->current_file = class_file->rel_file;
2552             }
2553            
2554             // Set initial information for tokenization
2555 34936           compiler->token_begin_ch_ptr = compiler->current_class_content;
2556 34936           compiler->ch_ptr = compiler->token_begin_ch_ptr;
2557 34936           compiler->line_begin_ch_ptr = compiler->token_begin_ch_ptr;
2558 34936           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 34936           break;
2569             }
2570             }
2571             else {
2572 0           assert(0);
2573             }
2574 94042           }
2575            
2576 34936           return 1;
2577             }
2578              
2579 10286281           SPVM_OP* SPVM_TOKE_new_op(SPVM_COMPILER* compiler, int32_t type) {
2580            
2581 10286281           SPVM_OP* op = SPVM_OP_new_op(compiler, type, compiler->current_file, compiler->current_line);
2582            
2583 10286281           return op;
2584             }
2585              
2586 243626           SPVM_OP* SPVM_TOKE_new_op_with_column(SPVM_COMPILER* compiler, int32_t type, int32_t column) {
2587            
2588 243626           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 243626           op->column = column;
2592            
2593 243626           return op;
2594             }
2595              
2596 6010479           int32_t SPVM_TOKE_is_white_space(SPVM_COMPILER* compiler, char ch) {
2597             (void)compiler;
2598             // SP, CR, LF, HT, FF
2599 6010479 100         if (ch == 0x20 || ch == 0x0D || ch == 0x0A || ch == 0x09 || ch == 0x0C) {
    50          
    100          
    50          
    50          
2600 2465943           return 1;
2601             }
2602             else {
2603 3544536           return 0;
2604             }
2605             }
2606              
2607 4296           int32_t SPVM_TOKE_is_octal_number(SPVM_COMPILER* compiler, char ch) {
2608             (void)compiler;
2609             // SP, CR, LF, HT, FF
2610 4296 100         if (ch >= '0' && ch <= '7') {
    100          
2611 1877           return 1;
2612             }
2613             else {
2614 2419           return 0;
2615             }
2616             }
2617              
2618 76491           int32_t SPVM_TOKE_is_hex_number(SPVM_COMPILER* compiler, char ch) {
2619             (void)compiler;
2620             // SP, CR, LF, HT, FF
2621 76491 100         if (isdigit(ch) || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
    100          
    100          
    100          
    100          
2622 54174           return 1;
2623             }
2624             else {
2625 22317           return 0;
2626             }
2627             }
2628              
2629 812           char SPVM_TOKE_parse_octal_escape(SPVM_COMPILER* compiler, char** ch_ptr_ptr) {
2630 812           char ch = -1;
2631 812           char* ch_ptr = *ch_ptr_ptr;
2632            
2633 812           int32_t is_o_escape_character = 0;
2634 812           int32_t has_brace = 0;
2635 812 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 811           char octal_escape_char[4] = {0};
2653 811           int32_t octal_escape_char_index = 0;
2654 1876 100         while (SPVM_TOKE_is_octal_number(compiler, *ch_ptr)) {
2655 1066 100         if (octal_escape_char_index >= 3) {
2656 1           break;
2657             }
2658 1065           octal_escape_char[octal_escape_char_index] = *ch_ptr;
2659 1065           ch_ptr++;
2660 1065           octal_escape_char_index++;
2661             }
2662            
2663 811 50         if (strlen(octal_escape_char) > 0) {
2664             char* end;
2665 811           int32_t number = strtol(octal_escape_char, &end, 8);
2666 811 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 810           ch = (char)number;
2671             }
2672            
2673 810 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 810           *ch_ptr_ptr = ch_ptr;
2683            
2684 812           return ch;
2685             }
2686              
2687 1261           char SPVM_TOKE_parse_hex_escape(SPVM_COMPILER* compiler, char** ch_ptr_ptr) {
2688             char ch;
2689 1261           char* ch_ptr = *ch_ptr_ptr;
2690              
2691 1261           ch_ptr++;
2692            
2693             // {
2694 1261           int32_t has_brace = 0;
2695 1261 100         if (*ch_ptr == '{') {
2696 16           has_brace = 1;
2697 16           ch_ptr++;
2698             }
2699            
2700 1261           char hex_escape_char[9] = {0};
2701 1261           int32_t hex_escape_char_index = 0;
2702 3234 100         while (SPVM_TOKE_is_hex_number(compiler, *ch_ptr)) {
2703 1977 100         if (hex_escape_char_index >= 2) {
2704 4           break;
2705             }
2706 1973           hex_escape_char[hex_escape_char_index] = *ch_ptr;
2707 1973           ch_ptr++;
2708 1973           hex_escape_char_index++;
2709             }
2710            
2711 1261 100         if (strlen(hex_escape_char) > 0) {
2712             char* end;
2713 1257           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 1261 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 1261           *ch_ptr_ptr = ch_ptr;
2729            
2730 1261           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 10323431           int32_t SPVM_TOKE_is_line_terminator(SPVM_COMPILER* compiler, char* ch) {
2778            
2779 10323431           int32_t is_line_terminator = 0;
2780            
2781 10323431 100         if (*ch == '\n' || *ch == '\r') {
    100          
2782 3156798           is_line_terminator = 1;
2783             }
2784            
2785 10323431           return is_line_terminator;
2786             }
2787              
2788 3156798           int32_t SPVM_TOKE_parse_line_terminator(SPVM_COMPILER* compiler, char** ch_ptr_ptr) {
2789            
2790 3156798           int32_t is_line_terminator = 0;
2791            
2792 3156798 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 3156119 100         else if (**ch_ptr_ptr == '\n' || **ch_ptr_ptr == '\r') {
    50          
2797 3156119           is_line_terminator = 1;
2798 3156119           (*ch_ptr_ptr)++;
2799             }
2800             else {
2801 0           assert(0);
2802             }
2803            
2804 3156798           return is_line_terminator;
2805             }
2806              
2807 3156766           void SPVM_TOKE_increment_current_line(SPVM_COMPILER* compiler) {
2808            
2809 3156766           compiler->current_line++;
2810 3156766           compiler->line_begin_ch_ptr = compiler->ch_ptr;
2811 3156766           }