⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c.y

📁 C编译器,在VC6.0环境下开发
💻 Y
📖 第 1 页 / 共 5 页
字号:
specifier_qualifier_list
		:	type_specifier specifier_qualifier_list
			{
				PARSE_INFO("specifier_qualifier_list :type_specifier specifier_qualifier_list")
			}
		|	type_specifier
			{
				PARSE_INFO("specifier_qualifier_list :type_specifier")
			}
		|	type_qualifier specifier_qualifier_list
			{
				PARSE_INFO("specifier_qualifier_list :type_qualifier specifier_qualifier_list")
			}
		|	type_qualifier
			{
				PARSE_INFO("specifier_qualifier_list :type_qualifier")
			}
		;
*/

declarator
		:
/*
			pointer	direct_declarator
			{
				PARSE_INFO("declarator :pointer	direct_declarator")
			}
		|
*/
			direct_declarator
			{
				PARSE_INFO("declarator :direct_declarator")
			}
		;

direct_declarator
		:	identifier
			{
				PARSE_INFO("direct_declarator :identifier")
				$$ = new_symbol();
				strncpy( $$->name, $1, NAME_LEN );
			}
/*	// pointer need it, we skip pointer, so skip it
		|	oLP declarator oRP
			{
				PARSE_INFO("direct_declarator :oLP declarator oRP")
			}
*/
		|	direct_declarator oLB constant_expression oRB
			{
				PARSE_INFO("direct_declarator :direct_declarator oLB constant_expression oRB")
				// array declaration
				if ( IS_FUNCTION($1) )
				{
					yyerror("function returns array");
					user_exit(1);
				}
				if ( IS_ARRAY($1) )
				{
					yyerror("only support one demision array");
					user_exit(1);
				}
				// check constant_expression
				if ( !IS_CL($3) )
				{
					yyerror("array unknown size");
					user_exit(1);
				}
				if ( !get_sym_value($3) )
				{
					yyerror("cannot allocate an array of constant size 0");
					user_exit(1);
				}
				if (get_sym_value($3) < 0)
				{
					yyerror("negative subscript or subscript is too large");
					user_exit(1);
				}
				// set array flag
				$1->is_array = 1;
				$1->num_ele = get_sym_value($3);
				del_symbol($3);
			}
		|	direct_declarator oLB oRB
			{
				PARSE_INFO("direct_declarator :direct_declarator oLB oRB")
				if ( IS_FUNCTION($1) )
				{
					yyerror("function returns array");
					user_exit(1);
				}
				if ( IS_ARRAY($1) )
				{
					yyerror("only support one demision array");
					user_exit(1);
				}
				// set array flag
				$1->is_array = 1;
				$1->num_ele = 0;
			}
		|	direct_declarator oLP parameter_type_list oRP
			{
				PARSE_INFO("direct_declarator :direct_declarator oLP parameter_type_list oRP")
				if ( IS_FUNCTION($1) )
				{
					yyerror("function returns function");
					user_exit(1);
				}
				if ( IS_ARRAY($1) )
				{
					yyerror("array element type cannot be function");
					user_exit(1);
				}
				// set function flag
				$1->is_function = 1;
				// assign function rname
				if ( IS_MAIN_FUNC($1) )
				{
					// main(..)
					strcpy($1->rname, $1->name);
				}
				else
				{
					sprintf($1->rname, _FUNCTION_NAME, $1->name);
				}
				// check weather func(void)
				if ( $3->NOUN == SPEC_VOID )
				{
					if ( $3->next )
					{
						yyerror("internal error in 'direct_declarator oLP parameter_type_list oRP'");
						user_exit(1);
					}
					//so, ...
					$1->args = NULL;
					del_symbol($3);
				}
				else
				{
					$1->args = $3;
					// assign parameters rname
					assign_parameters_rname($3);
				}
			}
/*		|	direct_declarator oLP identifier_list oRP
			{
				PARSE_INFO("direct_declarator :direct_declarator oLP identifier_list oRP")
				// old style function declaration, not support
			}
*/
		|	direct_declarator oLP oRP
			{
				PARSE_INFO("direct_declarator :direct_declarator oLP oRP")
				if ( IS_FUNCTION($1) )
				{
					yyerror("function returns function");
					user_exit(1);
				}
				if ( IS_ARRAY($1) )
				{
					yyerror("array element type cannot be function");
					user_exit(1);
				}
				// set function flag
				$1->is_function = 1;
				// assign function rname
				if ( IS_MAIN_FUNC($1) )
				{
					// main(..)
					strcpy($1->rname, $1->name);
				}
				else
				{
					sprintf($1->rname, _FUNCTION_NAME, $1->name);
				}
				// no parameters , so ->args is NULL as default
			}
		;

