fincparser.c
来自「FinC编译器源代码」· C语言 代码 · 共 2,486 行 · 第 1/4 页
C
2,486 行
match_token(token, self->lex, FinCTokenType_Right_Brace); match_token(token, self->lex, FinCTokenType_Semicolon); finc_node_add(type, id); unref(id); return type; } else { finc_lang_error_line(self->lex, "Parser Error:must use a interger in an array declaration."); finc_context_error_inc(g_finc_context); 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 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 type; break; case FinCTokenType_Semicolon:/*';', it's a variable declaration.*/ finc_node_add(type, id); unref(id); return type; break; default: finc_lang_error_line(self->lex, "Parser Error:variable declaration error."); finc_context_error_inc(g_finc_context); unref(type); unref(id); return NULL; break; }}/*decl_package -> PACKAGE V_STRING '{' decl_package_func_list '}' ';'*/static FinCNode* proc_package(FinCParser* self){ FinCTokenType token; FinCNode* pkg; match_token(token, self->lex, FinCTokenType_Package); match_token(token, self->lex, FinCTokenType_String); make_pkg_begin(self, string_get_str(self->lex->last_str)); match_token(token, self->lex, FinCTokenType_Left_Curly); next_token(token, self->lex); if (token != FinCTokenType_Right_Curly) { finc_token_replay(self->lex); proc_package_func(self); match_token(token, self->lex, FinCTokenType_Right_Curly); } match_token(token, self->lex, FinCTokenType_Semicolon); pkg = make_pkg_finish(self); #ifdef USING_PACKAGE finc_lang_proc_pkg(self->lang_env, pkg);#endif unref(pkg); return NULL;}/*decl_package_func_list -> decl_package_func | decl_package_func_list decl_package_funcdecl_package_func -> type identifier '(' decl_param_type_list ')' ';'*/static FinCNode* proc_package_func(FinCParser* self){ FinCTokenType token; FinCNode* type; FinCNode* id; FinCNode* node_pkg; next_token(token, self->lex); while ( is_type(token) ) { finc_token_replay(self->lex); type = proc_type(self); id = proc_identifier(self); make_pkg_func_begin(self, type, id); match_token(token, self->lex, FinCTokenType_Left_Paren); 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); } match_token(token, self->lex, FinCTokenType_Semicolon); node_pkg = make_pkg_func_finish(self); finc_node_add (self->current_pkg, node_pkg); unref(node_pkg); next_token(token, self->lex); } finc_token_replay(self->lex); return NULL;/*support for pkg.*/}/*decl_struct -> STRUCT identifier '{' decl_field_list '}' ';'*/static FinCNode* proc_struct(FinCParser* self){ FinCTokenType token; FinCNode* id; FinCNode* node_struct; match_token(token, self->lex, FinCTokenType_Struct); id = proc_identifier(self); if (id) { self->current_struct = finc_node_new_func ("struct"); finc_node_add (self->current_struct, id); unref (id); } else return NULL; match_token(token, self->lex, FinCTokenType_Left_Curly); next_token(token, self->lex); if ( token != FinCTokenType_Right_Curly ) { finc_token_replay(self->lex); proc_field_list(self); } match_token(token, self->lex, FinCTokenType_Right_Curly); match_token(token, self->lex, FinCTokenType_Semicolon); node_struct = self->current_struct; self->current_struct = NULL; finc_lang_proc_struct(self->lang_env, node_struct); unref(node_struct); return NULL;}/*decl_field_list -> decl_field_declarator | decl_field_list decl_field_declarator*/static FinCNode* proc_field_list(FinCParser* self){ FinCTokenType token; FinCNode* field; next_token(token, self->lex); while ( (token!= FinCTokenType_Right_Curly) && (is_type(token)) ) { finc_token_replay(self->lex); field = proc_field(self); finc_node_add (self->current_struct, field); unref(field); next_token(token, self->lex); } finc_token_replay(self->lex); return NULL;}/*decl_field_declarator -> type struct_declarator_list ';' | type identifier '[' V_INT ']' | type identifier '[' ']'struct_declarator_list -> struct_declarator_list ',' struct_declarator | struct_declaratorstruct_declarator -> identifier*/static FinCNode* proc_field(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 = self->lex->last_long; match_token(token, self->lex, FinCTokenType_Right_Brace); match_token(token, self->lex, FinCTokenType_Semicolon); finc_node_add(type, id); unref(id); return type; } else { finc_lang_error_line(self->lex, "Parser Error:must use a interger in an array declaration."); finc_context_error_inc(g_finc_context); 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 type; break; case FinCTokenType_Semicolon:/*';', it's a variable declaration.*/ finc_node_add(type, id); unref(id); return type; break; default: finc_lang_error_line(self->lex, "Parser Error:variable declaration error."); finc_context_error_inc(g_finc_context); unref(type); unref(id); return NULL; break; }}#ifdef USING_FILE/**decl_import -> IMPORT V_STRING ';'*/static FinCNode* proc_import(FinCParser* self){ FinCTokenType token; FinCNode* string; FinCNode* import; match_token(token, self->lex, FinCTokenType_Import); match_token(token, self->lex, FinCTokenType_String); /*perform at last.*/ string = finc_node_new_string(string_get_str(self->lex->last_str)); match_token(token, self->lex, FinCTokenType_Semicolon); import = make_efunc1 ("import", string); finc_lang_proc_import(self->lang_env, import); unref(import); return NULL;}#endif/**decl_param_type_list -> decl_param_list | decl_param_list ',' OPT_PARAMdecl_param_list -> empty | decl_param | decl_param_list ',' decl_paramdecl_param -> type identifier | type identifier '[' ']' | type identifier '[' V_INT ']'*/static FinCNode* proc_param_list(FinCParser* self){ FinCTokenType token; FinCNode* type; FinCNode* id; type = proc_type(self); id = proc_identifier(self); next_token(token, self->lex); if (token == FinCTokenType_Left_Brace)/*if it's a array param.*/ { next_token(token, self->lex); if (token == FinCTokenType_Right_Brace) { type->type->array_type = FinCArrayType_Dynamic; type->type->array_size = 0; } else { type->type->array_type = FinCArrayType_Fixed; type->type->array_size = (int)self->lex->last_double; } next_token(token, self->lex); } make_func_add_param(self, type, id); while (token == FinCTokenType_Comma) { type = proc_type(self); id = proc_identifier(self); next_token(token, self->lex); if (token == FinCTokenType_Left_Brace)/*if it's a array param.*/ { next_token(token, self->lex); if (token == FinCTokenType_Right_Brace) { type->type->array_type = FinCArrayType_Dynamic; type->type->array_size = 0; } else { type->type->array_type = FinCArrayType_Fixed; type->type->array_size = (int)self->lex->last_double; } next_token(token, self->lex); } make_func_add_param(self, type, id); } finc_token_replay(self->lex); return NULL;}#ifdef USING_OO/*decl_class -> CLASS identifier [:] [public] [class] class_scope '{' decl_class_member_list '}' [;]*/static FinCNode* proc_class(FinCParser* self){ FinCTokenType token; FinCNode* id; match_token(token, self->lex, FinCTokenType_Class); id = proc_identifier(self); if ( id ) { } else return NULL; next_token(token, self->lex); if ( token != FinCTokenType_Colon ) /* [:] */ { match_token(token, self->lex, FinCTokenType_Left_Curly); /* { */ next_token (token, self->lex); if ( token != FinCTokenType_Right_Curly ) /* } */ { finc_token_replay(self->lex); proc_class_member_list(self); /* decl_class_member_list */ } match_token(token, self->lex, FinCTokenType_Right_Curly); match_token(token, self->lex, FinCTokenType_Semicolon); /* ; */ } else { next_token(token, self->lex); if ( token != FinCTokenType_Public ) finc_token_replay(self->lex); next_token(token, self->lex); if ( token != FinCTokenType_Class ) finc_token_replay(self->lex); proc_class_scope(self); }}/*class_scope -> ID | class_scope ':'':' ID*/static FinCNode* proc_class_scope(FinCParser* self){ FinCTokenType token; FinCNode* id; id = proc_identifier(self); /* ID */ while ( token == FinCTokenType_Identifier ) { id = proc_identifier(self); } return id;}/*decl_class_member_list -> decl_class_class_member | decl_class_member_list decl_class_member*/static FinCNode* proc_class_member_list(FinCParser* self){ FinCTokenType token; FinCNode* field; next_token(token, self->lex); while ( (token!= FinCTokenType_Right_Curly) && ((is_type(token))|| token == FinCTokenType_Public || token == FinCTokenType_Private || token == FinCTokenType_Virtual || token == FinCTokenType_Class || ) ) { finc_token_replay(self->lex); member = proc_class_member(self); finc_node_add(self->current_class, member); unref(member); next_token(token, self->lex); } finc_token_replay(self->lex); return NULL;}/*decl_member -> access-specifier decl_variable | access-specifier type identifier '(' decl_param_type_list ')' statement_block | virtual access-specifier type identifier '(' decl_param_type_list ')' statement_block | virtual access-specifier type identifier '(' decl_param_type_list ')' '=' '0' ';' | access-specifier decl_classaccess-specifier -> PUBLIC | PRIVATE*/static FinCNode* proc_class_member(FinCParser* self){ FinCTokenType token; FinCNode* _class; FinCNode* type; FinCNode* id; FinCNode* assign; Bool b_public, b_virtual, b_static, b_unsigned; b_public = FALSE; b_virtual = FALSE; b_static = FALSE; b_unsigned = FALSE; next_token(token, self->lex); if ( token == FinCTokenType_Virtual ) b_virtual = TRUE; else if ( token == FinCTokenType_Public ) b_public = TRUE; else if ( token == FinCTokenType_Private ) b_public = FALSE; else if ( token == FinCTokenType_Static ) b_static = TRUE; else if ( token == FinCTokenType_unsigned ) b_unsigned = TRUE; else if ( token == FinCTokenType_Class ) { finc_token_replay(self->lex); _class = proc_class(self); } else finc_token_replay(self->lex); /* attribute and method */}#endif/*type -> type_list | identifiertype_list -> type_basic | type_list type_basictype_basic -> VOID | CHAR | SHORT | INT | STRING | POINTER | FLOAT | DOUBLE | BOOLidentifier -> IDENTIFIERnote:there is only one base type in type_list.so there are only four case:idbase_typeunsigned base_typestatice [unsigned] base_type*/static FinCNode* proc_type(FinCParser* self){ FinCTokenType token; FinCNode* type; String* str; type = NULL; next_token(token, self->lex); if ( token == FinCTokenType_Identifier ) /*case 1, id*/ { str = finc_token_get_token(self->lex); if (finc_lang_check_type(self->lang_env, str))/*it's a struct type.*/ { type = finc_node_new_type(str, FinCArrayType_None, 0); unref(str); } else { finc_token_replay(self->lex); finc_lang_error_line(self->lex, "Parser Error:unknow struct name."); unref(str); return NULL; } } else if ( is_base_type(token) ) /*case 2, base_type*/ { str = finc_token_get_token(self->lex); type = finc_node_new_type(str, FinCArrayType_None, 0); unref(str); } else if ( token == FinCTokenType_Unsigned ) /*case 3, unsigned base_type*/ { next_token(token, self->lex); if ( is_base_type(token) )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?