diff --git a/.gitignore b/.gitignore index bd1636c..32e0e1f 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,5 @@ y.tab.h y.tab.c lex.yy.c bin/* + +.vscode/* diff --git a/Makefile b/Makefile index 738306c..0b4a878 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -output: main.o lex.o grammar.o create.o string.o compiler.o codegen.o opcode.o +output: main.o lex.o grammar.o create.o string.o compiler.o codegen.o opcode.o error.o debug.o wchar.o $(CC) -o bin/main $^ main.o : main/main.c $(CC) -c main/main.c @@ -18,6 +18,12 @@ lex.o : compiler/lex.l grammar.o $(CC) -c lex.yy.c -o lex.o string.o : compiler/string.c $(CC) -c $< -o string.o +wchar.o: share/wchar.c + $(CC) -c $< -o wchar.o +error.o: compiler/error.c + $(CC) -c $< -o error.o +debug.o: debug/debug.c + $(CC) -c $< -o debug.o clean: rm -f y.tab.* diff --git a/compiler/compiler.c b/compiler/compiler.c index 58dd67f..e8c7dd1 100644 --- a/compiler/compiler.c +++ b/compiler/compiler.c @@ -6,7 +6,13 @@ static Compiler *st_current_compiler; Compiler *create_compiler() { Compiler *compiler = (Compiler *)malloc(sizeof(Compiler)); - compiler->func_definition_list = (FuncDefinition *)malloc(sizeof(FuncDefinition)); + compiler->svm_constant_count = 0; + compiler->svm_constant = NULL; + compiler->function_count = 0; + compiler->func_definition_list = NULL; + compiler->current_block = NULL; + compiler->declaration_list = NULL; + compiler->current_line_number = 0; return compiler; } diff --git a/compiler/create.c b/compiler/create.c index 18197b3..26d5e46 100644 --- a/compiler/create.c +++ b/compiler/create.c @@ -51,6 +51,14 @@ Expression *alloc_unary_expression(ExpressionKind kind, Expression *unaryExpr) return expr; } +Expression *alloc_type_cast_expression(TypeSpecifier *type, Expression *unaryExpr) +{ + Expression *expr = alloc_expression(TYPE_CAST_EXPRESSION); + expr->u.unary_expression = unaryExpr; + expr->type = type; + return expr; +} + Expression *alloc_binary_expression(ExpressionKind kind, Expression *left, Expression *right) { Expression *expr = alloc_expression(kind); diff --git a/compiler/error.c b/compiler/error.c new file mode 100644 index 0000000..d87e573 --- /dev/null +++ b/compiler/error.c @@ -0,0 +1,339 @@ +#include +#include +#include +#include +#include +#include "error.h" +#include "summoner.h" +#include "../include/DBG.h" +#include "../include/share.h" + +#define LINE_BUF_SIZE (1024) + +extern char *yytext; +static ErrorDefinition dkc_error_message_format[] = { + {"dummy"}, + {"在($(token))附近发生语法错误"}, + {"不正确的字符($(bad_char))"}, + {"函数名重复($(name))"}, + {"不正确的多字节字符。"}, + {"预期外的宽字符串。"}, + {"数组元素不能标识为final。"}, + {"复合赋值运算符不能用于final值"}, + {"函数的参数名重复($(name))。"}, + {"变量名$(name)重复。"}, + {"找不到变量或函数$(name)。"}, + {"$(name)是函数名,但没有函数调用的()。"}, + {"不能强制转型为派生类型。"}, + {"不能将$(src)转型为$(dest)。"}, + {"算数运算符的操作数类型不正确。"}, + {"比较运算符的操作数类型不正确。"}, + {"逻辑and/or运算符的操作数类型不正确。"}, + {"减法运算符的操作数类型不正确。"}, + {"逻辑非运算符的操作数类型不正确。"}, + {"自增/自减运算符的操作数类型不正确。"}, + {"函数调用运算符的操作数不是函数名。"}, + {"找不到函数$(name)。"}, + {"函数的参数数量错误。"}, + {"赋值运算符的左边不是一个左边值。"}, + {"标签$(label)不存在。"}, + {"数组字面量必须至少有一个元素"}, + {"下标运算符[]的左边不是数组类型"}, + {"数组的下标不是int。"}, + {"数组的大小不是int。"}, + {"整数值不能被0除。"}, + {"package名称过长"}, + {"被require的文件不存在($(file))"}, + {"require时发生错误($(status))。"}, + {"同一个源文件中重复require了同一个包。"}, + {"rename后的名称必须指定package。"}, + {"重复声明了abstract。"}, + {"重复声明了访问修饰符。"}, + {"重复声明了override。"}, + {"重复声明了virtual。"}, + {"该类型不能使用成员运算符。"}, + {"在类型$(class_name)中不存在成员$(member_name)。"}, + {"成员$(member_name)是private的,不能访问。"}, + {"没有实现abstract方法。"}, + {"必须实现非abstract方法。"}, + {"不能继承多个类。"}, + {"Diksam中不能继承非abstract的类" + "(类$(name)不是abstract类)。"}, + {"不能对abstract类($(name))使用new。"}, + {"void类型的函数不能有返回值。"}, + {"没有找到类$(name)。"}, + {"成员$(member_name)被声明为构造方法。并不是方法。"}, + {"用来new的方法$(member_name)并不是构造方法。"}, + {"不能调用字段$(member_name)"}, + {"尝试为方法$(member_name)赋值。"}, + {"不能覆盖非virtual方法$(name)。"}, + {"覆盖方法时必须使用override关键字($(name))。"}, + {"在abstract类中,存在非abstract方法$(method_name)。"}, + {"在没有超类的类中使用了super。"}, + {"方法调用以外不能使用super。"}, + {"不能引用super的字段。"}, + {"$(name)是字段,不能覆盖。"}, + {"重复的字段名$(name)。"}, + {"数组中没有$(name)方法。"}, + {"数组中没有$(name)方法。"}, + {"instanceof的操作数必须是引用类型。"}, + {"instanceof的右边的类型必须是引用类型。"}, + {"instanceof的目标必须是类。"}, + {"instanceof语句一直为真。"}, + {"instanceof语句一直为假。"}, + {"因为Diksam的接口间没有父子关系" + "instanceof语句一直为假。"}, + {"向下转型的源类型必须是类。"}, + {"向下转型的目标类型必须是类。"}, + {"不需要进行向下转型。"}, + {"尝试将父类转换为子类。"}, + {"尝试转换没有继承关系的类。"}, + {"因为Diksam的接口间没有父子关系" + "不能向下转型。"}, + {"不能catch类以外的类型。"}, + {"catch到的类$(class_name)不是Exception的子类。"}, + {"不能throw类以外的类型。"}, + {"throw的类$(class_name)不是Exception的子类。"}, + {"catch之外不能出现没有操作数的throw。"}, + {"$(statement_name)语句不能卸载finally块中。"}, + {"找不到throws中声明的$(name)。"}, + {"throws中声明的$(name)不是Exception的子类。"}, + {"在throws块中声明的异常$(name),必须在内部catch。"}, + {"不能require文件本身。"}, + {"if语句的条件表达式不是boolean型。"}, + {"while语句的条件表达式不是boolean型。"}, + {"for语句的条件表达式不是boolean型。"}, + {"do while语句的条件表达式不是boolean型。"}, + {"case块的表达式的类型不一致"}, + {"$(name)为final变量。不能赋值。"}, + {"$(name)为final字段。不能赋值。"}, + {"final变量$(name)没有初始化。"}, + {"被覆盖的方法$(name)的访问修饰符必须比超类的更严格。"}, + {"方法或函数$(name)的参数数量错误。"}, + {"方法或函数$(func_name)的第$(index)个参数" + "$(param_name)的类型错误。"}, + {"方法或函数$(name)的返回值类型错误。"}, + {"方法或函数$(func_name)描述的throws中含有不恰当的异常$(exception_name)。"}, + {"不能直接调用构造方法。"}, + {"找不到类型名$(name)。"}, + {"枚举类型$(type_name)中没有$(enumerator_name)。"}, + {"Diksam的接口之间不能继承(至今为止)。"}, + {"不能从包外访问成员$(member_name)。"}, + {"不能从包外访问类$(class_name)。"}, + {"不能在类外使用this。"}, + {"不能在类外使用super。"}, + {"~运算符的操作数必须是int。"}, + {"双目bite运算符的操作数必须是int或者boolean。"}, + {"在C样式的注释中终止了文件。"}, + {"在字符串字面量中终止了文件。"}, + {"字符字面量中包含了2个以上的字符。"}, + {"dummy"} +}; + +typedef struct +{ + MessageArgumentType type; + char *name; + union + { + int int_val; + double double_val; + char *string_val; + void *pointer_val; + int character_val; + } u; +} MessageArgument; + +static void +create_message_argument(MessageArgument *arg, va_list ap) +{ + int index = 0; + MessageArgumentType type; + + while ((type = va_arg(ap, MessageArgumentType)) != MESSAGE_ARGUMENT_END) + { + arg[index].type = type; + arg[index].name = va_arg(ap, char *); + switch (type) + { + case INT_MESSAGE_ARGUMENT: + arg[index].u.int_val = va_arg(ap, int); + break; + case DOUBLE_MESSAGE_ARGUMENT: + arg[index].u.double_val = va_arg(ap, double); + break; + case STRING_MESSAGE_ARGUMENT: + arg[index].u.string_val = va_arg(ap, char *); + break; + case POINTER_MESSAGE_ARGUMENT: + arg[index].u.pointer_val = va_arg(ap, void *); + break; + case CHARACTER_MESSAGE_ARGUMENT: + arg[index].u.character_val = va_arg(ap, int); + break; + case MESSAGE_ARGUMENT_END: + assert(0); + break; + default: + assert(0); + } + index++; + assert(index < MESSAGE_ARGUMENT_MAX); + } +} + +static void +search_argument(MessageArgument *arg_list, + char *arg_name, MessageArgument *arg) +{ + int i; + + for (i = 0; arg_list[i].type != MESSAGE_ARGUMENT_END; i++) + { + if (!strcmp(arg_list[i].name, arg_name)) + { + *arg = arg_list[i]; + return; + } + } + assert(0); +} + +wchar_t * +mbstowcs_alloc(int line_number, const char *src) +{ + int len; + wchar_t *ret; + + len = dvm_mbstowcs_len(src); + if (len < 0) + { + return NULL; + compile_error(line_number, + BAD_MULTIBYTE_CHARACTER_ERR, + MESSAGE_ARGUMENT_END); + } + ret = malloc(sizeof(wchar_t) * (len + 1)); + dvm_mbstowcs(src, ret); + + return ret; +} + +static void +format_message(int line_number, ErrorDefinition *format, VWString *v, + va_list ap) +{ + int i; + char buf[LINE_BUF_SIZE]; + wchar_t wc_buf[LINE_BUF_SIZE]; + int arg_name_index; + char arg_name[LINE_BUF_SIZE]; + MessageArgument arg[MESSAGE_ARGUMENT_MAX]; + MessageArgument cur_arg; + wchar_t *wc_format; + + create_message_argument(arg, ap); + + wc_format = mbstowcs_alloc(line_number, format->format); + DBG_assert(wc_format != NULL, ("wc_format is null.\n")); + + for (i = 0; wc_format[i] != L'\0'; i++) + { + if (wc_format[i] != L'$') + { + dkc_vwstr_append_character(v, wc_format[i]); + continue; + } + assert(wc_format[i + 1] == L'('); + i += 2; + for (arg_name_index = 0; wc_format[i] != L')'; + arg_name_index++, i++) + { + arg_name[arg_name_index] = dvm_wctochar(wc_format[i]); + } + arg_name[arg_name_index] = '\0'; + assert(wc_format[i] == L')'); + + search_argument(arg, arg_name, &cur_arg); + switch (cur_arg.type) + { + case INT_MESSAGE_ARGUMENT: + sprintf(buf, "%d", cur_arg.u.int_val); + dvm_mbstowcs(buf, wc_buf); + dkc_vwstr_append_string(v, wc_buf); + break; + case DOUBLE_MESSAGE_ARGUMENT: + sprintf(buf, "%f", cur_arg.u.double_val); + dvm_mbstowcs(buf, wc_buf); + dkc_vwstr_append_string(v, wc_buf); + break; + case STRING_MESSAGE_ARGUMENT: + dvm_mbstowcs(cur_arg.u.string_val, wc_buf); + dkc_vwstr_append_string(v, wc_buf); + break; + case POINTER_MESSAGE_ARGUMENT: + sprintf(buf, "%p", cur_arg.u.pointer_val); + dvm_mbstowcs(buf, wc_buf); + dkc_vwstr_append_string(v, wc_buf); + break; + case CHARACTER_MESSAGE_ARGUMENT: + sprintf(buf, "%c", cur_arg.u.character_val); + dvm_mbstowcs(buf, wc_buf); + dkc_vwstr_append_string(v, wc_buf); + break; + case MESSAGE_ARGUMENT_END: + assert(0); + break; + default: + assert(0); + } + } + free(wc_format); +} + +static void +self_check() +{ + if (strcmp(dkc_error_message_format[0].format, "dummy") != 0) + { + DBG_panic(("compile error message format error.\n")); + } + if (strcmp(dkc_error_message_format + [COMPILE_ERROR_COUNT_PLUS_1] + .format, + "dummy") != 0) + { + DBG_panic(("compile error message format error. " + "COMPILE_ERROR_COUNT_PLUS_1..%d\n", + COMPILE_ERROR_COUNT_PLUS_1)); + } +} + +void compile_error(int line_number, CompileError id, ...) +{ + va_list ap; + VWString message; + + self_check(); + va_start(ap, id); + + message.string = NULL; + format_message(line_number, + &dkc_error_message_format[id], + &message, ap); + fprintf(stderr, "%3d:", line_number); + dvm_print_wcs_ln(stderr, message.string); + va_end(ap); + + exit(1); +} + +int yyerror(char const *str) +{ + compile_error(get_current_compiler()->current_line_number, + PARSE_ERR, + STRING_MESSAGE_ARGUMENT, "token", yytext, + MESSAGE_ARGUMENT_END); + + return 0; +} diff --git a/compiler/error.h b/compiler/error.h new file mode 100644 index 0000000..dc06b55 --- /dev/null +++ b/compiler/error.h @@ -0,0 +1,138 @@ +#ifndef _ERROR_H_ +#define _ERROR_H_ + +#define MESSAGE_ARGUMENT_MAX (256) + +typedef enum +{ + INT_MESSAGE_ARGUMENT = 1, + DOUBLE_MESSAGE_ARGUMENT, + STRING_MESSAGE_ARGUMENT, + CHARACTER_MESSAGE_ARGUMENT, + POINTER_MESSAGE_ARGUMENT, + MESSAGE_ARGUMENT_END +} MessageArgumentType; + +typedef struct +{ + char *format; +} ErrorDefinition; + +typedef enum +{ + PARSE_ERR = 1, + CHARACTER_INVALID_ERR, + FUNCTION_MULTIPLE_DEFINE_ERR, + BAD_MULTIBYTE_CHARACTER_ERR, + UNEXPECTED_WIDE_STRING_IN_COMPILE_ERR, + ARRAY_ELEMENT_CAN_NOT_BE_FINAL_ERR, + COMPLEX_ASSIGNMENT_OPERATOR_TO_FINAL_ERR, + PARAMETER_MULTIPLE_DEFINE_ERR, + VARIABLE_MULTIPLE_DEFINE_ERR, + IDENTIFIER_NOT_FOUND_ERR, + FUNCTION_IDENTIFIER_ERR, + DERIVE_TYPE_CAST_ERR, + CAST_MISMATCH_ERR, + MATH_TYPE_MISMATCH_ERR, + COMPARE_TYPE_MISMATCH_ERR, + LOGICAL_TYPE_MISMATCH_ERR, + MINUS_TYPE_MISMATCH_ERR, + LOGICAL_NOT_TYPE_MISMATCH_ERR, + INC_DEC_TYPE_MISMATCH_ERR, + FUNCTION_NOT_IDENTIFIER_ERR, /* BUGBUG not used */ + FUNCTION_NOT_FOUND_ERR, + ARGUMENT_COUNT_MISMATCH_ERR, + NOT_LVALUE_ERR, + LABEL_NOT_FOUND_ERR, + ARRAY_LITERAL_EMPTY_ERR, + INDEX_LEFT_OPERAND_NOT_ARRAY_ERR, + INDEX_NOT_INT_ERR, + ARRAY_SIZE_NOT_INT_ERR, + DIVISION_BY_ZERO_IN_COMPILE_ERR, + PACKAGE_NAME_TOO_LONG_ERR, + REQUIRE_FILE_NOT_FOUND_ERR, + REQUIRE_FILE_ERR, + REQUIRE_DUPLICATE_ERR, + RENAME_HAS_NO_PACKAGED_NAME_ERR, + ABSTRACT_MULTIPLE_SPECIFIED_ERR, + ACCESS_MODIFIER_MULTIPLE_SPECIFIED_ERR, + OVERRIDE_MODIFIER_MULTIPLE_SPECIFIED_ERR, + VIRTUAL_MODIFIER_MULTIPLE_SPECIFIED_ERR, + MEMBER_EXPRESSION_TYPE_ERR, + MEMBER_NOT_FOUND_ERR, + PRIVATE_MEMBER_ACCESS_ERR, + ABSTRACT_METHOD_HAS_BODY_ERR, + CONCRETE_METHOD_HAS_NO_BODY_ERR, + MULTIPLE_INHERITANCE_ERR, + INHERIT_CONCRETE_CLASS_ERR, + NEW_ABSTRACT_CLASS_ERR, + RETURN_IN_VOID_FUNCTION_ERR, + CLASS_NOT_FOUND_ERR, + CONSTRUCTOR_IS_FIELD_ERR, + NOT_CONSTRUCTOR_ERR, + FIELD_CAN_NOT_CALL_ERR, + ASSIGN_TO_METHOD_ERR, + NON_VIRTUAL_METHOD_OVERRIDED_ERR, + NEED_OVERRIDE_ERR, + ABSTRACT_METHOD_IN_CONCRETE_CLASS_ERR, + HASNT_SUPER_CLASS_ERR, + SUPER_NOT_IN_MEMBER_EXPRESSION_ERR, + FIELD_OF_SUPER_REFERENCED_ERR, + FIELD_OVERRIDED_ERR, + FIELD_NAME_DUPLICATE_ERR, + ARRAY_METHOD_NOT_FOUND_ERR, + STRING_METHOD_NOT_FOUND_ERR, + INSTANCEOF_OPERAND_NOT_REFERENCE_ERR, + INSTANCEOF_TYPE_NOT_REFERENCE_ERR, + INSTANCEOF_FOR_NOT_CLASS_ERR, + INSTANCEOF_MUST_RETURN_TRUE_ERR, + INSTANCEOF_MUST_RETURN_FALSE_ERR, + INSTANCEOF_INTERFACE_ERR, + DOWN_CAST_OPERAND_IS_NOT_CLASS_ERR, + DOWN_CAST_TARGET_IS_NOT_CLASS_ERR, + DOWN_CAST_DO_NOTHING_ERR, + DOWN_CAST_TO_SUPER_CLASS_ERR, + DOWN_CAST_TO_BAD_CLASS_ERR, + DOWN_CAST_INTERFACE_ERR, + CATCH_TYPE_IS_NOT_CLASS_ERR, + CATCH_TYPE_IS_NOT_EXCEPTION_ERR, + THROW_TYPE_IS_NOT_CLASS_ERR, + THROW_TYPE_IS_NOT_EXCEPTION_ERR, + RETHROW_OUT_OF_CATCH_ERR, + GOTO_STATEMENT_IN_FINALLY_ERR, + THROWS_TYPE_NOT_FOUND_ERR, + THROWS_TYPE_IS_NOT_EXCEPTION_ERR, + EXCEPTION_HAS_TO_BE_THROWN_ERR, + REQUIRE_ITSELF_ERR, + IF_CONDITION_NOT_BOOLEAN_ERR, + WHILE_CONDITION_NOT_BOOLEAN_ERR, + FOR_CONDITION_NOT_BOOLEAN_ERR, + DO_WHILE_CONDITION_NOT_BOOLEAN_ERR, + CASE_TYPE_MISMATCH_ERR, + FINAL_VARIABLE_ASSIGNMENT_ERR, + FINAL_FIELD_ASSIGNMENT_ERR, + FINAL_VARIABLE_WITHOUT_INITIALIZER_ERR, + OVERRIDE_METHOD_ACCESSIBILITY_ERR, + BAD_PARAMETER_COUNT_ERR, + BAD_PARAMETER_TYPE_ERR, + BAD_RETURN_TYPE_ERR, + BAD_EXCEPTION_ERR, + CONSTRUCTOR_CALLED_ERR, + TYPE_NAME_NOT_FOUND_ERR, + ENUMERATOR_NOT_FOUND_ERR, + INTERFACE_INHERIT_ERR, + PACKAGE_MEMBER_ACCESS_ERR, + PACKAGE_CLASS_ACCESS_ERR, + THIS_OUT_OF_CLASS_ERR, + SUPER_OUT_OF_CLASS_ERR, + BIT_NOT_TYPE_MISMATCH_ERR, + BIT_BINARY_OPERATOR_TYPE_MISMATCH_ERR, + EOF_IN_C_COMMENT_ERR, + EOF_IN_STRING_LITERAL_ERR, + TOO_LONG_CHARACTER_LITERAL_ERR, + COMPILE_ERROR_COUNT_PLUS_1, +} CompileError; + +void compile_error(int line_number, CompileError id, ...); + +#endif diff --git a/compiler/grammar.y b/compiler/grammar.y index d95f683..ace9e13 100644 --- a/compiler/grammar.y +++ b/compiler/grammar.y @@ -187,13 +187,14 @@ block: expr: literal - | IDENTIFIER { $$ = alloc_identifier_expression($1); } - | expr '+' expr { $$ = alloc_binary_expression(ADD_EXPRESSION, $1, $3); } - | expr '-' expr { $$ = alloc_binary_expression(SUB_EXPRESSION, $1, $3); } - | expr '*' expr { $$ = alloc_binary_expression(MUL_EXPRESSION, $1, $3); } - | expr '/' expr { $$ = alloc_binary_expression(DIV_EXPRESSION, $1, $3); } - | '-' expr %prec MINUS { $$ = alloc_unary_expression(MINUS_EXPRESSION, $2); } - | '(' expr ')' { $$ = $2; } + | IDENTIFIER { $$ = alloc_identifier_expression($1); } + | expr '+' expr { $$ = alloc_binary_expression(ADD_EXPRESSION, $1, $3); } + | expr '-' expr { $$ = alloc_binary_expression(SUB_EXPRESSION, $1, $3); } + | expr '*' expr { $$ = alloc_binary_expression(MUL_EXPRESSION, $1, $3); } + | expr '/' expr { $$ = alloc_binary_expression(DIV_EXPRESSION, $1, $3); } + | '-' expr %prec MINUS { $$ = alloc_unary_expression(MINUS_EXPRESSION, $2); } + | '(' expr ')' { $$ = $2; } + | type_specifier '(' expr ')' { $$ = alloc_type_cast_expression($1, $3); } | bool_expr | func_call_expr ; @@ -236,9 +237,3 @@ new_line: | new_line '\n' %% - -int yyerror(char const *str) { - extern char *yytext; - fprintf(stderr, "parse error near %s\n", yytext); - return 0; -} diff --git a/compiler/summoner.h b/compiler/summoner.h index 3490d88..59bc1ec 100644 --- a/compiler/summoner.h +++ b/compiler/summoner.h @@ -17,6 +17,7 @@ typedef enum MUL_EXPRESSION, DIV_EXPRESSION, MINUS_EXPRESSION, + TYPE_CAST_EXPRESSION, MOD_EXPRESSION, /* % */ EQ_EXPRESSION, /* == */ NE_EXPRESSION, /* != */ @@ -67,7 +68,6 @@ typedef struct Expression struct Expression *unary_expression; struct FuncCallExpression *func_call_expression; } u; - } Expression; typedef struct BinaryExpression @@ -94,6 +94,7 @@ Expression *alloc_double_expression(double value); Expression *alloc_bool_expression(bool value); Expression *alloc_string_expression(char *value); Expression *alloc_identifier_expression(char *identifier); +Expression *alloc_type_cast_expression(TypeSpecifier *type, Expression *expr); Expression *alloc_unary_expression(ExpressionKind kind, Expression *unaryExpr); Expression *alloc_binary_expression(ExpressionKind kind, Expression *left, Expression *right); Expression *alloc_func_call_expression(char *identifier, ArgumentList *argument_list); @@ -308,6 +309,7 @@ typedef struct Compiler FuncDefinition *func_definition_list; Block *current_block; Declaration *declaration_list; + int current_line_number; } Compiler; Compiler *create_compiler(); @@ -335,4 +337,7 @@ void open_string_literal(void); void add_string_literal(int letter); char *close_string_literal(void); +/** fix_tree.c */ +void fix_tree(Compiler *compiler); + #endif diff --git a/debug/debug.c b/debug/debug.c new file mode 100644 index 0000000..1933b14 --- /dev/null +++ b/debug/debug.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include "debug.h" + +static DBG_Controller st_current_controller; +static char *st_current_file_name; +static int st_current_line; +static char *st_assert_expression; + +static struct DBG_Controller_tag st_default_controller = { + NULL, /*stderr,*/ + INT_MAX, +}; +DBG_Controller dbg_default_controller = &st_default_controller; + +DBG_Controller +DBG_create_controller_func(void) +{ + DBG_Controller controller; + + controller = malloc(sizeof(struct DBG_Controller_tag)); + controller->debug_write_fp = NULL; + controller->current_debug_level = INT_MAX; + + return controller; +} + +void +DBG_set_debug_level_func(DBG_Controller controller, int level) +{ + controller->current_debug_level = level; +} + +void +DBG_set_debug_write_fp_func(DBG_Controller controller, FILE *fp) +{ + controller->debug_write_fp = fp; +} + +static void +initialize_debug_write_fp(void) +{ + if (st_default_controller.debug_write_fp == NULL) { + st_default_controller.debug_write_fp = stderr; + } +} + +static void +assert_func(FILE *fp, char *file, int line, char *expression, + char *fmt, va_list ap) +{ + fprintf(fp, "Assertion failure (%s) file..%s line..%d\n", + expression, file, line); + if (fmt) { + vfprintf(fp, fmt, ap); + } +} + +void +DBG_assert_func(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + initialize_debug_write_fp(); + assert_func(st_current_controller->debug_write_fp, + st_current_file_name, st_current_line, + st_assert_expression, fmt, ap); + assert_func(stderr, + st_current_file_name, st_current_line, + st_assert_expression, fmt, ap); + va_end(ap); + abort(); +} + +static void +panic_func(FILE *fp, char *file, int line, char *fmt, va_list ap) +{ + fprintf(fp, "Panic!! file..%s line..%d\n", file, line); + if (fmt) { + vfprintf(fp, fmt, ap); + } +} + +void +DBG_panic_func(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + initialize_debug_write_fp(); + panic_func(st_current_controller->debug_write_fp, + st_current_file_name, st_current_line, fmt, ap); + panic_func(stderr, st_current_file_name, st_current_line, fmt, ap); + va_end(ap); + abort(); +} + +void +DBG_debug_write_func(int level, char *fmt, ...) +{ + va_list ap; + + if (level > 0 && level > st_current_controller->current_debug_level) { + return; + } + va_start(ap, fmt); + initialize_debug_write_fp(); + if (fmt) { + vfprintf(st_current_controller->debug_write_fp, fmt, ap); + } + va_end(ap); +} + +void +DBG_set(DBG_Controller controller, char *file, int line) +{ + st_current_controller = controller; + st_current_file_name = file; + st_current_line = line; +} + +void +DBG_set_expression(char *expression) +{ + st_assert_expression = expression; +} diff --git a/debug/debug.h b/debug/debug.h new file mode 100644 index 0000000..802046c --- /dev/null +++ b/debug/debug.h @@ -0,0 +1,12 @@ +#ifndef PRIVATE_DBG_H_INCLUDED +#define PRIVATE_DBG_H_INCLUDED +#include +#include "../include/DBG.h" + +struct DBG_Controller_tag +{ + FILE *debug_write_fp; + int current_debug_level; +}; + +#endif /* PRIVATE_DBG_H_INCLUDED */ diff --git a/include/DBG.h b/include/DBG.h new file mode 100644 index 0000000..314dbc0 --- /dev/null +++ b/include/DBG.h @@ -0,0 +1,52 @@ +#ifndef PUBLIC_DBG_H_INCLUDED +#define PUBLIC_DBG_H_INCLUDED +#include +#include + +typedef struct DBG_Controller_tag *DBG_Controller; +void DBG_set(DBG_Controller controller, char *file, int line); +void DBG_set_expression(char *expression); + +#ifdef DBG_NO_DEBUG +#define DBG_create_controller() ((void)0) +#define DBG_set_debug_level(level) ((void)0) +#define DBG_set_debug_write_fp(fp) ((void)0) +#define DBG_assert(expression, arg) ((void)0) +#define DBG_panic(arg) ((void)0) +#define DBG_debug_write(arg) ((void)0) +#else /* DBG_NO_DEBUG */ +#ifdef DBG_CONTROLLER +#define DBG_CURRENT_CONTROLLER DBG_CONTROLLER +#else /* DBG_CONTROLLER */ +#define DBG_CURRENT_CONTROLLER dbg_default_controller +#endif /* DBG_CONTROLLER */ +extern DBG_Controller DBG_CURRENT_CONTROLLER; + +#define DBG_create_controller() (DBG_create_controller_func()) +#define DBG_set_debug_level(level) \ + (DBG_set_debug_level_func(DBG_CURRENT_CONTROLLER, (level))) +#define DBG_set_debug_write_fp(fp) \ +(DBG_set_debug_write_fp(DBG_CURRENT_CONTROLLER, (fp)) +#define DBG_assert(expression, arg) \ + ((expression) ? (void)(0) : ((DBG_set(DBG_CURRENT_CONTROLLER, __FILE__, __LINE__)), (DBG_set_expression(#expression)), DBG_assert_func arg)) +#define DBG_panic(arg) \ + ((DBG_set(DBG_CURRENT_CONTROLLER, __FILE__, __LINE__)), \ + DBG_panic_func arg) +#define DBG_debug_write(arg) \ + ((DBG_set(DBG_CURRENT_CONTROLLER, __FILE__, __LINE__)), \ + DBG_debug_write_func arg) +#endif /* DBG_NO_DEBUG */ + +typedef enum +{ + DBG_TRUE = 1, + DBG_FALSE = 0 +} DBG_Boolean; + +DBG_Controller DBG_create_controller_func(void); +void DBG_set_debug_level_func(DBG_Controller controller, int level); +void DBG_set_debug_write_fp_func(DBG_Controller controller, FILE *fp); +void DBG_assert_func(char *fmt, ...); +void DBG_panic_func(char *fmt, ...); +void DBG_debug_write_func(int level, char *fmt, ...); +#endif /* PUBLIC_DBG_H_INCLUDED */ diff --git a/include/share.h b/include/share.h index 1e95950..fe18923 100644 --- a/include/share.h +++ b/include/share.h @@ -1,6 +1,34 @@ #ifndef PRIVATE_SHARE_H_INCLUDED #define PRIVATE_SHARE_H_INCLUDED +#include +#include +#include + +/* wchar.c */ +typedef struct +{ + wchar_t *string; +} VWString; + +void dkc_vwstr_append_string(VWString *v, wchar_t *str); +void dkc_vwstr_append_character(VWString *v, int ch); + +size_t dvm_wcslen(wchar_t *str); +wchar_t *dvm_wcscpy(wchar_t *dest, wchar_t *src); +wchar_t *dvm_wcsncpy(wchar_t *dest, wchar_t *src, size_t n); +int dvm_wcscmp(wchar_t *s1, wchar_t *s2); +wchar_t *dvm_wcscat(wchar_t *s1, wchar_t *s2); +int dvm_mbstowcs_len(const char *src); +void dvm_mbstowcs(const char *src, wchar_t *dest); +int dvm_wcstombs_len(const wchar_t *src); +void dvm_wcstombs_i(const wchar_t *src, char *dest); +char *dvm_wcstombs_alloc(const wchar_t *src); +char dvm_wctochar(wchar_t src); +int dvm_print_wcs(FILE *fp, wchar_t *str); +int dvm_print_wcs_ln(FILE *fp, wchar_t *str); +bool dvm_iswdigit(wchar_t ch); + #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) #endif diff --git a/interpreter/main.cpp b/interpreter/main.cpp index c20aab2..d77847a 100644 --- a/interpreter/main.cpp +++ b/interpreter/main.cpp @@ -15,6 +15,7 @@ int main(int argc, char *argv[]) if (yyin == NULL) { cout << "fail to open file:" << argv[1] << endl; + return 1; } else { diff --git a/main/main.c b/main/main.c index 597368c..3e9700e 100644 --- a/main/main.c +++ b/main/main.c @@ -4,7 +4,7 @@ int main(int argc, char *argv[]) { - Compiler *compiler = malloc(sizeof(Compiler)); + Compiler *compiler = create_compiler(); set_current_compiler(compiler); extern int yyparse(); @@ -13,10 +13,9 @@ int main(int argc, char *argv[]) if (yyin == NULL) { printf("fail to open file:%s\n", argv[1]); + exit(1); } - else - { - yyparse(); - } + + yyparse(); return 0; } diff --git a/share/wchar.c b/share/wchar.c new file mode 100644 index 0000000..14f7701 --- /dev/null +++ b/share/wchar.c @@ -0,0 +1,192 @@ +#include +#include +#include +#include +#include +#include +#include "../include/share.h" +#include "../include/DBG.h" + +size_t +dvm_wcslen(wchar_t *str) +{ + return wcslen(str); +} + +wchar_t * +dvm_wcscpy(wchar_t *dest, wchar_t *src) +{ + return wcscpy(dest, src); +} + +wchar_t * +dvm_wcsncpy(wchar_t *dest, wchar_t *src, size_t n) +{ + return wcsncpy(dest, src, n); +} + +int dvm_wcscmp(wchar_t *s1, wchar_t *s2) +{ + return wcscmp(s1, s2); +} + +wchar_t * +dvm_wcscat(wchar_t *s1, wchar_t *s2) +{ + return wcscat(s1, s2); +} + +int dvm_mbstowcs_len(const char *src) +{ + int src_idx, dest_idx; + int status; + mbstate_t ps; + + memset(&ps, 0, sizeof(mbstate_t)); + for (src_idx = dest_idx = 0; src[src_idx] != '\0';) + { + status = mbrtowc(NULL, &src[src_idx], MB_LEN_MAX, &ps); + if (status < 0) + { + return status; + } + dest_idx++; + src_idx += status; + } + + return dest_idx; +} + +void dvm_mbstowcs(const char *src, wchar_t *dest) +{ + int src_idx, dest_idx; + int status; + mbstate_t ps; + + memset(&ps, 0, sizeof(mbstate_t)); + for (src_idx = dest_idx = 0; src[src_idx] != '\0';) + { + status = mbrtowc(&dest[dest_idx], &src[src_idx], + MB_LEN_MAX, &ps); + dest_idx++; + src_idx += status; + } + dest[dest_idx] = L'\0'; +} + +int dvm_wcstombs_len(const wchar_t *src) +{ + int src_idx, dest_idx; + int status; + char dummy[MB_LEN_MAX]; + mbstate_t ps; + + memset(&ps, 0, sizeof(mbstate_t)); + for (src_idx = dest_idx = 0; src[src_idx] != L'\0';) + { + status = wcrtomb(dummy, src[src_idx], &ps); + src_idx++; + dest_idx += status; + } + + return dest_idx; +} + +void dvm_wcstombs_i(const wchar_t *src, char *dest) +{ + int src_idx, dest_idx; + int status; + mbstate_t ps; + + memset(&ps, 0, sizeof(mbstate_t)); + for (src_idx = dest_idx = 0; src[src_idx] != '\0';) + { + status = wcrtomb(&dest[dest_idx], src[src_idx], &ps); + src_idx++; + dest_idx += status; + } + dest[dest_idx] = '\0'; +} + +char * +dvm_wcstombs_alloc(const wchar_t *src) +{ + int len; + char *ret; + + len = dvm_wcstombs_len(src); + ret = malloc(len + 1); + dvm_wcstombs_i(src, ret); + + return ret; +} + +char dvm_wctochar(wchar_t src) +{ + mbstate_t ps; + int status; + char dest; + + memset(&ps, 0, sizeof(mbstate_t)); + status = wcrtomb(&dest, src, &ps); + DBG_assert(status == 1, ("wcrtomb status..%d\n", status)); + + return dest; +} + +int dvm_print_wcs(FILE *fp, wchar_t *str) +{ + char *tmp; + int result; + + tmp = dvm_wcstombs_alloc(str); + result = fprintf(fp, "%s", tmp); + free(tmp); + + return result; +} + +int dvm_print_wcs_ln(FILE *fp, wchar_t *str) +{ + int result; + + result = dvm_print_wcs(fp, str); + fprintf(fp, "\n"); + + return result; +} + +bool dvm_iswdigit(wchar_t ch) +{ + return ch >= L'0' && ch <= L'9'; +} + +static int my_wcslen(wchar_t *str) +{ + if (str == NULL) + { + return 0; + } + return dvm_wcslen(str); +} + +void dkc_vwstr_append_string(VWString *v, wchar_t *str) +{ + int new_size; + int old_len; + + old_len = my_wcslen(v->string); + new_size = sizeof(wchar_t) * (old_len + dvm_wcslen(str) + 1); + v->string = realloc(v->string, new_size); + dvm_wcscpy(&v->string[old_len], str); +} + +void dkc_vwstr_append_character(VWString *v, int ch) +{ + int current_len; + + current_len = my_wcslen(v->string); + v->string = realloc(v->string, sizeof(wchar_t) * (current_len + 2)); + v->string[current_len] = ch; + v->string[current_len + 1] = L'\0'; +}