/*
pointer
		:	oMUL type_qualifier_list
			{
				PARSE_INFO("pointer :oMUL type_qualifier_list")
			}
		|	oMUL
			{
				PARSE_INFO("pointer :oMUL")
			}
		|	oMUL type_qualifier_list pointer
			{
				PARSE_INFO("pointer :oMUL type_qualifier_list pointer")
			}
		|	oMUL pointer
			{
				PARSE_INFO("pointer :oMUL pointer")
			}
		;

type_qualifier_list
		:	type_qualifier
			{
				PARSE_INFO("type_qualifier_list :type_qualifier")
			}
		|	type_qualifier_list type_qualifier
			{
				PARSE_INFO("type_qualifier_list :type_qualifier_list type_qualifier")
			}
		;
*/

parameter_type_list
		:	parameter_list
			{
				PARSE_INFO("parameter_type_list :parameter_list")
			}
		|	parameter_list oCOMMA oDOTDOTDOT
			{
				PARSE_INFO("parameter_type_list :parameter_list oCOMMA oDOTDOTDOT")
				yyerror("more arguments not support now");
				user_exit(1);
			}
		;

parameter_list
		:	parameter_declaration
			{
				PARSE_INFO("parameter_list :parameter_declaration")
			}
		|	parameter_list oCOMMA parameter_declaration
			{
				PARSE_INFO("parameter_list :parameter_list oCOMMA parameter_declaration")
				// if in this state, parameter is void, it must be 
				// in declaration_specifiers
				// so it must has (..., void,..) or (void, ...)
				// error
				if ($3->NOUN == SPEC_VOID || $1->NOUN == SPEC_VOID)
				{
					yyerror("'void' cannot be an argument type, except for '(void)'");
					user_exit(1);
				}
				link_symbol_list($1, $3);
			}
		;

parameter_declaration
		:	declaration_specifiers declarator
			{
				PARSE_INFO("parameter_declaration :declaration_specifiers declarator")
				unoin_specifier_to_declarator($1, $2);
				del_symbol( $1 );
				// set argument flag
				$2->is_argument = 1;
				if ( !IS_VAR($2) )
				{
					yyerror("function has bad storage class");
					user_exit(1);
				}
				check_var_declarator($2);
				$$ = $2;
			}
		|	declaration_specifiers abstract_declarator
			{
				PARSE_INFO("parameter_declaration :declaration_specifiers abstract_declarator")
				unoin_specifier_to_declarator($1, $2);
				del_symbol( $1 );
				// set argument flag
				$2->is_argument = 1;
				if ( !IS_VAR($2) )
				{
					yyerror("function has bad storage class");
					user_exit(1);
				}
				check_var_declarator($2);
				$$ = $2;
			}
		|	declaration_specifiers
			{
				PARSE_INFO("parameter_declaration :declaration_specifiers")
				// it means in declaration is not use, and 
				// in definition is can not use the parameter
				// so assign the args a unmeeted name, such as number, xixi....
				// just use specifier symbol as var
				
				// set argument flag
				$1->is_argument = 1;
				if ( !IS_VAR($1) )
				{
					yyerror("function has bad storage class");
					user_exit(1);
				}
				// assign symbol a unused name
				assign_symbol_unusedname($1);
			}
		;

/*	// used by old style function declaration
identifier_list
		:	identifier
			{
				PARSE_INFO("identifier_list	:identifier")
			}
		|	identifier_list oCOMMA identifier
			{
				PARSE_INFO("identifier_list	:identifier_list oCOMMA identifier")
			}
		;
*/

initializer
		:	assignment_expression
			{
				PARSE_INFO("initializer :assignment_expression")
			}
		|	oLC initializer_list oRC
			{
				PARSE_INFO("initializer :oLC initializer_list oRC")
				yyerror("initialize = {....} not support");
				user_exit(1);
			}
		|	oLC initializer_list oCOMMA oRC
			{
				PARSE_INFO("initializer :oLC initializer_list oCOMMA oRC")
				yyerror("initialize = {...., } not support");
				user_exit(1);
			}
		;

initializer_list
		:	initializer
			{
				PARSE_INFO("initializer_list :initializer")
			}
		|	initializer_list oCOMMA initializer
			{
				PARSE_INFO("initializer_list :initializer_list oCOMMA initializer")
			}
		;

/*	// 类型转换, skip
type_name
		:	specifier_qualifier_list abstract_declarator
			{
				PARSE_INFO("type_name :specifier_qualifier_list abstract_declarator")
			}
		|	specifier_qualifier_list
			{
				PARSE_INFO("type_name :specifier_qualifier_list")
			}
		;
*/

abstract_declarator
		:
/*
			pointer
			{
				PARSE_INFO("abstract_declarator :pointer")
			}
		|	pointer direct_abstract_declarator
			{
				PARSE_INFO("abstract_declarator :pointer direct_abstract_declarator")
			}
		|
*/
			direct_abstract_declarator
			{
				PARSE_INFO("abstract_declarator :direct_abstract_declarator")
			}
		;

direct_abstract_declarator
		:	
