#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
#include <inttypes.h>
#include "spvm_toke.h"
#include "spvm_compiler.h"
#include "spvm_yacc_util.h"
#include "spvm_yacc.h"
#include "spvm_op.h"
#include "spvm_allocator.h"
#include "spvm_constant.h"
#include "spvm_var.h"
#include "spvm_list.h"
#include "spvm_hash.h"
#include "spvm_attribute.h"
#include "spvm_type.h"
#include "spvm_use.h"
#include "spvm_basic_type.h"
#include "spvm_var_decl.h"
#include "spvm_string_buffer.h"
#include "spvm_method.h"
#include "spvm_string.h"
#include "spvm_class_file.h"
#include "spvm_utf8.h"
int
SPVM_yylex(SPVM_YYSTYPE* yylvalp, SPVM_COMPILER* compiler) {
if
(compiler->ch_ptr == NULL) {
compiler->ch_ptr =
""
;
}
compiler->token_begin_ch_ptr = compiler->ch_ptr;
int32_t before_char_is_minus = 0;
int32_t before_token_is_arrow = compiler->before_token_is_arrow;
compiler->before_token_is_arrow = 0;
int32_t previous_token_is_heredoc = compiler->previous_token_is_heredoc;
compiler->previous_token_is_heredoc = 0;
int32_t expect_method_name = compiler->expect_method_name;
compiler->expect_method_name = 0;
int32_t expect_field_name = compiler->expect_field_name;
compiler->expect_field_name = 0;
int32_t var_expansion_state = compiler->var_expansion_state;
compiler->var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_NOT_STARTED;
int32_t end_of_file = compiler->end_of_file;
compiler->end_of_file = 0;
while
(1) {
int32_t source_index = compiler->ch_ptr - compiler->current_class_content;
if
(!compiler->current_class_content || source_index >= compiler->current_class_content_length) {
if
(!end_of_file) {
compiler->end_of_file = 1;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_END_OF_FILE);
yylvalp->opval = op;
return
END_OF_FILE;
}
int32_t success = SPVM_TOKE_load_class_file(compiler);
if
(!success) {
return
success;
}
if
(compiler->current_class_content) {
continue
;
}
else
{
return
0;
}
}
if
(compiler->ch_ptr == compiler->next_string_literal_ch_ptr) {
compiler->next_string_literal_ch_ptr = NULL;
var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_SECOND_STRING_CONCAT;
}
int32_t ch = -1;
if
(var_expansion_state > 0) {
switch
(var_expansion_state) {
case
SPVM_TOKE_C_VAR_EXPANSION_STATE_NOT_STARTED: {
ch = (uint8_t)*compiler->ch_ptr;
break
;
}
case
SPVM_TOKE_C_VAR_EXPANSION_STATE_FIRST_STRING_CONCAT: {
ch =
'.'
;
break
;
}
case
SPVM_TOKE_C_VAR_EXPANSION_STATE_VAR: {
ch = (uint8_t)*compiler->ch_ptr;
break
;
}
case
SPVM_TOKE_C_VAR_EXPANSION_STATE_SECOND_STRING_CONCAT: {
ch =
'.'
;
break
;
}
case
SPVM_TOKE_C_VAR_EXPANSION_STATE_BEGIN_NEXT_STRING_LITERAL: {
ch =
'"'
;
break
;
}
default
: {
assert
(0);
}
}
}
else
if
(previous_token_is_heredoc) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
return
(
int
) (uint8_t)
';'
;
}
else
{
ch = (uint8_t)*compiler->ch_ptr;
}
switch
(ch) {
case
' '
:
case
'\t'
:
case
'\f'
:
{
compiler->ch_ptr++;
compiler->token_begin_ch_ptr = compiler->ch_ptr;
continue
;
break
;
}
case
'\n'
:
{
assert
(SPVM_TOKE_is_line_terminator(compiler, compiler->ch_ptr));
SPVM_TOKE_parse_line_terminator(compiler, &compiler->ch_ptr);
SPVM_TOKE_increment_current_line(compiler);
compiler->token_begin_ch_ptr = compiler->ch_ptr;
continue
;
break
;
}
case
'.'
: {
if
(var_expansion_state == SPVM_TOKE_C_VAR_EXPANSION_STATE_FIRST_STRING_CONCAT) {
compiler->var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_VAR;
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_CONCAT);
return
'.'
;
}
else
if
(var_expansion_state == SPVM_TOKE_C_VAR_EXPANSION_STATE_SECOND_STRING_CONCAT) {
compiler->var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_BEGIN_NEXT_STRING_LITERAL;
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_CONCAT);
return
'.'
;
}
else
{
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_STRING_CONCAT;
yylvalp->opval = op_special_assign;
return
SPECIAL_ASSIGN;
}
else
{
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_CONCAT);
return
'.'
;
}
}
break
;
}
case
'+'
: {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'+'
) {
compiler->ch_ptr++;
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
return
INC;
}
else
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_ADD;
yylvalp->opval = op_special_assign;
return
SPECIAL_ASSIGN;
}
else
{
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
return
'+'
;
}
break
;
}
case
'-'
: {
compiler->ch_ptr++;
if
(SPVM_TOKE_isdigit_ascii(compiler, *compiler->ch_ptr)) {
before_char_is_minus = 1;
continue
;
}
else
if
(*compiler->ch_ptr ==
'>'
) {
compiler->ch_ptr++;
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
compiler->expect_method_name = 1;
compiler->before_token_is_arrow = 1;
return
ARROW;
}
else
if
(*compiler->ch_ptr ==
'-'
) {
compiler->ch_ptr++;
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
return
DEC;
}
else
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_SUBTRACT;
yylvalp->opval = op_special_assign;
return
SPECIAL_ASSIGN;
}
else
{
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
return
'-'
;
}
break
;
}
case
'*'
: {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_MULTIPLY;
yylvalp->opval = op_special_assign;
return
SPECIAL_ASSIGN;
}
else
{
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
yylvalp->opval = op;
return
'*'
;
}
}
case
'/'
: {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_DIVIDE;
yylvalp->opval = op_special_assign;
return
SPECIAL_ASSIGN;
}
else
{
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DIVIDE);
yylvalp->opval = op;
return
DIVIDE;
}
}
case
'%'
: {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_MODULO;
yylvalp->opval = op_special_assign;
return
SPECIAL_ASSIGN;
}
else
{
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_MODULO);
yylvalp->opval = op;
return
MODULO;
}
}
case
'^'
: {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_BIT_XOR;
yylvalp->opval = op_special_assign;
return
SPECIAL_ASSIGN;
}
else
{
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BIT_XOR);
yylvalp->opval = op;
return
BIT_XOR;
}
}
case
'|'
: {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'|'
) {
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LOGICAL_OR);
yylvalp->opval = op;
return
LOGICAL_OR;
}
else
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_BIT_OR;
yylvalp->opval = op_special_assign;
return
SPECIAL_ASSIGN;
}
else
{
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BIT_OR);
yylvalp->opval = op;
return
BIT_OR;
}
break
;
}
case
'&'
: {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'&'
) {
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LOGICAL_AND);
yylvalp->opval = op;
return
LOGICAL_AND;
}
else
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_BIT_AND;
yylvalp->opval = op_special_assign;
return
SPECIAL_ASSIGN;
}
else
if
(SPVM_TOKE_isalpha_ascii(compiler, *compiler->ch_ptr) || *compiler->ch_ptr ==
'_'
) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_OUTMOST_CLASS);
compiler->expect_method_name = 1;
return
OUTMOST_CLASS;
}
else
{
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BIT_AND);
yylvalp->opval = op;
return
BIT_AND;
}
break
;
}
case
'#'
: {
int32_t is_content_begin = (compiler->ch_ptr == compiler->current_class_content);
int32_t is_line_begin_after_sheban = (compiler->ch_ptr == compiler->line_begin_after_shebang_line_ch_ptr);
int32_t is_line_begin = (compiler->ch_ptr == compiler->line_begin_ch_ptr);
compiler->ch_ptr++;
if
(
strncmp
(compiler->ch_ptr,
"line "
, 5) == 0) {
if
(!is_line_begin) {
SPVM_COMPILER_error(compiler,
"A line directive must begin from the beggining of the line.\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
compiler->ch_ptr += 4;
while
(*compiler->ch_ptr ==
' '
) {
compiler->ch_ptr++;
}
const
char
* line_number_begin_ptr = compiler->ch_ptr;
while
(
isdigit
(*compiler->ch_ptr) || *compiler->ch_ptr ==
'-'
) {
compiler->ch_ptr++;
}
while
(*compiler->ch_ptr ==
' '
) {
compiler->ch_ptr++;
}
if
(!(*compiler->ch_ptr ==
'\n'
)) {
SPVM_COMPILER_error(compiler,
"A line directive must end with \"\\n\".\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
if
(line_number_begin_ptr == compiler->ch_ptr) {
SPVM_COMPILER_error(compiler,
"A line directive must have a line number.\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
errno
= 0;
char
*end;
int64_t line_number = (int64_t)strtoll(line_number_begin_ptr, &end, 10);
if
(!(line_number >= 1 && line_number <= INT32_MAX &&
errno
== 0)) {
SPVM_COMPILER_error(compiler,
"The line number given to a line directive must be a positive 32bit integer.\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
compiler->current_line = (int32_t)line_number;
compiler->ch_ptr++;
compiler->line_begin_ch_ptr = compiler->ch_ptr;
}
else
if
(
strncmp
(compiler->ch_ptr,
"file "
, 5) == 0) {
if
(!(is_content_begin || is_line_begin_after_sheban)) {
SPVM_COMPILER_error(compiler,
"A file directive must begin from the beggining of the source code excluding a shebang line.\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
compiler->ch_ptr += 4;
while
(*compiler->ch_ptr ==
' '
) {
compiler->ch_ptr++;
}
char
* file = NULL;
if
(*compiler->ch_ptr ==
'"'
) {
compiler->ch_ptr++;
const
char
* file_begin_ptr = compiler->ch_ptr;
int32_t file_length = 0;
while
(*compiler->ch_ptr !=
'"'
) {
if
(*compiler->ch_ptr ==
'\n'
) {
SPVM_COMPILER_error(compiler,
"A file in a file directive must end with \".\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
compiler->ch_ptr++;
file_length++;
}
compiler->ch_ptr++;
file = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->current_each_compile_allocator, file_length + 1);
memcpy
(file, file_begin_ptr, file_length);
SPVM_STRING_new(compiler, file, file_length);
}
else
{
SPVM_COMPILER_error(compiler,
"A file directive must start with '\"'.\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
while
(*compiler->ch_ptr ==
' '
) {
compiler->ch_ptr++;
}
if
(!(*compiler->ch_ptr ==
'\n'
)) {
SPVM_COMPILER_error(compiler,
"A file directive must end with \"\\n\".\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
if
(
strlen
(file) == 0) {
SPVM_COMPILER_error(compiler,
"A file directive must have a file path.\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
compiler->current_file = file;
compiler->ch_ptr++;
compiler->line_begin_ch_ptr = compiler->ch_ptr;
}
else
if
(
strncmp
(compiler->ch_ptr,
"lib "
, 4) == 0) {
if
(!is_line_begin) {
SPVM_COMPILER_error(compiler,
"A lib directive must begin from the beggining of the line.\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
compiler->ch_ptr += 3;
while
(*compiler->ch_ptr ==
' '
) {
compiler->ch_ptr++;
}
int32_t include_dir_length = 0;
if
(*compiler->ch_ptr ==
'"'
) {
compiler->ch_ptr++;
const
char
* include_dir_begin_ptr = compiler->ch_ptr;
while
(*compiler->ch_ptr !=
'"'
) {
if
(*compiler->ch_ptr ==
'\n'
) {
SPVM_COMPILER_error(compiler,
"The directory specified by a lib directive must end with \".\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
compiler->ch_ptr++;
include_dir_length++;
}
compiler->ch_ptr++;
}
else
{
SPVM_COMPILER_error(compiler,
"The directory specified by a lib directive must start with '\"'.\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
while
(*compiler->ch_ptr ==
' '
) {
compiler->ch_ptr++;
}
if
(!(*compiler->ch_ptr ==
'\n'
)) {
SPVM_COMPILER_error(compiler,
"The directory specified by a lib directive must end with \"\\n\".\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
if
(include_dir_length == 0) {
SPVM_COMPILER_error(compiler,
"The directory specified by a lib directive must not be an empty string.\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
compiler->ch_ptr++;
compiler->line_begin_ch_ptr = compiler->ch_ptr;
}
else
{
int32_t is_shebang_line = 0;
if
(is_content_begin &&
strncmp
(compiler->ch_ptr,
"! "
, 1) == 0) {
is_shebang_line = 1;
}
while
(1) {
int32_t is_line_terminator = SPVM_TOKE_is_line_terminator(compiler, compiler->ch_ptr);
if
(is_line_terminator) {
SPVM_TOKE_parse_line_terminator(compiler, &compiler->ch_ptr);
SPVM_TOKE_increment_current_line(compiler);
}
if
(is_line_terminator || *compiler->ch_ptr ==
'\0'
) {
break
;
}
else
{
compiler->ch_ptr++;
}
}
if
(is_shebang_line) {
compiler->line_begin_after_shebang_line_ch_ptr = compiler->ch_ptr;
}
}
continue
;
break
;
}
case
'='
: {
if
((compiler->ch_ptr == compiler->current_class_content || *(compiler->ch_ptr - 1) ==
'\n'
) && SPVM_TOKE_isalpha_ascii(compiler, *(compiler->ch_ptr + 1))) {
compiler->ch_ptr++;
while
(1) {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'\n'
) {
compiler->current_line++;
}
if
(*compiler->ch_ptr ==
'\0'
) {
break
;
}
if
(
*compiler->ch_ptr ==
'='
&&
strncmp
(compiler->ch_ptr + 1,
"cut"
, 3) == 0
&& (*(compiler->ch_ptr + 4) ==
'\0'
|| SPVM_TOKE_is_white_space(compiler, *(compiler->ch_ptr + 4)))
)
{
compiler->ch_ptr += 4;
while
(1) {
if
(*compiler->ch_ptr ==
'\n'
|| *compiler->ch_ptr ==
'\0'
) {
break
;
}
compiler->ch_ptr++;
}
break
;
}
}
continue
;
}
else
{
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_COMPARISON_EQ);
yylvalp->opval = op;
return
NUMEQ;
}
if
(*compiler->ch_ptr ==
'>'
) {
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
yylvalp->opval = op;
return
','
;
}
else
{
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ASSIGN);
yylvalp->opval = op;
return
ASSIGN;
}
}
break
;
}
case
'<'
: {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'<'
) {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_LEFT_SHIFT;
yylvalp->opval = op_special_assign;
return
SPECIAL_ASSIGN;
}
else
if
(*compiler->ch_ptr ==
'\''
) {
compiler->ch_ptr++;
const
char
* heredoc_name_start_ptr = compiler->ch_ptr;
while
(SPVM_TOKE_isalnum_ascii(compiler, *compiler->ch_ptr) || *compiler->ch_ptr ==
'_'
) {
compiler->ch_ptr++;
}
int32_t heredoc_name_length = (compiler->ch_ptr - heredoc_name_start_ptr);
if
(heredoc_name_length == 0) {
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);
return
0;
}
char
* heredoc_name = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, heredoc_name_length + 1);
memcpy
(heredoc_name, heredoc_name_start_ptr, heredoc_name_length);
heredoc_name[heredoc_name_length] =
'\0'
;
int32_t comile_error = 0;
if
(SPVM_TOKE_isdigit_ascii(compiler, heredoc_name[0])) {
SPVM_COMPILER_error(compiler,
"A here document name cannot start with a number.\n at %s line %d"
, compiler->current_file, compiler->current_line);
}
else
if
(
strstr
(heredoc_name,
"__"
)) {
SPVM_COMPILER_error(compiler,
"A here document name cannot contain \"__\".\n at %s line %d"
, compiler->current_file, compiler->current_line);
}
else
if
(!(*(compiler->ch_ptr) ==
'\''
&& *(compiler->ch_ptr + 1) ==
';'
&& SPVM_TOKE_is_line_terminator(compiler, compiler->ch_ptr + 2))) {
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);
}
if
(compiler->error_messages->length == 0) {
compiler->ch_ptr += 2;
SPVM_TOKE_parse_line_terminator(compiler, &compiler->ch_ptr);
SPVM_TOKE_increment_current_line(compiler);
char
* heredoc_end_ch_ptr = compiler->ch_ptr;
int32_t heredoc_length = 0;
int32_t previous_is_line_terminator = 1;
char
* heredoc_ptr = compiler->ch_ptr;
int32_t heredoc_begin_line = compiler->current_line;
while
(1) {
if
(previous_is_line_terminator) {
int32_t end_of_heredoc = 0;
if
(
strncmp
(compiler->ch_ptr, heredoc_name, heredoc_name_length) == 0 && SPVM_TOKE_is_line_terminator(compiler, compiler->ch_ptr + heredoc_name_length)) {
compiler->ch_ptr += heredoc_name_length;
SPVM_TOKE_parse_line_terminator(compiler, &compiler->ch_ptr);
SPVM_TOKE_increment_current_line(compiler);
break
;
}
}
int32_t is_line_terminator = SPVM_TOKE_is_line_terminator(compiler, compiler->ch_ptr);
if
(is_line_terminator) {
SPVM_TOKE_parse_line_terminator(compiler, &compiler->ch_ptr);
SPVM_TOKE_increment_current_line(compiler);
heredoc_length++;
previous_is_line_terminator = 1;
}
else
if
(*compiler->ch_ptr ==
'\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);
break
;
}
else
{
heredoc_length++;
compiler->ch_ptr++;
previous_is_line_terminator = 0;
}
}
if
(compiler->error_messages->length == 0) {
char
* heredoc = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, heredoc_length + 1);
int32_t heredoc_index = 0;
while
(heredoc_index < heredoc_length) {
if
(*heredoc_ptr ==
'\0'
) {
assert
(0);
}
else
{
heredoc[heredoc_index] = *heredoc_ptr;
heredoc_ptr++;
heredoc_index++;
}
}
SPVM_OP* op_constant = SPVM_OP_new_op_constant_string(compiler, heredoc, heredoc_length, compiler->current_file, compiler->current_line);
yylvalp->opval = op_constant;
compiler->previous_token_is_heredoc = 1;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, heredoc);
}
}
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, heredoc_name);
if
(compiler->error_messages->length > 0) {
return
0;
}
return
CONSTANT;
}
else
{
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LEFT_SHIFT);
yylvalp->opval = op;
return
SHIFT;
}
}
else
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'>'
) {
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_COMPARISON_CMP);
yylvalp->opval = op;
return
NUMERIC_CMP;
}
else
{
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_COMPARISON_LE);
yylvalp->opval = op;
return
NUMLE;
}
}
else
{
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_COMPARISON_LT);
yylvalp->opval = op;
return
NUMLT;
}
break
;
}
case
'>'
: {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'>'
) {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'>'
) {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_RIGHT_LOGICAL_SHIFT;
yylvalp->opval = op_special_assign;
return
SPECIAL_ASSIGN;
}
else
{
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_RIGHT_LOGICAL_SHIFT);
yylvalp->opval = op;
return
SHIFT;
}
}
else
{
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op_special_assign = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SPECIAL_ASSIGN);
op_special_assign->flag = SPVM_OP_C_FLAG_SPECIAL_ASSIGN_RIGHT_ARITHMETIC_SHIFT;
yylvalp->opval = op_special_assign;
return
SPECIAL_ASSIGN;
}
else
{
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_RIGHT_ARITHMETIC_SHIFT);
yylvalp->opval = op;
return
SHIFT;
}
}
}
else
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_COMPARISON_GE);
yylvalp->opval = op;
return
NUMGE;
}
else
{
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_COMPARISON_GT);
yylvalp->opval = op;
return
NUMGT;
}
break
;
}
case
'!'
: {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'='
) {
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NUMERIC_COMPARISON_NE);
yylvalp->opval = op;
return
NUMNE;
}
else
{
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LOGICAL_NOT);
yylvalp->opval = op;
return
LOGICAL_NOT;
}
break
;
}
case
'~'
: {
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BIT_NOT);
yylvalp->opval = op;
return
BIT_NOT;
break
;
}
case
'\''
: {
compiler->ch_ptr++;
char
ch = 0;
if
(*compiler->ch_ptr ==
'\''
) {
SPVM_COMPILER_error(compiler,
"The character literal cannnot be empty.\n at %s line %d"
, compiler->current_file, compiler->current_line);
compiler->ch_ptr++;
}
else
{
if
(*compiler->ch_ptr ==
'\\'
) {
compiler->ch_ptr++;
if
(*compiler->ch_ptr ==
'a'
) {
ch = 0x07;
compiler->ch_ptr++;
}
else
if
(*compiler->ch_ptr ==
't'
) {
ch = 0x09;
compiler->ch_ptr++;
}
else
if
(*compiler->ch_ptr ==
'n'
) {
ch = 0x0a;
compiler->ch_ptr++;
}
else
if
(*compiler->ch_ptr ==
'f'
) {
ch = 0x0c;
compiler->ch_ptr++;
}
else
if
(*compiler->ch_ptr ==
'r'
) {
ch = 0x0d;
compiler->ch_ptr++;
}
else
if
(*compiler->ch_ptr ==
'\''
) {
ch = 0x27;
compiler->ch_ptr++;
}
else
if
(*compiler->ch_ptr ==
'"'
) {
ch = 0x22;
compiler->ch_ptr++;
}
else
if
(*compiler->ch_ptr ==
'\\'
) {
ch = 0x5c;
compiler->ch_ptr++;
}
else
if
(SPVM_TOKE_is_octal_number(compiler, *compiler->ch_ptr) || *compiler->ch_ptr ==
'o'
) {
ch = SPVM_TOKE_parse_octal_escape(compiler, &compiler->ch_ptr);
}
else
if
(*compiler->ch_ptr ==
'x'
) {
ch = SPVM_TOKE_parse_hex_escape(compiler, &compiler->ch_ptr);
}
else
{
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);
compiler->ch_ptr++;
}
}
else
{
ch = *compiler->ch_ptr;
compiler->ch_ptr++;
}
if
(*compiler->ch_ptr ==
'\''
) {
compiler->ch_ptr++;
}
else
{
SPVM_COMPILER_error(compiler,
"The character literal must ends with \"'\".\n at %s line %d"
, compiler->current_file, compiler->current_line);
}
}
SPVM_OP* op_constant = SPVM_OP_new_op_constant_byte(compiler, ch, compiler->current_file, compiler->current_line);
yylvalp->opval = op_constant;
return
CONSTANT;
}
case
'"'
: {
if
(var_expansion_state == SPVM_TOKE_C_VAR_EXPANSION_STATE_BEGIN_NEXT_STRING_LITERAL) {
compiler->var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_NOT_STARTED;
}
else
{
compiler->ch_ptr++;
}
const
char
* string_literal_begin_ch_ptr = compiler->ch_ptr;
int8_t next_var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_NOT_STARTED;
char
* string_literal_tmp;
int32_t memory_blocks_count_tmp = compiler->current_each_compile_allocator->memory_blocks_count_tmp;
int32_t string_literal_length = 0;
if
(*(compiler->ch_ptr) ==
'"'
) {
string_literal_tmp = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, 1);
string_literal_tmp[0] =
'\0'
;
compiler->ch_ptr++;
}
else
{
int32_t string_literal_finished = 0;
while
(1) {
if
(*compiler->ch_ptr ==
'"'
) {
string_literal_finished = 1;
}
else
if
(*compiler->ch_ptr ==
'$'
) {
if
(*(compiler->ch_ptr + 1) ==
'"'
) {
}
else
{
string_literal_finished = 1;
next_var_expansion_state = SPVM_TOKE_C_VAR_EXPANSION_STATE_FIRST_STRING_CONCAT;
char
* next_string_literal_ch_ptr = compiler->ch_ptr + 1;
int32_t var_is_ref = 0;
if
(*next_string_literal_ch_ptr ==
'$'
) {
next_string_literal_ch_ptr++;
var_is_ref = 1;
}
int32_t var_have_brace = 0;
if
(*next_string_literal_ch_ptr ==
'{'
) {
next_string_literal_ch_ptr++;
var_have_brace = 1;
}
if
(*next_string_literal_ch_ptr ==
'@'
) {
next_string_literal_ch_ptr++;
if
(var_have_brace) {
if
(*next_string_literal_ch_ptr ==
'}'
) {
next_string_literal_ch_ptr++;
}
}
}
else
{
while
(1) {
if
(SPVM_TOKE_isalnum_ascii(compiler, *next_string_literal_ch_ptr) || *next_string_literal_ch_ptr ==
'_'
) {
next_string_literal_ch_ptr++;
}
else
if
(*next_string_literal_ch_ptr ==
':'
&& *(next_string_literal_ch_ptr + 1) ==
':'
) {
next_string_literal_ch_ptr += 2;
}
else
if
(*next_string_literal_ch_ptr ==
'}'
) {
if
(var_have_brace) {
next_string_literal_ch_ptr++;
break
;
}
}
else
{
break
;
}
}
if
(!var_have_brace && !var_is_ref) {
int32_t has_arrow = 0;
int32_t open_getting_field_brace = 0;
int32_t open_bracket = 0;
int32_t is_first_allow = 1;
while
(1) {
if
(!has_arrow) {
if
(*next_string_literal_ch_ptr ==
'-'
&& *(next_string_literal_ch_ptr + 1) ==
'>'
) {
has_arrow = 1;
next_string_literal_ch_ptr += 2;
}
else
{
break
;
}
}
if
(has_arrow) {
has_arrow = 0;
if
(*next_string_literal_ch_ptr ==
'{'
) {
open_getting_field_brace = 1;
next_string_literal_ch_ptr++;
}
else
if
(*next_string_literal_ch_ptr ==
'['
) {
open_bracket = 1;
next_string_literal_ch_ptr++;
}
else
{
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);
return
0;
}
}
while
(SPVM_TOKE_isalnum_ascii(compiler, *next_string_literal_ch_ptr) || *next_string_literal_ch_ptr ==
'_'
) {
next_string_literal_ch_ptr++;
}
if
(open_getting_field_brace) {
if
(*next_string_literal_ch_ptr ==
'}'
) {
next_string_literal_ch_ptr++;
open_getting_field_brace = 0;
}
else
{
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);
return
0;
}
}
else
if
(open_bracket) {
if
(*next_string_literal_ch_ptr ==
']'
) {
next_string_literal_ch_ptr++;
open_bracket = 0;
}
else
{
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);
return
0;
}
}
else
{
assert
(0);
}
if
(*next_string_literal_ch_ptr ==
'-'
&& *(next_string_literal_ch_ptr + 1) ==
'>'
) {
next_string_literal_ch_ptr += 2;
}
if
(!(*next_string_literal_ch_ptr ==
'{'
|| *next_string_literal_ch_ptr ==
'['
)) {
break
;
}
has_arrow = 1;
}
}
}
compiler->next_string_literal_ch_ptr = next_string_literal_ch_ptr;
}
}
else
if
(*compiler->ch_ptr ==
'\0'
) {
string_literal_finished = 1;
}
if
(string_literal_finished) {
break
;
}
else
{
if
(*compiler->ch_ptr ==
'\\'
) {
compiler->ch_ptr += 2;
}
else
{
compiler->ch_ptr++;
}
}
}
if
(*compiler->ch_ptr ==
'\0'
) {
SPVM_COMPILER_error(compiler,
"The string literal must be end with '\"'.\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
int32_t string_literal_tmp_len = (int32_t)(compiler->ch_ptr - string_literal_begin_ch_ptr) * 4;
compiler->ch_ptr++;
string_literal_tmp = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, string_literal_tmp_len + 1);
{
char
* string_literal_ch_ptr = (
char
*)string_literal_begin_ch_ptr;
const
char
* string_literal_end_ch_ptr = compiler->ch_ptr - 1;
while
(string_literal_ch_ptr != string_literal_end_ch_ptr) {
if
(*string_literal_ch_ptr ==
'\\'
) {
string_literal_ch_ptr++;
if
(*string_literal_ch_ptr ==
'a'
) {
string_literal_tmp[string_literal_length] = 0x07;
string_literal_length++;
string_literal_ch_ptr++;
}
else
if
(*string_literal_ch_ptr ==
't'
) {
string_literal_tmp[string_literal_length] = 0x09;
string_literal_length++;
string_literal_ch_ptr++;
}
else
if
(*string_literal_ch_ptr ==
'n'
) {
string_literal_tmp[string_literal_length] = 0x0a;
string_literal_length++;
string_literal_ch_ptr++;
}
else
if
(*string_literal_ch_ptr ==
'f'
) {
string_literal_tmp[string_literal_length] = 0x0c;
string_literal_length++;
string_literal_ch_ptr++;
}
else
if
(*string_literal_ch_ptr ==
'r'
) {
string_literal_tmp[string_literal_length] = 0x0d;
string_literal_length++;
string_literal_ch_ptr++;
}
else
if
(*string_literal_ch_ptr ==
'"'
) {
string_literal_tmp[string_literal_length] = 0x22;
string_literal_length++;
string_literal_ch_ptr++;
}
else
if
(*string_literal_ch_ptr ==
'$'
) {
string_literal_tmp[string_literal_length] = 0x24;
string_literal_length++;
string_literal_ch_ptr++;
}
else
if
(*string_literal_ch_ptr ==
'\''
) {
string_literal_tmp[string_literal_length] = 0x27;
string_literal_length++;
string_literal_ch_ptr++;
}
else
if
(*string_literal_ch_ptr ==
'\\'
) {
string_literal_tmp[string_literal_length] = 0x5c;
string_literal_length++;
string_literal_ch_ptr++;
}
else
if
(SPVM_TOKE_is_octal_number(compiler, *string_literal_ch_ptr) || *string_literal_ch_ptr ==
'o'
) {
ch = SPVM_TOKE_parse_octal_escape(compiler, &string_literal_ch_ptr);
string_literal_tmp[string_literal_length] = ch;
string_literal_length++;
}
else
if
(*string_literal_ch_ptr ==
'x'
) {
ch = SPVM_TOKE_parse_hex_escape(compiler, &string_literal_ch_ptr);
string_literal_tmp[string_literal_length] = ch;
string_literal_length++;
}
else
if
(*string_literal_ch_ptr ==
'N'
&& *(string_literal_ch_ptr + 1) ==
'{'
) {
string_literal_ch_ptr++;
if
(*string_literal_ch_ptr ==
'{'
&& *(string_literal_ch_ptr + 1) ==
'U'
&& *(string_literal_ch_ptr + 2) ==
'+'
) {
string_literal_ch_ptr += 3;
char
* char_start_ptr = string_literal_ch_ptr;
int32_t unicode_chars_length = 0;
while
(SPVM_TOKE_is_hex_number(compiler, *string_literal_ch_ptr)) {
string_literal_ch_ptr++;
unicode_chars_length++;
}
if
(*string_literal_ch_ptr ==
'}'
) {
string_literal_ch_ptr++;
if
(unicode_chars_length < 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);
}
else
if
(unicode_chars_length > 8) {
SPVM_COMPILER_error(compiler,
"Too large Unicode escape character.\n at %s line %d"
, compiler->current_file, compiler->current_line);
}
else
{
int32_t memory_blocks_count_tmp = compiler->current_each_compile_allocator->memory_blocks_count_tmp;
char
* unicode_chars = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, unicode_chars_length + 1);
memcpy
(unicode_chars, char_start_ptr, unicode_chars_length);
char
*end;
int64_t unicode = (int64_t)strtoll(unicode_chars, &end, 16);
int32_t is_valid_utf8_code_point = SPVM_UTF8_is_valid_utf8_code_point(unicode);
if
(is_valid_utf8_code_point) {
char
utf8_chars[4];
int32_t byte_length = SPVM_UTF8_convert_unicode_codepoint_to_utf8_character(unicode, (uint8_t*)utf8_chars);
for
(int32_t byte_index = 0; byte_index < byte_length; byte_index++) {
string_literal_tmp[string_literal_length] = utf8_chars[byte_index];
string_literal_length++;
}
}
else
{
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);
}
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, unicode_chars);
assert
(compiler->current_each_compile_allocator->memory_blocks_count_tmp == memory_blocks_count_tmp);
}
}
else
{
SPVM_COMPILER_error(compiler,
"A Unicode escape character must be closed by \"}\".\n at %s line %d"
, compiler->current_file, compiler->current_line);
}
}
else
{
SPVM_COMPILER_error(compiler,
"Invalid Unicode escape character.\n at %s line %d"
, compiler->current_file, compiler->current_line);
}
}
else
{
switch
(*string_literal_ch_ptr) {
case
'!'
:
case
'#'
:
case
'%'
:
case
'&'
:
case
'('
:
case
')'
:
case
'*'
:
case
'+'
:
case
','
:
case
'-'
:
case
'.'
:
case
'/'
:
case
'1'
:
case
'2'
:
case
'3'
:
case
'4'
:
case
'5'
:
case
'6'
:
case
'7'
:
case
'8'
:
case
'9'
:
case
':'
:
case
';'
:
case
'<'
:
case
'='
:
case
'>'
:
case
'?'
:
case
'@'
:
case
'A'
:
case
'B'
:
case
'D'
:
case
'G'
:
case
'H'
:
case
'K'
:
case
'N'
:
case
'P'
:
case
'R'
:
case
'S'
:
case
'V'
:
case
'W'
:
case
'X'
:
case
'Z'
:
case
'['
:
case
']'
:
case
'^'
:
case
'_'
:
case
'`'
:
case
'b'
:
case
'd'
:
case
'g'
:
case
'h'
:
case
'k'
:
case
'p'
:
case
's'
:
case
'v'
:
case
'w'
:
case
'z'
:
case
'{'
:
case
'|'
:
case
'}'
:
case
'~'
:
{
string_literal_tmp[string_literal_length] =
'\\'
;
string_literal_length++;
string_literal_tmp[string_literal_length] = *string_literal_ch_ptr;
string_literal_length++;
string_literal_ch_ptr++;
break
;
}
default
: {
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);
}
}
}
}
else
{
int32_t is_line_terminator = SPVM_TOKE_is_line_terminator(compiler, string_literal_ch_ptr);
if
(is_line_terminator) {
SPVM_TOKE_parse_line_terminator(compiler, &string_literal_ch_ptr);
SPVM_TOKE_increment_current_line(compiler);
string_literal_tmp[string_literal_length] =
'\n'
;
string_literal_length++;
}
else
{
string_literal_tmp[string_literal_length] = *string_literal_ch_ptr;
string_literal_length++;
string_literal_ch_ptr++;
}
}
}
}
string_literal_tmp[string_literal_length] =
'\0'
;
}
SPVM_STRING* string_literal_string = SPVM_STRING_new(compiler, string_literal_tmp, string_literal_length);
const
char
* string_literal = string_literal_string->value;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, string_literal_tmp);
assert
(compiler->current_each_compile_allocator->memory_blocks_count_tmp == memory_blocks_count_tmp);
SPVM_OP* op_constant = SPVM_OP_new_op_constant_string(compiler, string_literal, string_literal_length, compiler->current_file, compiler->current_line);
yylvalp->opval = op_constant;
if
(next_var_expansion_state == SPVM_TOKE_C_VAR_EXPANSION_STATE_FIRST_STRING_CONCAT) {
compiler->var_expansion_state = next_var_expansion_state;
compiler->ch_ptr--;
}
return
CONSTANT;
}
case
'\\'
: {
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_REFERENCE);
yylvalp->opval = op;
return
REFERENCE;
}
case
'$'
: {
if
(*(compiler->ch_ptr + 1) ==
'$'
) {
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DEREFERENCE);
yylvalp->opval = op;
return
DEREFERENCE;
}
else
if
(*(compiler->ch_ptr + 1) ==
'@'
) {
compiler->ch_ptr += 2;
SPVM_OP* op_exception_var = SPVM_OP_new_op(compiler, SPVM_OP_C_ID_EXCEPTION_VAR, compiler->current_file, compiler->current_line);
yylvalp->opval = op_exception_var;
return
EXCEPTION_VAR;
}
else
if
(*(compiler->ch_ptr + 1) ==
'{'
&& *(compiler->ch_ptr + 2) ==
'@'
&& *(compiler->ch_ptr + 3) ==
'}'
) {
compiler->ch_ptr += 4;
SPVM_OP* op_exception_var = SPVM_OP_new_op(compiler, SPVM_OP_C_ID_EXCEPTION_VAR, compiler->current_file, compiler->current_line);
yylvalp->opval = op_exception_var;
return
EXCEPTION_VAR;
}
else
{
compiler->ch_ptr++;
int8_t have_brace = 0;
if
(*compiler->ch_ptr ==
'{'
) {
have_brace = 1;
compiler->ch_ptr++;
}
const
char
* var_name_symbol_name_part_start_ptr = compiler->ch_ptr;
while
(
SPVM_TOKE_isalnum_ascii(compiler, *compiler->ch_ptr)
|| (*compiler->ch_ptr) ==
'_'
|| (*compiler->ch_ptr ==
':'
&& *(compiler->ch_ptr + 1) ==
':'
)
)
{
if
(*compiler->ch_ptr ==
':'
&& *(compiler->ch_ptr + 1) ==
':'
) {
compiler->ch_ptr += 2;
}
else
{
compiler->ch_ptr++;
}
}
int32_t var_name_symbol_name_part_length = compiler->ch_ptr - var_name_symbol_name_part_start_ptr;
int32_t var_name_length = var_name_symbol_name_part_length + 1;
const
char
* var_name = NULL;
{
int32_t memory_blocks_count_tmp_var_name_tmp = compiler->current_each_compile_allocator->memory_blocks_count_tmp;
char
* var_name_tmp = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, var_name_length + 1);
var_name_tmp[0] =
'$'
;
memcpy
(&var_name_tmp[1], var_name_symbol_name_part_start_ptr, var_name_symbol_name_part_length);
var_name_tmp[1 + var_name_symbol_name_part_length] =
'\0'
;
SPVM_STRING* var_name_string = SPVM_STRING_new(compiler, var_name_tmp, 1 + var_name_symbol_name_part_length);
var_name = var_name_string->value;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, var_name_tmp);
assert
(compiler->current_each_compile_allocator->memory_blocks_count_tmp == memory_blocks_count_tmp_var_name_tmp);
}
if
(have_brace) {
if
(*compiler->ch_ptr ==
'}'
) {
compiler->ch_ptr++;
}
else
{
SPVM_COMPILER_error(compiler,
"The variable name is not closed by \"}\".\n at %s line %d"
, compiler->current_file, compiler->current_line);
}
}
{
if
(
strstr
(var_name,
"__"
)) {
SPVM_COMPILER_error(compiler,
"The variable name \"%s\" cannnot contain \"__\".\n at %s line %d"
, var_name, compiler->current_file, compiler->current_line);
}
if
(var_name_symbol_name_part_length >= 2 && var_name[1] ==
':'
&& var_name[2] ==
':'
) {
SPVM_COMPILER_error(compiler,
"The variable name \"%s\" cannnot begin with \"$::\".\n at %s line %d"
, var_name, compiler->current_file, compiler->current_line);
}
if
(var_name_symbol_name_part_length >= 2 && var_name[var_name_length - 1] ==
':'
&& var_name[var_name_length - 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);
}
if
(
strstr
(var_name,
"::::"
)) {
SPVM_COMPILER_error(compiler,
"The variable name \"%s\" cannnot contain \"::::\".\n at %s line %d"
, var_name, compiler->current_file, compiler->current_line);
}
if
(var_name_symbol_name_part_length >= 1 && SPVM_TOKE_isdigit_ascii(compiler, var_name[1])) {
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);
}
}
SPVM_OP* op_name = SPVM_OP_new_op_name(compiler, var_name, compiler->current_file, compiler->current_line);
yylvalp->opval = op_name;
return
VAR_NAME;
}
}
case
'('
:
case
')'
:
case
'['
:
case
']'
:
case
'{'
:
case
'}'
:
case
','
:
case
':'
:
case
';'
:
case
'@'
:
{
compiler->ch_ptr++;
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DO_NOTHING);
if
(before_token_is_arrow && ch ==
'{'
) {
compiler->expect_field_name = 1;
}
return
(
int
) (uint8_t) ch;
}
default
: {
if
(ch ==
'q'
&& *(compiler->ch_ptr + 1) ==
'\''
) {
compiler->ch_ptr += 2;
const
char
* string_literal_begin_ch_ptr = compiler->ch_ptr;
char
* string_literal_tmp = NULL;
int32_t memory_blocks_count_tmp = compiler->current_each_compile_allocator->memory_blocks_count_tmp;
int32_t string_literal_length = 0;
if
(*(compiler->ch_ptr) ==
'\''
) {
string_literal_tmp = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, 1);
string_literal_tmp[0] =
'\0'
;
compiler->ch_ptr++;
}
else
{
int32_t string_literal_finished = 0;
while
(1) {
if
(*compiler->ch_ptr ==
'\''
) {
string_literal_finished = 1;
}
else
if
(*compiler->ch_ptr ==
'\0'
) {
string_literal_finished = 1;
}
if
(string_literal_finished) {
break
;
}
else
{
if
(*compiler->ch_ptr ==
'\\'
) {
compiler->ch_ptr += 2;
}
else
{
compiler->ch_ptr++;
}
}
}
if
(*compiler->ch_ptr ==
'\0'
) {
SPVM_COMPILER_error(compiler,
"A single-quoted string literal must be end with \"'\".\n at %s line %d"
, compiler->current_file, compiler->current_line);
return
0;
}
int32_t string_literal_tmp_len = (int32_t)(compiler->ch_ptr - string_literal_begin_ch_ptr);
compiler->ch_ptr++;
string_literal_tmp = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, string_literal_tmp_len + 1);
{
char
* string_literal_ch_ptr = (
char
*)string_literal_begin_ch_ptr;
const
char
* string_literal_end_ch_ptr = compiler->ch_ptr - 1;
while
(string_literal_ch_ptr != string_literal_end_ch_ptr) {
if
(*string_literal_ch_ptr ==
'\\'
) {
string_literal_ch_ptr++;
if
(*string_literal_ch_ptr ==
'\\'
) {
string_literal_tmp[string_literal_length] =
'\\'
;
string_literal_length++;
string_literal_ch_ptr++;
}
else
if
(*string_literal_ch_ptr ==
'\''
) {
string_literal_tmp[string_literal_length] =
'\''
;
string_literal_length++;
string_literal_ch_ptr++;
}
else
{
SPVM_COMPILER_error(compiler,
"The escape character \"\\%c\" in a single-quoted string literal is invalid.\n at %s line %d"
, *string_literal_ch_ptr, compiler->current_file, compiler->current_line);
}
}
else
{
int32_t is_line_terminator = SPVM_TOKE_is_line_terminator(compiler, string_literal_ch_ptr);
if
(is_line_terminator) {
SPVM_TOKE_parse_line_terminator(compiler, &string_literal_ch_ptr);
SPVM_TOKE_increment_current_line(compiler);
string_literal_tmp[string_literal_length] =
'\n'
;
string_literal_length++;
}
else
{
string_literal_tmp[string_literal_length] = *string_literal_ch_ptr;
string_literal_length++;
string_literal_ch_ptr++;
}
}
}
}
string_literal_tmp[string_literal_length] =
'\0'
;
}
SPVM_STRING* string_literal_string = SPVM_STRING_new(compiler, string_literal_tmp, string_literal_length);
const
char
* string_literal = string_literal_string->value;
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, string_literal_tmp);
assert
(compiler->current_each_compile_allocator->memory_blocks_count_tmp == memory_blocks_count_tmp);
SPVM_OP* op_constant = SPVM_OP_new_op_constant_string(compiler, string_literal, string_literal_length, compiler->current_file, compiler->current_line);
yylvalp->opval = op_constant;
return
CONSTANT;
}
else
if
(SPVM_TOKE_isdigit_ascii(compiler, ch)) {
const
char
* number_literal_begin_ptr = compiler->ch_ptr;
int32_t minus = 0;
if
(before_char_is_minus) {
before_char_is_minus = 0;
minus = 1;
}
int32_t digit = 0;
if
(*(compiler->ch_ptr) ==
'0'
) {
if
(*(compiler->ch_ptr + 1) ==
'x'
|| *(compiler->ch_ptr + 1) ==
'X'
) {
digit = 16;
}
else
if
(*(compiler->ch_ptr + 1) ==
'b'
|| *(compiler->ch_ptr + 1) ==
'B'
) {
digit = 2;
}
else
if
(SPVM_TOKE_isdigit_ascii(compiler, *(compiler->ch_ptr + 1)) || *(compiler->ch_ptr + 1) ==
'_'
) {
digit = 8;
}
else
{
digit = 10;
}
}
else
{
digit = 10;
}
int32_t is_floating_number = 0;
int32_t is_hex_floating_number = 0;
compiler->ch_ptr++;
int32_t before_is_exponant = 0;
if
(digit == 16) {
compiler->ch_ptr += 2;
while
(
SPVM_TOKE_is_hex_number(compiler, *compiler->ch_ptr) || *compiler->ch_ptr ==
'_'
|| *compiler->ch_ptr ==
'.'
|| *compiler->ch_ptr ==
'p'
|| *compiler->ch_ptr ==
'P'
|| *compiler->ch_ptr ==
'-'
|| *compiler->ch_ptr ==
'+'
)
{
if
(!before_is_exponant && (*compiler->ch_ptr ==
'-'
|| *compiler->ch_ptr ==
'+'
)) {
break
;
}
if
(*compiler->ch_ptr ==
'.'
|| *compiler->ch_ptr ==
'p'
|| *compiler->ch_ptr ==
'P'
) {
is_floating_number = 1;
}
if
(*compiler->ch_ptr ==
'p'
|| *compiler->ch_ptr ==
'P'
) {
is_hex_floating_number = 1;
before_is_exponant = 1;
}
compiler->ch_ptr++;
}
}
else
if
(digit == 8 || digit == 2) {
compiler->ch_ptr += 1;
while
(
SPVM_TOKE_isdigit_ascii(compiler, *compiler->ch_ptr)
|| *compiler->ch_ptr ==
'_'
)
{
compiler->ch_ptr++;
}
}
else
{
while
(
SPVM_TOKE_isdigit_ascii(compiler, *compiler->ch_ptr)
|| *compiler->ch_ptr ==
'.'
|| *compiler->ch_ptr ==
'-'
|| *compiler->ch_ptr ==
'+'
|| *compiler->ch_ptr ==
'e'
|| *compiler->ch_ptr ==
'E'
|| *compiler->ch_ptr ==
'_'
)
{
if
(!before_is_exponant && (*compiler->ch_ptr ==
'-'
|| *compiler->ch_ptr ==
'+'
)) {
break
;
}
if
(*compiler->ch_ptr ==
'.'
|| *compiler->ch_ptr ==
'e'
|| *compiler->ch_ptr ==
'E'
) {
is_floating_number = 1;
before_is_exponant = 1;
}
compiler->ch_ptr++;
}
}
int32_t str_len = (compiler->ch_ptr - number_literal_begin_ptr);
int32_t numeric_literal_memoyr_blocks_count = compiler->current_each_compile_allocator->memory_blocks_count_tmp;
char
* numeric_literal = (
char
*)SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, str_len + 1);
int32_t pos = 0;
{
int32_t i;
for
(i = 0; i < str_len; i++) {
if
(*(number_literal_begin_ptr + i) !=
'_'
) {
*(numeric_literal + pos) = *(number_literal_begin_ptr + i);
pos++;
}
}
numeric_literal[pos] =
'\0'
;
}
if
(is_hex_floating_number && !SPVM_TOKE_isdigit_ascii(compiler, *(compiler->ch_ptr - 1))) {
compiler->ch_ptr--;
numeric_literal[pos - 1] =
'\0'
;
}
SPVM_TYPE* constant_type;
char
suffix[2];
suffix[1] =
'\0'
;
if
(*compiler->ch_ptr ==
'l'
|| *compiler->ch_ptr ==
'L'
) {
suffix[0] = *compiler->ch_ptr;
constant_type = SPVM_TYPE_new_long_type(compiler);
compiler->ch_ptr++;
}
else
if
(*compiler->ch_ptr ==
'f'
|| *compiler->ch_ptr ==
'F'
) {
suffix[0] = *compiler->ch_ptr;
constant_type = SPVM_TYPE_new_float_type(compiler);
compiler->ch_ptr++;
}
else
if
(*compiler->ch_ptr ==
'd'
|| *compiler->ch_ptr ==
'D'
) {
suffix[0] = *compiler->ch_ptr;
constant_type = SPVM_TYPE_new_double_type(compiler);
compiler->ch_ptr++;
}
else
{
suffix[0] =
'\0'
;
if
(is_floating_number) {
constant_type = SPVM_TYPE_new_double_type(compiler);
}
else
{
constant_type = SPVM_TYPE_new_int_type(compiler);
}
}
SPVM_VALUE num;
if
(constant_type->basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_INT) {
errno
= 0;
int32_t out_of_range = 0;
int32_t parse_start_offset;
if
(digit == 16) {
parse_start_offset = 2;
}
else
if
(digit == 8) {
parse_start_offset = 1;
}
else
if
(digit == 2) {
parse_start_offset = 2;
}
else
if
(digit == 10) {
parse_start_offset = 0;
}
else
{
assert
(0);
}
char
*end;
uint64_t num_uint64_nosign = strtoull(numeric_literal + parse_start_offset, &end, digit);
if
(*end !=
'\0'
) {
out_of_range = 1;
}
else
if
(
errno
== ERANGE) {
out_of_range = 1;
}
else
{
if
(digit == 16 || digit == 8 || digit == 2) {
if
(num_uint64_nosign > UINT32_MAX) {
out_of_range = 1;
}
}
else
{
if
(minus) {
if
(num_uint64_nosign > ((uint32_t)INT32_MAX + 1)) {
out_of_range = 1;
}
}
else
{
if
(num_uint64_nosign > INT32_MAX) {
out_of_range = 1;
}
}
}
}
if
(out_of_range) {
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);
}
if
(digit == 16 || digit == 8 || digit == 2) {
num.ival = (int32_t)(uint32_t)num_uint64_nosign;
if
(minus) {
num.ival = -num.ival;
}
}
else
{
num.ival = minus ? (int32_t)-num_uint64_nosign : (int32_t)num_uint64_nosign;
}
}
else
if
(constant_type->basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_LONG) {
errno
= 0;
int32_t invalid = 0;
int32_t parse_start_offset;
if
(digit == 16) {
parse_start_offset = 2;
}
else
if
(digit == 8) {
parse_start_offset = 1;
}
else
if
(digit == 2) {
parse_start_offset = 2;
}
else
if
(digit == 10) {
parse_start_offset = 0;
}
else
{
assert
(0);
}
char
*end;
uint64_t num_uint64_nosign = strtoull(numeric_literal + parse_start_offset, &end, digit);
if
(*end !=
'\0'
) {
invalid = 1;
}
else
if
(
errno
== ERANGE) {
invalid = 1;
}
else
{
if
(digit == 16 || digit == 8 || digit == 2) {
if
(num_uint64_nosign > UINT64_MAX) {
invalid = 1;
}
}
else
{
if
(minus) {
if
(num_uint64_nosign > ((uint64_t)INT64_MAX + 1)) {
invalid = 1;
}
}
else
{
if
(num_uint64_nosign > INT64_MAX) {
invalid = 1;
}
}
}
}
if
(invalid) {
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);
}
if
(digit == 16 || digit == 8 || digit == 2) {
num.lval = (int64_t)(uint64_t)num_uint64_nosign;
if
(minus) {
num.lval = -num.lval;
}
}
else
{
num.lval = minus ? (int64_t)-num_uint64_nosign : (int64_t)num_uint64_nosign;
}
}
else
if
(constant_type->basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT) {
char
*end;
num.fval = strtof(numeric_literal, &end);
if
(*end !=
'\0'
) {
SPVM_COMPILER_error(compiler,
"Invalid float literal.\n at %s line %d"
, compiler->current_file, compiler->current_line);
}
if
(minus) {
num.fval = -num.fval;
}
}
else
if
(constant_type->basic_type->id == SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE) {
char
*end;
num.dval =
strtod
(numeric_literal, &end);
if
(*end !=
'\0'
) {
SPVM_COMPILER_error(compiler,
"Invalid double literal.\n at %s line %d"
, compiler->current_file, compiler->current_line);
}
if
(minus) {
num.dval = -num.dval;
}
}
else
{
assert
(0);
}
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, numeric_literal);
assert
(compiler->current_each_compile_allocator->memory_blocks_count_tmp == numeric_literal_memoyr_blocks_count);
SPVM_OP* op_constant;
switch
(constant_type->basic_type->id) {
case
SPVM_NATIVE_C_BASIC_TYPE_ID_INT: {
op_constant = SPVM_OP_new_op_constant_int(compiler, num.ival, compiler->current_file, compiler->current_line);
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_LONG: {
op_constant = SPVM_OP_new_op_constant_long(compiler, num.lval, compiler->current_file, compiler->current_line);
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_FLOAT: {
op_constant = SPVM_OP_new_op_constant_float(compiler, num.fval, compiler->current_file, compiler->current_line);
break
;
}
case
SPVM_NATIVE_C_BASIC_TYPE_ID_DOUBLE: {
op_constant = SPVM_OP_new_op_constant_double(compiler, num.dval, compiler->current_file, compiler->current_line);
break
;
}
default
: {
assert
(0);
}
}
yylvalp->opval = op_constant;
return
CONSTANT;
}
else
if
(SPVM_TOKE_isalpha_ascii(compiler, ch) || ch ==
'_'
) {
int32_t column = compiler->ch_ptr - compiler->line_begin_ch_ptr;
const
char
* symbol_name_start_ptr = compiler->ch_ptr;
compiler->ch_ptr++;
while
(SPVM_TOKE_isalnum_ascii(compiler, *compiler->ch_ptr)
|| *compiler->ch_ptr ==
'_'
|| (*compiler->ch_ptr ==
':'
&& *(compiler->ch_ptr + 1) ==
':'
))
{
if
(*compiler->ch_ptr ==
':'
&& *(compiler->ch_ptr + 1) ==
':'
) {
compiler->ch_ptr += 2;
}
else
{
compiler->ch_ptr++;
}
}
int32_t symbol_name_length = (compiler->ch_ptr - symbol_name_start_ptr);
char
* symbol_name = SPVM_ALLOCATOR_alloc_memory_block_tmp(compiler->current_each_compile_allocator, symbol_name_length + 1);
memcpy
(symbol_name, symbol_name_start_ptr, symbol_name_length);
symbol_name[symbol_name_length] =
'\0'
;
int32_t next_is_fat_camma = 0;
char
* fat_camma_check_ptr = compiler->ch_ptr;
while
(SPVM_TOKE_is_white_space(compiler, *fat_camma_check_ptr)) {
fat_camma_check_ptr++;
}
if
(*fat_camma_check_ptr ==
'='
&& *(fat_camma_check_ptr + 1) ==
'>'
) {
next_is_fat_camma = 1;
}
else
{
next_is_fat_camma = 0;
}
int32_t keyword_token = 0;
if
(next_is_fat_camma) {
}
else
if
(expect_method_name) {
}
else
if
(expect_field_name) {
}
else
{
switch
(symbol_name[0]) {
case
'a'
: {
if
(
strcmp
(symbol_name,
"alias"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ALIAS);
keyword_token = ALIAS;
}
else
if
(
strcmp
(symbol_name,
"allow"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ALLOW);
keyword_token = ALLOW;
}
else
if
(
strcmp
(symbol_name,
"args_width"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ARGS_WIDTH);
keyword_token = ARGS_WIDTH;
}
else
if
(
strcmp
(symbol_name,
"as"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_AS);
keyword_token = AS;
}
break
;
}
case
'b'
: {
if
(
strcmp
(symbol_name,
"basic_type_id"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BASIC_TYPE_ID);
keyword_token = BASIC_TYPE_ID;
}
else
if
(
strcmp
(symbol_name,
"break"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BREAK);
keyword_token = BREAK;
}
else
if
(
strcmp
(symbol_name,
"byte"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_BYTE);
keyword_token =
BYTE
;
}
break
;
}
case
'c'
: {
if
(
strcmp
(symbol_name,
"cache"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_CACHE, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
else
if
(
strcmp
(symbol_name,
"can"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CAN);
keyword_token = CAN;
}
else
if
(
strcmp
(symbol_name,
"case"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CASE);
keyword_token = CASE;
}
else
if
(
strcmp
(symbol_name,
"cmp"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_COMPARISON_CMP);
keyword_token = STRING_CMP;
}
else
if
(
strcmp
(symbol_name,
"class"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CLASS);
keyword_token = CLASS;
}
else
if
(
strcmp
(symbol_name,
"compile_type_name"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_COMPILE_TYPE_NAME);
keyword_token = COMPILE_TYPE_NAME;
}
else
if
(
strcmp
(symbol_name,
"copy"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_COPY);
keyword_token = COPY;
}
break
;
}
case
'd'
: {
if
(
strcmp
(symbol_name,
"default"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DEFAULT);
keyword_token = DEFAULT;
}
else
if
(
strcmp
(symbol_name,
"die"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DIE);
keyword_token = DIE;
}
else
if
(
strcmp
(symbol_name,
"div_uint"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DIVIDE_UNSIGNED_INT);
keyword_token = DIVIDE_UNSIGNED_INT;
}
else
if
(
strcmp
(symbol_name,
"div_ulong"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DIVIDE_UNSIGNED_LONG);
keyword_token = DIVIDE_UNSIGNED_LONG;
}
else
if
(
strcmp
(symbol_name,
"double"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DOUBLE);
keyword_token = DOUBLE;
}
else
if
(
strcmp
(symbol_name,
"dump"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_DUMP);
keyword_token = DUMP;
}
break
;
}
case
'e'
: {
if
(
strcmp
(symbol_name,
"elsif"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ELSIF);
keyword_token = ELSIF;
}
else
if
(
strcmp
(symbol_name,
"else"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ELSE);
keyword_token = ELSE;
}
else
if
(
strcmp
(symbol_name,
"enum"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ENUM);
keyword_token = ENUM;
}
else
if
(
strcmp
(symbol_name,
"eq"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_COMPARISON_EQ);
keyword_token = STREQ;
}
else
if
(
strcmp
(symbol_name,
"eval"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_EVAL);
keyword_token = EVAL;
}
else
if
(
strcmp
(symbol_name,
"eval_error_id"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_EVAL_ERROR_ID);
keyword_token = EVAL_ERROR_ID;
}
else
if
(
strcmp
(symbol_name,
"extends"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_EXTENDS);
keyword_token = EXTENDS;
}
break
;
}
case
'f'
: {
if
(
strcmp
(symbol_name,
"for"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_FOR);
keyword_token = FOR;
}
else
if
(
strcmp
(symbol_name,
"float"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_FLOAT);
keyword_token =
FLOAT
;
}
else
if
(
strcmp
(symbol_name,
"false"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_FALSE);
keyword_token = FALSE;
}
break
;
}
case
'g'
: {
if
(
strcmp
(symbol_name,
"gt"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_COMPARISON_GT);
keyword_token = STRGT;
}
else
if
(
strcmp
(symbol_name,
"ge"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_COMPARISON_GE);
keyword_token = STRGE;
}
break
;
}
case
'h'
: {
if
(
strcmp
(symbol_name,
"has"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_FIELD);
compiler->expect_field_name = 1;
keyword_token = HAS;
}
break
;
}
case
'i'
: {
if
(
strcmp
(symbol_name,
"if"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IF);
keyword_token = IF;
}
else
if
(
strcmp
(symbol_name,
"interface"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_INTERFACE);
keyword_token = INTERFACE;
}
else
if
(
strcmp
(symbol_name,
"int"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_INT);
keyword_token =
INT
;
}
else
if
(
strcmp
(symbol_name,
"interface_t"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_INTERFACE_T, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
else
if
(
strcmp
(symbol_name,
"isa"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ISA);
keyword_token = ISA;
}
else
if
(
strcmp
(symbol_name,
"isa_error"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ISA_ERROR);
keyword_token = ISA_ERROR;
}
else
if
(
strcmp
(symbol_name,
"isweak"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_ISWEAK);
keyword_token = ISWEAK;
}
else
if
(
strcmp
(symbol_name,
"is_compile_type"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IS_COMPILE_TYPE);
keyword_token = IS_COMPILE_TYPE;
}
else
if
(
strcmp
(symbol_name,
"is_type"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IS_TYPE);
keyword_token = IS_TYPE;
}
else
if
(
strcmp
(symbol_name,
"is_error"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IS_ERROR);
keyword_token = IS_ERROR;
}
else
if
(
strcmp
(symbol_name,
"is_read_only"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_IS_READ_ONLY);
keyword_token = IS_READ_ONLY;
}
break
;
}
case
'l'
: {
if
(
strcmp
(symbol_name,
"last"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LAST);
keyword_token = LAST;
}
else
if
(
strcmp
(symbol_name,
"length"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_LENGTH);
keyword_token = STRING_LENGTH;
}
else
if
(
strcmp
(symbol_name,
"lt"
) == 0) {
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_COMPARISON_LT);
yylvalp->opval = op;
keyword_token = STRLT;
}
else
if
(
strcmp
(symbol_name,
"le"
) == 0) {
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_COMPARISON_LE);
yylvalp->opval = op;
keyword_token = STRLE;
}
else
if
(
strcmp
(symbol_name,
"long"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_LONG);
keyword_token =
LONG
;
}
break
;
}
case
'm'
: {
if
(
strcmp
(symbol_name,
"make_read_only"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_MAKE_READ_ONLY);
keyword_token = MAKE_READ_ONLY;
}
else
if
(
strcmp
(symbol_name,
"method"
) == 0) {
SPVM_OP* op_method = SPVM_TOKE_new_op_with_column(compiler, SPVM_OP_C_ID_METHOD, column);
yylvalp->opval = op_method;
compiler->expect_method_name = 1;
keyword_token = METHOD;
}
else
if
(
strcmp
(symbol_name,
"mod_uint"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_MODULO_UNSIGNED_INT);
keyword_token = MODULO_UNSIGNED_INT;
}
else
if
(
strcmp
(symbol_name,
"mod_ulong"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_MODULO_UNSIGNED_LONG);
keyword_token = MODULO_UNSIGNED_LONG;
}
else
if
(
strcmp
(symbol_name,
"mulnum_t"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_MULNUM_T, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
else
if
(
strcmp
(symbol_name,
"mutable"
) == 0) {
SPVM_OP* op_mutable = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_MUTABLE);
keyword_token = MUTABLE;
}
else
if
(
strcmp
(symbol_name,
"my"
) == 0) {
SPVM_OP* op_var_decl = SPVM_OP_new_op_var_decl(compiler, compiler->current_file, compiler->current_line);
yylvalp->opval = op_var_decl;
keyword_token = MY;
}
break
;
}
case
'n'
: {
if
(
strcmp
(symbol_name,
"native"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_NATIVE, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
else
if
(
strcmp
(symbol_name,
"ne"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING_COMPARISON_NE);
keyword_token = STRNE;
}
else
if
(
strcmp
(symbol_name,
"next"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NEXT);
keyword_token = NEXT;
}
else
if
(
strcmp
(symbol_name,
"new"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NEW);
keyword_token = NEW;
}
else
if
(
strcmp
(symbol_name,
"new_string_len"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_NEW_STRING_LEN);
keyword_token = NEW_STRING_LEN;
}
break
;
}
case
'o'
: {
if
(
strcmp
(symbol_name,
"of"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_OF);
keyword_token = OF;
}
else
if
(
strcmp
(symbol_name,
"our"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_CLASS_VAR);
keyword_token = OUR;
}
else
if
(
strcmp
(symbol_name,
"object"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_OBJECT);
keyword_token = OBJECT;
}
break
;
}
case
'p'
: {
if
(
strcmp
(symbol_name,
"print"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_PRINT);
keyword_token = PRINT;
}
else
if
(
strcmp
(symbol_name,
"private"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_PRIVATE, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
else
if
(
strcmp
(symbol_name,
"protected"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_PROTECTED, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
else
if
(
strcmp
(symbol_name,
"public"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_PUBLIC, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
else
if
(
strcmp
(symbol_name,
"precompile"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_PRECOMPILE, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
else
if
(
strcmp
(symbol_name,
"pointer"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_POINTER, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
break
;
}
case
'r'
: {
if
(
strcmp
(symbol_name,
"return"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_RETURN);
keyword_token = RETURN;
}
else
if
(
strcmp
(symbol_name,
"require"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_REQUIRE);
keyword_token = REQUIRE;
}
else
if
(
strcmp
(symbol_name,
"required"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_REQUIRED, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
else
if
(
strcmp
(symbol_name,
"rw"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_RW, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
else
if
(
strcmp
(symbol_name,
"ro"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_RO, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
break
;
}
case
's'
: {
if
(
strcmp
(symbol_name,
"say"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SAY);
keyword_token = SAY;
}
else
if
(
strcmp
(symbol_name,
"static"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_STATIC, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
else
if
(
strcmp
(symbol_name,
"switch"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SWITCH);
keyword_token = SWITCH;
}
else
if
(
strcmp
(symbol_name,
"string"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_STRING);
keyword_token = STRING;
}
else
if
(
strcmp
(symbol_name,
"short"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SHORT);
keyword_token =
SHORT
;
}
else
if
(
strcmp
(symbol_name,
"scalar"
) == 0) {
compiler->ch_ptr++;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_SCALAR);
yylvalp->opval = op;
keyword_token = SCALAR;
}
break
;
}
case
't'
: {
if
(
strcmp
(symbol_name,
"true"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_TRUE);
keyword_token = TRUE;
}
else
if
(
strcmp
(symbol_name,
"type_name"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_TYPE_NAME);
keyword_token = TYPE_NAME;
}
break
;
}
case
'u'
: {
if
(
strcmp
(symbol_name,
"undef"
) == 0) {
yylvalp->opval = SPVM_OP_new_op_undef(compiler, compiler->current_file, compiler->current_line);
keyword_token = UNDEF;
}
else
if
(
strcmp
(symbol_name,
"unless"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_UNLESS);
keyword_token = UNLESS;
}
else
if
(
strcmp
(symbol_name,
"unweaken"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_UNLESS);
keyword_token = UNWEAKEN;
}
else
if
(
strcmp
(symbol_name,
"use"
) == 0) {
yylvalp->opval = SPVM_OP_new_op_use(compiler, compiler->current_file, compiler->current_line);
keyword_token = USE;
}
break
;
}
case
'v'
: {
if
(
strcmp
(symbol_name,
"version"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_VERSION_DECL);
keyword_token = VERSION_DECL;
}
else
if
(
strcmp
(symbol_name,
"version_from"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_VERSION_FROM);
keyword_token = VERSION_FROM;
}
else
if
(
strcmp
(symbol_name,
"void"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_VOID);
keyword_token =
VOID
;
}
break
;
}
case
'w'
: {
if
(
strcmp
(symbol_name,
"warn"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_WARN);
keyword_token = WARN;
}
else
if
(
strcmp
(symbol_name,
"while"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_WHILE);
keyword_token = WHILE;
}
else
if
(
strcmp
(symbol_name,
"weaken"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_WEAKEN);
keyword_token = WEAKEN;
}
else
if
(
strcmp
(symbol_name,
"wo"
) == 0) {
SPVM_OP* op_attribute = SPVM_OP_new_op_attribute(compiler, SPVM_ATTRIBUTE_C_ID_WO, compiler->current_file, compiler->current_line);
yylvalp->opval = op_attribute;
keyword_token = ATTRIBUTE;
}
break
;
}
case
'I'
: {
if
(
strcmp
(symbol_name,
"INIT"
) == 0) {
yylvalp->opval = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_INIT);
keyword_token = INIT;
}
break
;
}
case
'_'
: {
if
(
strcmp
(symbol_name,
"__END__"
) == 0) {
compiler->ch_ptr = compiler->current_class_content + compiler->current_class_content_length;
compiler->token_begin_ch_ptr = compiler->ch_ptr;
compiler->end_of_file = 1;
SPVM_OP* op = SPVM_TOKE_new_op(compiler, SPVM_OP_C_ID_END_OF_FILE);
yylvalp->opval = op;
keyword_token = END_OF_FILE;
}
else
if
(
strcmp
(symbol_name,
"__PACKAGE__"
) == 0) {
yylvalp->opval = SPVM_OP_new_op(compiler, SPVM_OP_C_ID_OUTMOST_CLASS_NAME, compiler->current_file, compiler->current_line);
keyword_token = OUTMOST_CLASS_NAME;
}
else
if
(
strcmp
(symbol_name,
"__FILE__"
) == 0) {
SPVM_OP* op_constant = SPVM_OP_new_op_constant_string(compiler, compiler->current_file,
strlen
(compiler->current_file), compiler->current_file, compiler->current_line);
yylvalp->opval = op_constant;
keyword_token = CONSTANT;
}
else
if
(
strcmp
(symbol_name,
"__LINE__"
) == 0) {
SPVM_OP* op_constant = SPVM_OP_new_op_constant_int(compiler, compiler->current_line, compiler->current_file, compiler->current_line);
yylvalp->opval = op_constant;
keyword_token = CONSTANT;
}
break
;
}
}
}
int32_t token;
if
(keyword_token > 0) {
token = keyword_token;
}
else
{
{
if
(
strstr
(symbol_name,
"__"
)) {
SPVM_COMPILER_error(compiler,
"The symbol name \"%s\" cannnot constain \"__\".\n at %s line %d"
, symbol_name, compiler->current_file, compiler->current_line);
}
if
(
strstr
(symbol_name,
"::::"
)) {
SPVM_COMPILER_error(compiler,
"The symbol name \"%s\" cannnot contains \"::::\".\n at %s line %d"
, symbol_name, compiler->current_file, compiler->current_line);
}
assert
(!(symbol_name[0] ==
':'
&& symbol_name[1] ==
':'
));
assert
(!SPVM_TOKE_isdigit_ascii(compiler, symbol_name[0]));
}
if
(next_is_fat_camma) {
if
(symbol_name_length >= 2 &&
strstr
(symbol_name,
"::"
)) {
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);
}
SPVM_OP* op_constant = SPVM_OP_new_op_constant_string(compiler, symbol_name, symbol_name_length, compiler->current_file, compiler->current_line);
yylvalp->opval = op_constant;
token = CONSTANT;
}
else
{
SPVM_OP* op_name = SPVM_OP_new_op_name(compiler, symbol_name, compiler->current_file, compiler->current_line);
yylvalp->opval = op_name;
token = SYMBOL_NAME;
}
}
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, symbol_name);
return
token;
}
else
{
SPVM_COMPILER_error(compiler,
"Use of the character code \"%X\" is not allowed in source code.\n at %s line %d"
, (uint8_t)ch, compiler->current_file, compiler->current_line);
return
0;
}
}
}
}
}
int32_t SPVM_TOKE_load_class_file(SPVM_COMPILER* compiler) {
compiler->current_file = NULL;
compiler->current_class_content = NULL;
compiler->current_tmp_vars_length = 0;
compiler->ch_ptr = NULL;
compiler->token_begin_ch_ptr = NULL;
compiler->line_begin_ch_ptr = NULL;
compiler->current_anon_op_types = SPVM_LIST_new_list_permanent(compiler->current_each_compile_allocator, 128);
SPVM_LIST* op_use_stack = compiler->op_use_stack;
while
(1) {
if
(op_use_stack->length == 0) {
return
0;
}
else
if
(op_use_stack->length > 0) {
SPVM_OP* op_use = SPVM_LIST_shift(op_use_stack);
const
char
* basic_type_name = op_use->uv.use->op_type->uv.type->unresolved_basic_type_name;
int32_t basic_type_name_length =
strlen
(basic_type_name);
int32_t is_class_generated_by_anon_method = !!
strstr
(basic_type_name,
"::anon_method::"
);
int32_t is_anon_class = !!
strstr
(basic_type_name,
"::anon_class::"
);
if
(!(is_class_generated_by_anon_method || is_anon_class)) {
if
(SPVM_TOKE_islower_ascii(compiler, basic_type_name[0])) {
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);
return
0;
}
int32_t module_part_name_is_invalid = 0;
int32_t basic_type_name_length =
strlen
(basic_type_name);
for
(int32_t i = 0; i < basic_type_name_length; i++) {
if
(i > 1) {
if
(basic_type_name[i - 2] ==
':'
&& basic_type_name[i - 1] ==
':'
) {
if
(SPVM_TOKE_islower_ascii(compiler, basic_type_name[i])) {
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);
return
0;
}
}
}
}
if
(
strstr
(basic_type_name,
"__"
)) {
SPVM_COMPILER_error(compiler,
"The class name \"%s\" cannnot constain \"__\".\n at %s line %d"
, basic_type_name, op_use->file, op_use->line);
return
0;
}
if
(basic_type_name_length >= 2 && basic_type_name[basic_type_name_length - 2] ==
':'
&& basic_type_name[basic_type_name_length - 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);
return
0;
}
if
(
strstr
(basic_type_name,
"::::"
)) {
SPVM_COMPILER_error(compiler,
"The class name \"%s\" cannnot contains \"::::\".\n at %s line %d"
, basic_type_name, op_use->file, op_use->line);
return
0;
}
if
(basic_type_name_length >= 2 && basic_type_name[0] ==
':'
&& basic_type_name[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);
return
0;
}
if
(basic_type_name_length >= 1 && SPVM_TOKE_isdigit_ascii(compiler, basic_type_name[0])) {
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);
return
0;
}
}
SPVM_BASIC_TYPE* basic_type = SPVM_HASH_get(compiler->basic_type_symtable, basic_type_name,
strlen
(basic_type_name));
if
(basic_type) {
continue
;
}
else
{
int32_t current_class_rel_file_length = (int32_t)(
strlen
(basic_type_name) + 6);
char
* current_class_rel_file = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->current_each_compile_allocator, current_class_rel_file_length + 1);
const
char
* ch_ptr_orig = basic_type_name;
char
* ch_ptr_to = current_class_rel_file;
while
(*ch_ptr_orig) {
if
(*ch_ptr_orig ==
':'
&& *(ch_ptr_orig + 1) ==
':'
) {
*ch_ptr_to =
'/'
;
ch_ptr_orig += 2;
ch_ptr_to++;
}
else
{
*ch_ptr_to = *ch_ptr_orig;
ch_ptr_orig++;
ch_ptr_to++;
}
}
strncpy
(ch_ptr_to,
".spvm"
, 5);
ch_ptr_to += 5;
*ch_ptr_to =
'\0'
;
char
* current_file = NULL;
SPVM_CLASS_FILE* class_file = SPVM_COMPILER_get_class_file(compiler, basic_type_name);
const
char
* include_dir = NULL;
if
(!class_file) {
FILE
* fh = NULL;
int32_t include_dirs_length = SPVM_COMPILER_get_include_dirs_length(compiler);
for
(int32_t i = 0; i < include_dirs_length; i++) {
include_dir = SPVM_COMPILER_get_include_dir(compiler, i);
int32_t file_name_length = (int32_t)(
strlen
(include_dir) + 1 +
strlen
(current_class_rel_file));
current_file = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->current_each_compile_allocator, file_name_length + 1);
sprintf
(current_file,
"%s/%s"
, include_dir, current_class_rel_file);
current_file[file_name_length] =
'\0'
;
for
(int32_t i = 0; i < file_name_length; i++) {
if
(current_file[i] ==
'\\'
) {
current_file[i] =
'/'
;
}
}
fh =
fopen
(current_file,
"rb"
);
if
(fh) {
break
;
}
errno
= 0;
}
if
(!fh) {
if
(!op_use->uv.use->is_require) {
int32_t include_dirs_str_length = 0;
for
(int32_t i = 0; i < include_dirs_length; i++) {
const
char
* include_dir = SPVM_COMPILER_get_include_dir(compiler, i);
include_dirs_str_length += 1 +
strlen
(include_dir);
}
char
* include_dirs_str = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->current_each_compile_allocator, include_dirs_str_length + 1);
int32_t include_dirs_str_offset = 0;
for
(int32_t i = 0; i < include_dirs_length; i++) {
const
char
* include_dir = SPVM_COMPILER_get_include_dir(compiler, i);
sprintf
(include_dirs_str + include_dirs_str_offset,
"%s"
, include_dir);
include_dirs_str_offset +=
strlen
(include_dir);
if
(i != include_dirs_length - 1) {
include_dirs_str[include_dirs_str_offset] =
' '
;
include_dirs_str_offset++;
}
}
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);
return
0;
}
}
else
{
fseek
(fh, 0, SEEK_END);
int32_t source_length = (int32_t)
ftell
(fh);
if
(source_length < 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);
return
0;
}
fseek
(fh, 0, SEEK_SET);
char
* source = SPVM_ALLOCATOR_alloc_memory_block_permanent(compiler->current_each_compile_allocator, source_length + 1);
int32_t read_error = 0;
if
((int32_t)
fread
(source, 1, source_length, fh) < source_length) {
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);
SPVM_ALLOCATOR_free_memory_block_tmp(compiler->current_each_compile_allocator, source);
read_error = 1;
}
if
(!read_error) {
fclose
(fh);
source[source_length] =
'\0'
;
int32_t content_length =
strlen
(source);
SPVM_CLASS_FILE* found_class_file = SPVM_COMPILER_get_class_file(compiler, basic_type_name);
if
(!found_class_file) {
SPVM_COMPILER_add_class_file(compiler, basic_type_name);
SPVM_CLASS_FILE* class_file = SPVM_COMPILER_get_class_file(compiler, basic_type_name);
SPVM_CLASS_FILE_set_file(compiler, class_file, current_file);
SPVM_CLASS_FILE_set_rel_file(compiler, class_file, current_class_rel_file);
SPVM_CLASS_FILE_set_dir(compiler, class_file, include_dir);
SPVM_CLASS_FILE_set_content(compiler, class_file, source);
SPVM_CLASS_FILE_set_content_length(compiler, class_file, content_length);
}
}
}
}
class_file = SPVM_COMPILER_get_class_file(compiler, basic_type_name);
if
(class_file) {
if
(!class_file->content) {
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);
return
0;
}
compiler->current_class_content = (
char
*)class_file->content;
if
(!(class_file->content_length >= 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);
return
0;
}
compiler->current_class_content_length = class_file->content_length;
compiler->current_class_dir = class_file->dir;
if
(!class_file->rel_file) {
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);
return
0;
}
compiler->current_class_rel_file = class_file->rel_file;
compiler->current_outmost_class_name = class_file->class_name;
if
(class_file->file) {
compiler->current_file = class_file->file;
}
else
{
compiler->current_file = class_file->rel_file;
}
int32_t content_length = class_file->content_length;
for
(int32_t i = 0; i < content_length; i++) {
char
ch = compiler->current_class_content[i];
}
int32_t content_offset = 0;
while
(content_offset < class_file->content_length) {
int32_t dst;
const
char
* current_ch = compiler->current_class_content + content_offset;
int32_t utf8_char_len = (int32_t)SPVM_UTF8_iterate((
const
uint8_t*)(compiler->current_class_content + content_offset), class_file->content_length, &dst);
if
(!(utf8_char_len > 0)) {
SPVM_COMPILER_error(compiler,
"The charactor encoding of SPVM source codes must be UTF-8. The source code of the \"%s\" class in the \"%s\" file contains non-UTF8 characters.\n at %s line %d"
, basic_type_name, compiler->current_file, op_use->file, op_use->line);
return
0;
}
if
(utf8_char_len == 1) {
if
(!(SPVM_TOKE_isprint_ascii(compiler, *current_ch) || SPVM_TOKE_isspace_ascii(compiler, *current_ch))) {
SPVM_COMPILER_error(compiler,
"If a character in an SPVM source code is ASCII, it must be ASCII printable or space. The source code of the \"%s\" class in the \"%s\" file contains it.\n at %s line %d"
, basic_type_name, compiler->current_file, op_use->file, op_use->line);
return
0;
}
if
(*current_ch ==
'\r'
) {
SPVM_COMPILER_error(compiler,
"The new line of SPVM source codes must be LF. The source code cannot contains CR and CRLF. The source code of the \"%s\" class in the \"%s\" file contains it.\n at %s line %d"
, basic_type_name, compiler->current_file, op_use->file, op_use->line);
return
0;
}
}
content_offset += utf8_char_len;
}
compiler->token_begin_ch_ptr = compiler->current_class_content;
compiler->ch_ptr = compiler->token_begin_ch_ptr;
compiler->line_begin_ch_ptr = compiler->token_begin_ch_ptr;
compiler->current_line = 1;
}
else
{
if
(op_use->uv.use->is_require) {
SPVM_HASH_set(compiler->if_require_not_found_basic_type_name_symtable, basic_type_name,
strlen
(basic_type_name), (
void
*)basic_type_name);
continue
;
}
}
break
;
}
}
else
{
assert
(0);
}
}
if
(!(compiler->error_messages->length == 0)) {
return
0;
}
return
1;
}
SPVM_OP* SPVM_TOKE_new_op(SPVM_COMPILER* compiler, int32_t type) {
SPVM_OP* op = SPVM_OP_new_op(compiler, type, compiler->current_file, compiler->current_line);
return
op;
}
SPVM_OP* SPVM_TOKE_new_op_with_column(SPVM_COMPILER* compiler, int32_t type, int32_t column) {
SPVM_OP* op = SPVM_OP_new_op(compiler, type, compiler->current_file, compiler->current_line);
op->column = column;
return
op;
}
int32_t SPVM_TOKE_is_white_space(SPVM_COMPILER* compiler,
char
ch) {
(
void
)compiler;
if
(ch == 0x20 || ch == 0x0D || ch == 0x0A || ch == 0x09 || ch == 0x0C) {
return
1;
}
else
{
return
0;
}
}
int32_t SPVM_TOKE_is_octal_number(SPVM_COMPILER* compiler,
char
ch) {
(
void
)compiler;
if
(ch >=
'0'
&& ch <=
'7'
) {
return
1;
}
else
{
return
0;
}
}
int32_t SPVM_TOKE_is_hex_number(SPVM_COMPILER* compiler,
char
ch) {
(
void
)compiler;
if
(SPVM_TOKE_isdigit_ascii(compiler, ch) || (ch >=
'a'
&& ch <=
'f'
) || (ch >=
'A'
&& ch <=
'F'
)) {
return
1;
}
else
{
return
0;
}
}
char
SPVM_TOKE_parse_octal_escape(SPVM_COMPILER* compiler,
char
** ch_ptr_ptr) {
char
ch = -1;
char
* ch_ptr = *ch_ptr_ptr;
int32_t is_o_escape_character = 0;
int32_t has_brace = 0;
if
(*ch_ptr ==
'o'
) {
is_o_escape_character = 1;
ch_ptr++;
if
(*ch_ptr ==
'{'
) {
has_brace = 1;
ch_ptr++;
if
(!SPVM_TOKE_is_octal_number(compiler, *ch_ptr)) {
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);
return
ch;
}
}
else
{
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);
return
ch;
}
}
char
octal_escape_char[4] = {0};
int32_t octal_escape_char_index = 0;
while
(SPVM_TOKE_is_octal_number(compiler, *ch_ptr)) {
if
(octal_escape_char_index >= 3) {
break
;
}
octal_escape_char[octal_escape_char_index] = *ch_ptr;
ch_ptr++;
octal_escape_char_index++;
}
if
(
strlen
(octal_escape_char) > 0) {
char
* end;
int32_t number =
strtol
(octal_escape_char, &end, 8);
if
(number > 255) {
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);
return
ch;
}
ch = (
char
)number;
}
if
(has_brace) {
if
(*ch_ptr ==
'}'
) {
ch_ptr++;
}
else
{
SPVM_COMPILER_error(compiler,
"The octal escape character is not closed by \"}\".\n at %s line %d"
, compiler->current_file, compiler->current_line);
}
}
*ch_ptr_ptr = ch_ptr;
return
ch;
}
char
SPVM_TOKE_parse_hex_escape(SPVM_COMPILER* compiler,
char
** ch_ptr_ptr) {
char
ch;
char
* ch_ptr = *ch_ptr_ptr;
ch_ptr++;
int32_t has_brace = 0;
if
(*ch_ptr ==
'{'
) {
has_brace = 1;
ch_ptr++;
}
char
hex_escape_char[9] = {0};
int32_t hex_escape_char_index = 0;
while
(SPVM_TOKE_is_hex_number(compiler, *ch_ptr)) {
if
(hex_escape_char_index >= 2) {
break
;
}
hex_escape_char[hex_escape_char_index] = *ch_ptr;
ch_ptr++;
hex_escape_char_index++;
}
if
(
strlen
(hex_escape_char) > 0) {
char
* end;
ch = (
char
)
strtol
(hex_escape_char, &end, 16);
}
else
{
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);
}
if
(has_brace) {
if
(*ch_ptr ==
'}'
) {
ch_ptr++;
}
else
{
SPVM_COMPILER_error(compiler,
"The hexadecimal escape character is not closed by \"}\".\n at %s line %d"
, compiler->current_file, compiler->current_line);
}
}
*ch_ptr_ptr = ch_ptr;
return
ch;
}
int32_t SPVM_TOKE_is_line_terminator(SPVM_COMPILER* compiler,
char
* ch) {
int32_t is_line_terminator = 0;
if
(*ch ==
'\n'
) {
is_line_terminator = 1;
}
return
is_line_terminator;
}
int32_t SPVM_TOKE_isalpha_ascii(SPVM_COMPILER* compiler, int32_t ch) {
int32_t isalpha_ascii = 0;
if
(isascii(ch) &&
isalpha
(ch)) {
isalpha_ascii = 1;
}
return
isalpha_ascii;
}
int32_t SPVM_TOKE_isalnum_ascii(SPVM_COMPILER* compiler, int32_t ch) {
int32_t isalnum_ascii = 0;
if
(isascii(ch) &&
isalnum
(ch)) {
isalnum_ascii = 1;
}
return
isalnum_ascii;
}
int32_t SPVM_TOKE_isspace_ascii(SPVM_COMPILER* compiler, int32_t ch) {
int32_t isalpha_ascii = 0;
if
(isascii(ch) &&
isspace
(ch)) {
isalpha_ascii = 1;
}
return
isalpha_ascii;
}
int32_t SPVM_TOKE_isdigit_ascii(SPVM_COMPILER* compiler, int32_t ch) {
int32_t isdigit_ascii = 0;
if
(isascii(ch) &&
isdigit
(ch)) {
isdigit_ascii = 1;
}
return
isdigit_ascii;
}
int32_t SPVM_TOKE_islower_ascii(SPVM_COMPILER* compiler, int32_t ch) {
int32_t islower_ascii = 0;
if
(isascii(ch) &&
islower
(ch)) {
islower_ascii = 1;
}
return
islower_ascii;
}
int32_t SPVM_TOKE_isprint_ascii(SPVM_COMPILER* compiler, int32_t ch) {
int32_t islower_ascii = 0;
if
(isascii(ch) && isprint(ch)) {
islower_ascii = 1;
}
return
islower_ascii;
}
int32_t SPVM_TOKE_parse_line_terminator(SPVM_COMPILER* compiler,
char
** ch_ptr_ptr) {
int32_t is_line_terminator = 0;
if
(**ch_ptr_ptr ==
'\n'
) {
is_line_terminator = 1;
(*ch_ptr_ptr)++;
}
else
{
assert
(0);
}
return
is_line_terminator;
}
void
SPVM_TOKE_increment_current_line(SPVM_COMPILER* compiler) {
compiler->current_line++;
compiler->line_begin_ch_ptr = compiler->ch_ptr;
}