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 + -
显示快捷键?