/*	// pointer need it, we skip pointer. so we skip it
			oLP abstract_declarator oRP
			{
				PARSE_INFO("direct_abstract_declarator :oLP abstract_declarator oRP")
			}
		|	
*/
/*	// we only support one demission array, so skip it
			direct_abstract_declarator oLB constant_expression oRB
			{
				PARSE_INFO("direct_abstract_declarator :direct_abstract_declarator oLB constant_expression oRB")
			}
		|	
*/
			oLB constant_expression oRB
			{
				PARSE_INFO("direct_abstract_declarator :oLB constant_expression oRB")
				// array declaration
				// check constant_expression
				if ( !IS_CL($2) )
				{
					yyerror("array unknown size");
					user_exit(1);
				}
				if ( !get_sym_value($2) )
				{
					yyerror("cannot allocate an array of constant size 0");
					user_exit(1);
				}
				if (get_sym_value($2) < 0)
				{
					yyerror("negative subscript or subscript is too large");
					user_exit(1);
				}
				$$ = new_symbol();
				// assign symbol a unused name
				assign_symbol_unusedname($$);
				// set array flag
				$$->is_array = 1;
				$$->num_ele = get_sym_value($2);
				del_symbol($2);
			}
/*	// function pointer, so skip
		|	direct_abstract_declarator oLP parameter_type_list oRP
			{
				PARSE_INFO("direct_abstract_declarator :direct_abstract_declarator oLP parameter_type_list oRP")
			}
		|	oLP parameter_type_list oRP
			{
				PARSE_INFO("direct_abstract_declarator :oLP parameter_type_list oRP")
			}
*/
		;

identifier
		:	yNAME
			{
				PARSE_INFO("identifier :yNAME")
				PARSE_INFO("======= FOLLOW BY =======")
				PARSE_INFO($1)
			}
		;

statement
		:	labeled_statement
			{
				PARSE_INFO("statement :labeled_statement")
			}
		|	expression_statement
			{
				PARSE_INFO("statement :expression_statement")
			}
		|	compound_statement
			{
				PARSE_INFO("statement :compound_statement")
			}
		|	selection_statement
			{
				PARSE_INFO("statement :selection_statement")
			}
		|	iteration_statement
			{
				PARSE_INFO("statement :iteration_statement")
			}
		|	jump_statement
			{
				PARSE_INFO("statement :jump_statement")
			}
		;

labeled_statement
		:	identifier oCOLON 
			{
				symbol	*lb;

				PARSE_INFO("labeled_statement :identifier oCOLON ")
				lb = search_goto_label($1);
				if ( !lb )
				{
					// the label has not be reference
					// so, new symbol and add it to goto label symtab
					lb = new_symbol();
					lb->NOUN = SPEC_LABEL;
					strcpy(lb->name, $1);
					strcpy(lb->rname, get_a_label());
					add_goto_label(lb);
				}
				else if ( !IS_LAB_DECL(lb) )
				{
					// the label has been used
					parse_error($1, " : redefine label");
					user_exit(1);
				}
				else
				{
					// the label only be reference
					// so, change the decl flag
					lb->is_declaration = 0;
				}
				// label:
				gen_label(lb->rname);
			}
			statement
			{
				PARSE_INFO("statement")
			}
		|	kCASE constant_expression oCOLON 
			{
				symbol	*cs;

				PARSE_INFO("labeled_statement :kCASE constant_expression oCOLON ")
				if ( !IS_CL($2) )
				{
					yyerror("case expression not constant");
					user_exit(1);
				}
				cs = new_symbol();

				strcpy(cs->name, _CASE_NAME);
				// get a label
				strcpy(cs->rname, get_a_label());
				cs->V_I = get_sym_value($2);
				add_case_to_switch(cs);
				// label:
				gen_label(cs->rname);
			}
			statement
			{
				PARSE_INFO("statement")
			}
		|	kDEFAULT oCOLON 
			{
				symbol	*cs;

				PARSE_INFO("labeled_statement :kDEFAULT oCOLON ")
				cs = new_symbol();

				strcpy(cs->name, _DEFAULT_NAME);
				// get a label
				strcpy(cs->rname, get_a_label());
				add_case_to_switch(cs);
				// label:
				gen_label(cs->rname);
			}
			statement
			{
				PARSE_INFO("statement")
			}
		;

expression_statement
		:	expression oSEMI
			{
				PARSE_INFO("expression_statement :expression oSEMI")

				GEN_END_EXPRESS($1)
				
				if ($1)
					del_symbol($1);
			}
					
compound_statement
		:	oLC declaration_list 
			{
				PARSE_INFO("compound_statement :oLC declaration_list ");

				if ( sg_parameter_list )
				// means this compound statement belong to a function, so...
				// of course, if sg_parameter_list is NULL it also maybe a
				// compound statement belong to a function because the parameters
				// is void , heihei....
				{
					add_symbol_list_to_current_symtab(sg_parameter_list);
					sg_parameter_list = NULL;
				}
					
				gen_var_assign_init($2);
			}
			statement_list oRC
			{
				PARSE_INFO("statement_list oRC");
				del_compound_symtab();
			}
		|	oLC 
			{
				PARSE_INFO("compound_statement :oLC ")

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -