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

📄 c.y

📁 C编译器,在VC6.0环境下开发
💻 Y
📖 第 1 页 / 共 5 页
字号:
/*
 * C.Y
 * Grammar file for C Compiler
 *
 * Copyright (c) 2001 by Ren Qi and Lin Ying
 * All Rights Reserved.
 *
 */

%{
#include    "Common.h"
#include    "Debug.h"
#include	"Error.h"
#include	"SymTab.h"
#include	"GBStrTab.h"
#include	"GenCode.h"
#include	"stack.h"
#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <assert.h>

extern  char* yytext;

// globe value 
// used by cSTRING , record current string context
char	g_String[MAX_STR_LEN];
const	char _FUNCTION_NAME[] = "func_%s";
const	char _CASE_NAME[] = "_case_";
const	char _DEFAULT_NAME[] = "_default_";
const	char _STRING_NAME[] = "_string_";

#define		IS_CASE(x)		( !strcmp( (x)->name, _CASE_NAME ) )
#define		IS_DEFAULT(x)	( !strcmp( (x)->name, _DEFAULT_NAME ) )

// label buffer for return
static	char	sg_return_label_buf[LABEL_LEN];

// used by function, to add parameter list to compound statement
static	symbol	*sg_parameter_list = NULL;

#define	PARSE_INFO(x)	StrToDebug(x, "\nIn yyparse() : ", "  --- YACC");

void	set_return_label(char *lb);
void	gen_return_label();
void	gen_return_stmt(symbol *x);
char	*get_string_context(char *s);
int		yylex();

%}

%union
{
// note : NAME_LEN == 32
	char		p_char[32];
	int			num;
	int			ascii;
	symbol		*p_symbol;
}


/* Definition of terminals */
%term	<p_char>idTYPEDEF

%term	kFOR
%term	kWHILE
%term	kIF
%term	kELSE
%term	kCASE
%term	kSWITCH
%term	kDEFAULT
%term	kGOTO
%term	kRETURN
%term	kDO
%term	kBREAK
%term	kCONTINUE
%term	kSIZEOF

%term	kAUTO
%term	kREGISTER
%term	kSTATIC
%term	kEXTERN
%term	kTYPEDEF

%term	kINT
%term	kLONG
%term	kSHORT
%term	kCHAR
%term	kVOID
%term	kFLOAT
%term	kDOUBLE
%term	kSIGNED
%term	kUNSIGNED

%term	kCONST
%term	kVOLATILE

%term   cSTRING					/* STRING CONSTANT */
%term   <num>cINT				/* INT CONSTANT */
%term   <p_char>cREAL			/* REAL CONSTANT */
%term   <p_char>cCHAR			/* CHAR CONSTANT */

%term	oPLUS
%term	oMINUS
%term	oMUL
%term	oDIV
%term	oMOD
%term	oEQUAL
%term	oASSIGN
%term	oUNEQU
%term   oLT
%term   oLE
%term   oGT
%term   oGE
%term   oCOMMA
%term	oSEMI
%term	oCOLON
%term	oQUESTION
%term	oQUOTE
%term	oDOTDOTDOT
%term	oARROW
%term	oLP
%term	oRP
%term	oLB
%term	oRB
%term	oLC
%term	oRC

%term	oBITOR
%term	oBITAND
%term	oBITNOT
%term	oBITXOR
%term	oLFTSHT
%term	oRITSHT

%term	oOR
%term	oAND
%term	oNOT

%term	oADDADD
%term	oSUBSUB

%term	oPLUSASSIGN
%term	oMINUSASSIGN
%term	oMULASSIGN
%term	oDIVASSIGN
%term	oMODASSIGN
%term	oBITORASSIGN
%term	oBITANDASSIGN
%term	oBITNOTASSIGN
%term	oBITXORASSIGN
%term	oLFTSHTASSIGN
%term	oRITSHTASSIGN

%term   <p_char>yNAME

/* preprocessor */
%term	pINCLUDE
%term	pINCLDNAME

/* Definition of nonterminals */

%type	<p_symbol>storage_class_specifier type_specifier type_qualifier
%type	<p_symbol>declaration_specifiers
%type	<p_char>identifier
%type	<p_symbol>direct_declarator	declarator init_declarator init_declarator_list
%type	<p_symbol>declaration declaration_list
%type	<p_symbol>parameter_declaration parameter_list parameter_type_list
%type	<p_symbol>abstract_declarator direct_abstract_declarator
%type	<p_symbol>initializer
%type	<p_symbol>function_definition

%type	<p_symbol>constant primary_expression postfix_expression unary_expression
%type	<p_symbol>cast_expression multiplicative_expression additive_expression
%type	<p_symbol>shift_expression relational_expression equality_expression
%type	<p_symbol>AND_expression exclusive_OR_expression inclusive_OR_expression
%type	<p_symbol>logical_AND_expression logical_OR_expression constant_expression
%type	<p_symbol>conditional_expression assignment_expression
%type	<p_symbol>expression
%type	<p_symbol>argument_expression_list
/*%type	<num>unary_operator*/
/*%type	<num>assignment_operator*/

/*
	// no attribute nonterminals
	translation_unit
	external_declaration

	statement
	labeled_statement
	expression_statement
	statement_list
	iteration_statement
	jump_statement
*/

%start translation_unit

%%

translation_unit
		:	external_declaration
			{
				PARSE_INFO("translation_unit :external_declaration")
			}
		|	translation_unit external_declaration
			{
				PARSE_INFO("translation_unit :translation_unit external_declaration")
			}
		;

external_declaration
		:	function_definition
			{
				PARSE_INFO("external_declaration :function_definition")
			}
		|	declaration
			{
				PARSE_INFO("external_declaration :declaration")
				// gen globe value
				gen_globe_var_list($1);
			}
		|	control_line
			{
				PARSE_INFO("external_declaration :control_line")
			}
		;

function_definition
		:	declaration_specifiers declarator 
			{
				PARSE_INFO("function_definition :declaration_specifiers declarator ")
				assert( IS_FUNCTION($2) );
				unoin_specifier_to_declarator($1, $2);
				del_symbol( $1 );
				check_function_retval($2);
				// $2->args point to parameter list
				// so we can tell the compound statement to link the parameters
				// assign $2->args to sg_parameter_list to tell compound statement
				sg_parameter_list = $2->args;
				// add function definition to sg_function_symtab
				// for function call itself
				// can search in function definition table
				$2 = add_function_def_to_functab($2);
				// for compound statement code genc in code2 files
				open_code2();
				
				// set return label
				set_return_label(get_a_label());
				// create goto label symtab
				create_goto_label_symtab();
			}
			compound_statement
			{
				PARSE_INFO("compound_statement")

				// destory the goto label
				destory_goto_label_symtab();
				// gen return label
				gen_return_label();

				// set func offset
				set_func_offset($2);
				// gen function head
				gen_func_head($2);
				// copy compound statement in code2 to code
				copy_code2_code();
				// add function end
				gen_func_end($2);
				// since compound statement code has copy to code file,
				// then close code2 for next function
				close_code2();
				$$ = $2;
			}
		|	declarator 
			{
				PARSE_INFO("function_definition :declarator ")
				assert( IS_FUNCTION($1) );
				// default the function return value is int
				$1->NOUN = SPEC_INT;
				// $1->args point to parameter list
				// so we can tell the compound statement to link the parameters
				// assign $1->args to sg_parameter_list to tell compound statement
				sg_parameter_list = $1->args;
				// add function definition to sg_function_symtab
				// for function call itself
				// can search in function definition table
				$1 = add_function_def_to_functab($1);
				// for compound statement code genc in code2 files
				open_code2();

				// set return label
				set_return_label(get_a_label());
				// create goto label symtab
				create_goto_label_symtab();
			}
			compound_statement
			{
				PARSE_INFO("compound_statement")

				// destory the goto label
				destory_goto_label_symtab();
				// gen return label
				gen_return_label();

				// set func offset
				set_func_offset($1);
				// gen function head
				gen_func_head($1);
				// copy compound statement in code2 to code
				copy_code2_code();
				// add function end
				gen_func_end($1);
				// since compound statement code has copy to code file,
				// then close code2 for next function
				close_code2();
			}
		;

declaration
		:	declaration_specifiers init_declarator_list oSEMI
			{
				symbol	*decl_lst;

				PARSE_INFO("declaration :declaration_specifiers init_declarator_list oSEMI")
				// at same time check declarator , not be void
				unoin_specifier_to_declarator_list($1, $2);
				del_symbol( $1 );

				// $2 is a list
				// so add all function in the list to function symtab
				decl_lst = $2;
				while ( decl_lst )
				{
					if (IS_FUNCTION(decl_lst))
					{
						// is function declaration
						// so add it to function declaration symtab

						// set decl flag
						decl_lst->is_declaration = 1;

						// only declaration
						// add or only check parameter type 
						// not overwrite parameters type
						add_function_decl_to_functab(decl_lst);
					}
					else if ( IS_LOCAL_VAR(decl_lst) )
					{
						check_var_declarator(decl_lst);
					}

					decl_lst = decl_lst->next;
				}
				add_symbol_list_to_current_symtab($2);
				$$ = $2;
			}
		|	declaration_specifiers oSEMI
			{
				PARSE_INFO("declaration :declaration_specifiers oSEMI")
				// empty declaration
				// so delete it
				del_symbol( $1 );
				yyerror("waring : ignored on left of specifier when no variable is declared");
				$$ = NULL;
			}
		;

declaration_list
		:	declaration
			{
				PARSE_INFO("declaration_list :declaration")
			}
		|	declaration_list declaration
			{
				PARSE_INFO("declaration_list :declaration_list declaration")
				link_symbol_list( $1, $2 );
			}
		;

declaration_specifiers
		:	storage_class_specifier declaration_specifiers
			{
				PARSE_INFO("declaration_specifiers :storage_class_specifier declaration_specifiers")
				union_specifier_symbol( $1, $2 );
				del_symbol( $2 );
			}
		|	storage_class_specifier
			{
				PARSE_INFO("declaration_specifiers :storage_class_specifier")
			}
		|	type_specifier declaration_specifiers
			{
				PARSE_INFO("declaration_specifiers :type_specifier declaration_specifiers")
				union_specifier_symbol( $1, $2 );
				del_symbol( $2 );
			}
		|	type_specifier
			{
				PARSE_INFO("declaration_specifiers :type_specifier")
			}
		|	type_qualifier declaration_specifiers
			{
				PARSE_INFO("declaration_specifiers :type_qualifier declaration_specifiers")
				union_specifier_symbol( $1, $2 );
				del_symbol( $2 );
			}
		|	type_qualifier
			{
				PARSE_INFO("declaration_specifiers :type_qualifier")
			}
		;

storage_class_specifier
		:	kAUTO
			{
				PARSE_INFO("storage_class_specifier :kAUTO")
				$$ = new_symbol();
				$$->SCLASS = SPEC_AUTO;
			}
		|	kREGISTER
			{
				PARSE_INFO("storage_class_specifier :kREGISTER")
				$$ = new_symbol();
				$$->SCLASS = SPEC_REGISTER;
			}
		|	kSTATIC
			{
				PARSE_INFO("storage_class_specifier :kSTATIC")
				$$ = new_symbol();
				$$->IS_STATIC = 1;
			}
		|	kTYPEDEF
			{
				PARSE_INFO("storage_class_specifier :kTYPEDEF")
				$$ = new_symbol();
				$$->SCLASS = SPEC_TYPEDEF;
			}
		|	kEXTERN
			{
				PARSE_INFO("storage_class_specifier :kEXTERN")
				$$ = new_symbol();
				$$->IS_EXTERN = 1;
			}
		;

type_specifier
		:	kINT
			{
				PARSE_INFO("type_specifier :kINT")
				$$ = new_symbol();
				$$->NOUN = SPEC_INT;
			}
		|	kLONG
			{
				PARSE_INFO("type_specifier :kLONG")
				$$ = new_symbol();
				$$->NOUN = SPEC_INT;
				$$->IS_LONG = 1;
			}
		|	kSHORT
			{
				PARSE_INFO("type_specifier :kSHORT")
				$$ = new_symbol();
				$$->NOUN = SPEC_INT;
			}
		|	kCHAR
			{
				PARSE_INFO("type_specifier :kCHAR")
				$$ = new_symbol();
				$$->NOUN = SPEC_CHAR;
			}
		|	kVOID
			{
				PARSE_INFO("type_specifier :kVOID")
				$$ = new_symbol();
				$$->NOUN = SPEC_VOID;
			}
		|	kFLOAT
			{
				PARSE_INFO("type_specifier :kFLOAT")
				$$ = new_symbol();
				$$->NOUN = SPEC_FLOAT;
			}
		|	kDOUBLE
			{
				PARSE_INFO("type_specifier :kDOUBLE")
				$$ = new_symbol();
				$$->NOUN = SPEC_DOUBLE;
			}
		|	kSIGNED
			{
				PARSE_INFO("type_specifier :kSIGNED")
				$$ = new_symbol();
				$$->NOUN = SPEC_INT;
			}
		|	kUNSIGNED
			{
				PARSE_INFO("type_specifier :kUNSIGNED")
				$$ = new_symbol();
				$$->NOUN = SPEC_INT;
				$$->IS_UNSIGNED = 1;
			}
		|	idTYPEDEF
			{
				symbol	*tmp;

				PARSE_INFO("type_specifier :idTYPEDEF")
				tmp = find_symtab_typedef( $1 );
				assert( tmp );
				$$ = new_symbol_from_typedef( tmp );
				assert( $$ );
			}
		;
		
type_qualifier
		:	kCONST
			{
				PARSE_INFO("type_qualifier :kCONST")
				$$ = new_symbol();
				$$->SCLASS = SPEC_CONSTANT;
			}
		|	kVOLATILE
			{
				PARSE_INFO("type_qualifier :kVOLATILE")
				$$ = new_symbol();
				// ingore volatile attribute
			}
		;

init_declarator_list
		:	init_declarator
			{
				PARSE_INFO("init_declarator_list :init_declarator")
			}
		|	init_declarator_list oCOMMA init_declarator
			{
				PARSE_INFO("init_declarator_list :init_declarator_list oCOMMA init_declarator")
				link_symbol_list($1, $3);
			}
		;

init_declarator
		:	declarator
			{
				PARSE_INFO("init_declarator :declarator")
				// check array element
				// for globe or local var, the array element number could not be zero
				if ( IS_ARRAY($1) && !$1->num_ele )
				{
					yyerror("Array must be declarated with element number");
					user_exit(1);
				}
			}
		|	declarator oASSIGN initializer
			{
				PARSE_INFO("init_declarator :declarator oASSIGN initializer")
				if ( IS_FUNCTION($1) )
				{
					yyerror("initialization of a function");
					user_exit(1);
				}
				if ( !IS_CL($3) )
				{
					yyerror("initializer is not a constant");
					user_exit(1);
				}
				if ( IS_ARRAY($1) )
				{
					yyerror("array initialization unsupport");
					user_exit(1);
				}
				$1->args = $3;
				// set assign flag
				$1->is_assign = 1;
			}
		;

/*	// cast type 类型转换, skip

⌨️ 快捷键说明

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