fincparser.c
来自「FinC编译器源代码」· C语言 代码 · 共 2,486 行 · 第 1/4 页
C
2,486 行
#include <stdio.h>#include <finc/fincparser.h>#include <finc/finclang.h>#include <finc/finctype.h>#include <finc/finccontext.h>#ifdef USING_FILEstatic unsigned char* file_input(const char *arg);#endifstatic unsigned char* buffer_input(const char *arg);#ifdef USING_FILEstatic void parser_internal(FinCParser* self);#endifstatic void parser_internal_line(FinCParser* self);static FinCNode* proc_func_variable_decl(FinCParser* self);static FinCNode* proc_variable_decl(FinCParser* self);static FinCNode* proc_package(FinCParser* self);static FinCNode* proc_package_func(FinCParser* self);static FinCNode* proc_struct(FinCParser* self);static FinCNode* proc_field_list(FinCParser* self);static FinCNode* proc_field(FinCParser* self);#ifdef USING_FILEstatic FinCNode* proc_import(FinCParser* self);#endifstatic FinCNode* proc_param_list(FinCParser* self);static FinCNode* proc_type(FinCParser* self);static FinCNode* proc_identifier(FinCParser* self);static FinCNode* proc_expr(FinCParser* self);static FinCNode* proc_assign_expr(FinCParser* self);static FinCNode* proc_condition_expr(FinCParser* self);static FinCNode* proc_logical_or_expr(FinCParser* self);static FinCNode* proc_logical_and_expr(FinCParser* self);static FinCNode* proc_inclusive_or_expr(FinCParser* self);static FinCNode* proc_exclusive_or_expr(FinCParser* self);static FinCNode* proc_and_expr(FinCParser* self);static FinCNode* proc_equality_expr(FinCParser* self);static FinCNode* proc_relational_expr(FinCParser* self);static FinCNode* proc_shift_expr(FinCParser* self);static FinCNode* proc_additive_expr(FinCParser* self);static FinCNode* proc_multiplicative_expr(FinCParser* self);static FinCNode* proc_cast_expr(FinCParser* self);static FinCNode* proc_unary_expr(FinCParser* self);static FinCNode* proc_postfix_expr(FinCParser* self);static FinCNode* proc_primary_expr(FinCParser* self);static FinCNode* proc_call_param_list(FinCParser* self);static FinCNode* proc_statement(FinCParser* self);static FinCNode* proc_in_block_statement(FinCParser* self);static FinCNode* proc_block_statement(FinCParser* self);static FinCNode* proc_expr_statement(FinCParser* self);static FinCNode* proc_for_statement(FinCParser* self);static FinCNode* proc_while_statement(FinCParser* self);static FinCNode* proc_if_statement(FinCParser* self);static FinCNode* proc_simple_statement(FinCParser* self);static void make_pkg_begin(FinCParser* self, unsigned char* p_package);static void make_pkg_func_begin (FinCParser* self, FinCNode* p_type, FinCNode* p_identifier);static FinCNode* make_pkg_func_finish (FinCParser* self);static FinCNode* make_pkg_finish(FinCParser* self);static void make_func_begin (FinCParser* self, FinCNode* p_type, FinCNode* p_identifier);static void make_func_add_param (FinCParser* self, FinCNode* p_type, FinCNode* p_name);static void make_func_opt_param (FinCParser* self);static FinCNode* make_func_finish (FinCParser* self, FinCNode* p_code);static void make_block_begin (FinCParser* self);static void make_block_add (FinCParser* self, FinCNode* p_node);static FinCNode* make_block_finish (FinCParser* self);static void make_call_begin (FinCParser* self, unsigned char* p_identifier);static void make_call_add (FinCParser* self, FinCNode* p_node);static FinCNode* make_call_finish (FinCParser* self);static FinCNode* make_efunc (unsigned char* p_func);static FinCNode* make_efunc1 (unsigned char* p_func, FinCNode* p_node1);static FinCNode* make_efunc2 (unsigned char* p_func, FinCNode* p_node1, FinCNode* p_node2);static FinCNode* make_efunc3 (unsigned char* p_func, FinCNode* p_node1, FinCNode* p_node2, FinCNode* p_node3);static FinCNode* make_efunc4 (unsigned char* p_func, FinCNode* p_node1, FinCNode* p_node2, FinCNode* p_node3, FinCNode* p_node4);#define check_token(token, lex, type) if ( (token) != (type) ) \ { \ finc_lang_error_line(lex, "Parser Error: Invalid token."); \ finc_context_error_inc(g_finc_context); \ finc_token_replay(lex); \ }#ifdef USING_DOUBLE#define is_double(token) ((token) == FinCTokenType_Type_Double)#else#define is_double(token) 0#endif#ifdef USING_FLOAT#define is_float(token) ((token) == FinCTokenType_Type_Float)#else#define is_float(token) 0#endif#define is_base_type(token) (token) == FinCTokenType_Type_Void || (token) == FinCTokenType_Type_Char \ || (token) == FinCTokenType_Type_Short || (token) == FinCTokenType_Type_Int \ || is_double(token) \ || is_float(token) \ || (token) == FinCTokenType_Type_Pointer || (token) == FinCTokenType_Type_String#define is_type(token) (token) == FinCTokenType_Identifier || is_base_type(token)#define next_token(token, lex) (token) = finc_token_token(lex)#define match_token(token, lex, type) next_token(token, lex); \ check_token(token, lex, type)FinCParser* finc_parser_new(){ FinCParser* self; self = (FinCParser*)mem_new(sizeof(FinCParser)); self->tree_root = NULL; self->lex = NULL; self->parse_string = NULL; self->lang_env = NULL; self->stack_call = stack_new(); self->stack_block = stack_new(); self->current_func = NULL; self->current_block = NULL; self->current_call = NULL; self->current_type = NULL; self->current_pkg = NULL; self->current_struct= NULL; object_init_object((Object*)self, finc_parser_destroy); return self;}void finc_parser_destroy(Object* self){ unref( ((FinCParser*)self)->tree_root ); unref( ((FinCParser*)self)->lex ); unref( ((FinCParser*)self)->parse_string ); unref( ((FinCParser*)self)->lang_env ); unref( ((FinCParser*)self)->stack_call); unref( ((FinCParser*)self)->stack_block); unref( ((FinCParser*)self)->current_func); unref( ((FinCParser*)self)->current_block); unref( ((FinCParser*)self)->current_call); unref( ((FinCParser*)self)->current_type); unref( ((FinCParser*)self)->current_pkg); unref( ((FinCParser*)self)->current_struct); mem_destroy(self);}void finc_parser_set_env (FinCParser* self, FinCLangEnv* env){ unref(self->lang_env); self->lang_env = addref(FinCLangEnv, env);}static int parse_string_pos;static unsigned char* buffer_input(const char *arg){ static char line[512]; char* p, ch; String* buffer = (String*)arg; line[0] = '\0'; p = line; if (string_at(buffer, parse_string_pos)=='\0') return NULL; while( ((ch = string_at(buffer, parse_string_pos++)) != '\0') && (ch != '\n') ) *p++ = ch; if ( string_at(buffer, parse_string_pos -1) == '\0') parse_string_pos --; *p++ = ch; *p = '\0'; return line;}void finc_parser_parser_string(FinCParser* self, String* str){ self->parse_string = addref(String, str); self->lex = finc_token_new(); self->lex->arg = (char*)self->parse_string; self->lex->read_line = buffer_input; parse_string_pos = 0; parser_internal_line(self); unref(self->lex); self->lex = NULL; unref(str);}#ifdef USING_FILEstatic unsigned char* file_input(const char *arg){ static char line[512]; line[0] = 0; return fgets(line, sizeof line, (FILE *)arg);}void finc_parser_parser_file(FinCParser* self, const char* filename){ FILE* fp; fp = fopen(filename, "r"); if ( fp == NULL ) { printf("Can't open input file.\n"); return; } self->lex = finc_token_new(); self->lex->arg = (char*)fp; self->lex->read_line = file_input; parser_internal(self); fclose(fp); unref(self->lex); self->lex = NULL;}#endif/**line_input -> empty | line_input line_startline_start -> decl_import | decl_global | decl_function | decl_struct | decl_package | statement_block | statement_expr | statement_for | statement_while | statement_if*/static void parser_internal_line(FinCParser* self){ FinCNode* node; FinCTokenType token; String* str; self->tree_root = finc_node_new(); finc_node_set_block (self->tree_root); next_token(token, self->lex); while ( (token != FinCTokenType_Eof) && (token != FinCTokenType_Bad) ) { switch ( token ) {#ifdef USING_FILE case FinCTokenType_Import: finc_token_replay(self->lex); proc_import(self); break;#endif case FinCTokenType_Struct: finc_token_replay(self->lex); proc_struct(self); break; case FinCTokenType_Package: finc_token_replay(self->lex); proc_package(self); break; case FinCTokenType_Left_Curly: finc_token_replay(self->lex); node = proc_block_statement(self); if (node) { finc_node_add( self->tree_root, node); unref(node); } break; case FinCTokenType_For: finc_token_replay(self->lex); node = proc_for_statement(self); if (node) { finc_node_add( self->tree_root, node); unref(node); } break; case FinCTokenType_While: finc_token_replay(self->lex); node = proc_while_statement(self); if (node) { finc_node_add( self->tree_root, node); unref(node); } break; case FinCTokenType_If: finc_token_replay(self->lex); node = proc_if_statement(self); if (node) { finc_node_add( self->tree_root, node); unref(node); } break; default: if ( is_base_type(token) ) /*function or variable declaration*/ { finc_token_replay(self->lex); node = proc_func_variable_decl(self); } else if ( token == FinCTokenType_Identifier ) { str = finc_token_get_token(self->lex); if (finc_lang_check_type(self->lang_env, str))/*it's a struct type.*/ { unref(str); finc_token_replay(self->lex); node = proc_func_variable_decl(self); } else { unref(str); finc_token_replay(self->lex); node = proc_expr_statement(self); } } else /*statement_expr*/ { finc_token_replay(self->lex); node = proc_expr_statement(self); } if (node) { finc_node_add( self->tree_root, node); unref(node); } break; } next_token(token, self->lex); } /*end of line parser*/}/**input -> empty | input declarationdeclaration -> decl_import | decl_global | decl_function | decl_struct | decl_package*/#ifdef USING_FILEstatic void parser_internal(FinCParser* self){ FinCNode* node; FinCTokenType token; self->tree_root = finc_node_new(); finc_node_set_block (self->tree_root); next_token(token, self->lex); while ( token == FinCTokenType_Package || token == FinCTokenType_Struct || token == FinCTokenType_Import || is_type(token) ) { switch ( token ) { case FinCTokenType_Import: finc_token_replay(self->lex); proc_import(self); break; case FinCTokenType_Struct: finc_token_replay(self->lex); proc_struct(self); break; case FinCTokenType_Package: finc_token_replay(self->lex); proc_package(self); break; default: if ( is_type(token) ) { finc_token_replay(self->lex); node = proc_func_variable_decl(self); if (node) { finc_node_add( self->tree_root, node); unref(node); } } else { finc_lang_error_line(self->lex, "Parser Error: expecting a declaration."); finc_context_error_inc(g_finc_context); } break; } next_token(token, self->lex); } if ( token != FinCTokenType_Eof ) { finc_lang_error_line(self->lex, "Parser Error:expecting a EOF.\n"); finc_context_error_inc(g_finc_context); } /*end of main parser*/}#endif/*process for function and variable declaration.decl_variable -> type declaration_list ';' | type identifier '[' V_INT ']' ';' | type identifier '[' ']' ';'declarator_list -> declarator_list ',' declarator | declaratordeclarator -> identifier | identifier ASSIGN expr_assigndecl_function -> type identifier '(' decl_param_type_list ')' statement_block*/static FinCNode* proc_func_variable_decl(FinCParser* self){ FinCTokenType token; FinCNode* type; FinCNode* id; FinCNode* statement; FinCNode* assign; FinCNode* node_func; Bool b_static, b_unsigned; b_static = FALSE; b_unsigned = FALSE; type = proc_type(self); id = proc_identifier(self);/*process id.*/ next_token(token, self->lex); switch ( token ) { case FinCTokenType_Left_Brace:/*'[', it's a array variable declaration.*/ next_token(token, self->lex); if (token == FinCTokenType_Right_Brace)/*it's a dynamic array declaration.*/ { type->type->array_type = FinCArrayType_Dynamic; type->type->array_size = 0; match_token(token, self->lex, FinCTokenType_Semicolon); finc_node_add(type, id); unref(id); return make_efunc1("global", type); } else if (token == FinCTokenType_Int)/*it's a fixed array declaration.*/ { type->type->array_type = FinCArrayType_Fixed; type->type->array_size = (int)self->lex->last_double; match_token(token, self->lex, FinCTokenType_Right_Brace); match_token(token, self->lex, FinCTokenType_Semicolon); finc_node_add(type, id); unref(id); return make_efunc1("global", type); } else { finc_lang_error_line(self->lex, "Parser Error:expecting an interger in an array declaration."); finc_context_error_inc(g_finc_context); finc_token_replay(self->lex); return NULL; } break; case FinCTokenType_Comma:/*',', it's a variable_list declaration.*/ finc_node_add(type, id); unref(id); id = proc_identifier(self); next_token(token, self->lex); if ( token == FinCTokenType_Assign ) { assign = proc_assign_expr(self); finc_node_add (id, assign); unref(assign); next_token(token, self->lex); } finc_node_add(type, id); unref(id); while ( token == FinCTokenType_Comma ) { id = proc_identifier(self); next_token(token, self->lex); if ( token == FinCTokenType_Assign ) { assign = proc_assign_expr(self); finc_node_add (id, assign); unref(assign); next_token(token, self->lex); } finc_node_add(type, id); unref(id); } check_token(token, self->lex, FinCTokenType_Semicolon); return make_efunc1("global", type); break; case FinCTokenType_Assign:/*'=', it's a variable with assign declaration.*/ assign = proc_assign_expr(self); finc_node_add (id, assign); unref(assign); finc_node_add (type, id); unref(id); next_token(token, self->lex); while ( token == FinCTokenType_Comma ) { id = proc_identifier(self); next_token(token, self->lex); if ( token == FinCTokenType_Assign ) { assign = proc_assign_expr(self); finc_node_add (id, assign); unref(assign); next_token(token, self->lex); } finc_node_add(type, id); unref(id); } check_token(token, self->lex, FinCTokenType_Semicolon); return make_efunc1("global", type); case FinCTokenType_Semicolon:/*';', it's a variable declaration.*/ finc_node_add(type, id); unref(id); return make_efunc1("global", type); case FinCTokenType_Left_Paren:/*'(', it's a function declaration.*/ make_func_begin(self, type, id); next_token(token, self->lex); if ( token != FinCTokenType_Right_Paren ) { finc_token_replay(self->lex); proc_param_list(self); match_token(token, self->lex, FinCTokenType_Right_Paren); } statement = proc_block_statement(self); node_func = make_func_finish(self, statement); finc_lang_proc_func(self->lang_env, node_func); unref(node_func); return NULL; break; default: finc_lang_error_line(self->lex, "Parser Error:variable or function declaration error."); finc_context_error_inc(g_finc_context); unref(type); unref(id); return NULL; break; }}/*process for function and variable declaration.decl_variable -> type declaration_list ';' | type identifier '[' V_INT ']' | type identifier '[' ']'declarator_list -> declarator_list ',' declarator | declaratordeclarator -> identifier | identifier ASSIGN expr_assign*/static FinCNode* proc_variable_decl(FinCParser* self){ FinCTokenType token; FinCNode* type; FinCNode* id; FinCNode* assign; Bool b_static, b_unsigned; b_static = FALSE; b_unsigned = FALSE; type = proc_type(self); id = proc_identifier(self);/*process id.*/ next_token(token, self->lex); switch ( token ) { case FinCTokenType_Left_Brace:/*'[', it's a array variable declaration.*/ next_token(token, self->lex); if (token == FinCTokenType_Right_Brace)/*it's a dynamic array declaration.*/ { type->type->array_type = FinCArrayType_Dynamic; type->type->array_size = 0; match_token(token, self->lex, FinCTokenType_Semicolon); finc_node_add(type, id); unref(id); return type; } else if (token == FinCTokenType_Int)/*it's a fixed array declaration.*/ { type->type->array_type = FinCArrayType_Fixed; type->type->array_size = (int)self->lex->last_double;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?