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

📄 checker.y

📁 一个用C++实现的C的Compiler。 代码风格良好。 原作者自己写了这个编译器
💻 Y
字号:
%{

#include <string>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <vector>
#include <list>

#include "CHKsupport.cpp"

using namespace std;

struct __yystype {
	int intval;
	list <int> int_list;
	string strval;
	list <TSymbolListVariableEntry> Ventry_list;
	TSymbolListVariableEntry Ventry;
	TSymbolListTypeEntry Tentry;
	TSymbolListFunctionEntry Fentry;
};

extern int PROGRAM_EOF;
extern int PROGRAM_LineNumber;
extern char* PROGRAM_FileName;

#define YYSTYPE __yystype

int yyerror(string msg)
{
	Tmsg tmpmsg;
	tmpmsg.lineno = PROGRAM_LineNumber;
	if (PROGRAM_EOF)
	{
		tmpmsg.msgtxt = "1: " + msg + " before *end of file*";
	}
	else
	{
		tmpmsg.msgtxt = "1: " + msg + " before \"" + yytext + "\"";
	}
	tmpmsg.sourcecount = error_msgs.size();
	error_msgs.push_back(tmpmsg);
	return 0;
}

int yylex();

int InFuncLevel = -1;
int InLoopCount = 0;
int PROGRAM_func_ret;

%}

%token NIL
%token <intval> IDENT 
%token <intval> TRUE FALSE INT SYMNULL CHAR DOUBLE 
%token <strval> STRING
%token IF ELSE FOR WHILE BREAK RETURN
%token PRINT READINT READDBL READLINE NEW
%token LPAREN RPAREN LBRACKET RBRACKET LSQUARE RSQUARE DOT COMMA SEMICOLON
%token TYPEINT TYPEDOUBLE TYPEBOOL TYPESTRING TYPEVOID TYPECHAR CLASS EXTENDS THIS
%token STRUCT CONST 
%token READREG WRITEREG ASM

%right LET
%left LOGICOR
%left LOGICAND
%left LES GTR LEQ GEQ EQL NEQ
%left OR
%left CALCNOT
%left AND XOR SHL SHR
%left ADD MINUS 
%left MUL DIV MOD
%left STAR REF FORCE
%left UMINUS NOT 

%left DOT LSQUARE RSQUARE
%left PPLUS MMINUS
%left LPAREN RPAREN

%type <intval> basictype 
%type <Ventry> expr arraysub call  
%type <Ventry_list> actuals exprs types
%type <int_list> varlist
%type <Ventry_list> funcvars formals
%type <Ventry> funcvar
%type <Tentry> fieldblock fields
%type <Fentry> funcdecl funcdef


%nonassoc IFX
%nonassoc ELSE

%start program

%%
program		:	decls											{	}
			;

decls		:	decls decl										{	}
			|	decl											{	}
			;

decl		:	vardecl											{	CheckMakeNewVarDecls($1.intval, $1.int_list);		}
			|	funcdef											{	CheckMakeNewFuncDef($1);							}
			|	funcdecl										{	CheckMakeNewFuncDecl($1);							}
			|	structdef										{	}
			|	error											{	}
			;

varlist		:	IDENT											{	$$.clear();	$$.push_back($1);						}
			|	varlist COMMA IDENT								{	$$ = $1; $$.push_back($3);							}
			;

vardecl		:	var SEMICOLON									{	$$ = $1;											}
			|	var COMMA varlist SEMICOLON						{	$$.intval = $1.intval;
																	$$.int_list = $3;
																	$$.int_list.push_front(*$1.int_list.begin());		}
			|	CONST type IDENT LET expr SEMICOLON				{	CheckAddConstVariable(SymbolListTypeADDArrayList($2.intval, $2.int_list), $3, $5);
																														}
			;

arraysub	:	LSQUARE expr RSQUARE							{	$$ = $2;											}
			;

var			:	type IDENT										{	$$.intval = SymbolListTypeADDArrayList($1.intval, $1.int_list);
																	$$.int_list.clear(); $$.int_list.push_back($2);		}
			;

types		:	type											{	$$.clear(); 
																	TSymbolListVariableEntry Ventry;
																	Ventry.var_type = SymbolListTypeADDArrayList($1.intval, $1.int_list);
																	$$.push_back(Ventry);								}
			|	types COMMA type								{	$$ = $1;
																	TSymbolListVariableEntry Ventry;
																	Ventry.var_type = SymbolListTypeADDArrayList($3.intval, $3.int_list);
																	$$.push_back(Ventry);								}
			;

type		:	basictype										{	$$.intval = $1; $$.int_list.clear();				}
			|	type MUL										{	$$.intval = SymbolListTypeADDArrayList($1.intval, $1.int_list);	
																	$$.intval = SymbolListTypeADDStar($$.intval);
																	$$.int_list.clear();								}
			|	type arraysub									{	$$.intval = $1.intval; $$.int_list = $1.int_list;
																	$$.int_list.push_back(CheckArraysubToConst($2));	}
			|	type LPAREN RPAREN LPAREN types RPAREN			{	$$.intval = SymbolListMakeFunctionType(SymbolListTypeADDArrayList($1.intval, $1.int_list),
																						$5);
																	$$.int_list.clear();								}
			;

basictype	:	TYPEINT											{	$$ = var_type_int;									}
			|	TYPECHAR										{	$$ = var_type_char;									}
			|	TYPEVOID										{	$$ = var_type_void;									}
			|	STRUCT IDENT									{	if (SymbolListType[$2].total_size == type_undefined )
																	{
																		errormsg(4, PROGRAM_LineNumber, IDHash_int2ID($2));
																		$$ = var_type_notfound;
																	}
																	else
																	{
																		$$ = $2;
																	}
																														}						
			;

funcdecl	:	type IDENT LPAREN formals RPAREN SEMICOLON		{	TSymbolListFunctionEntry Fentry;
																	Fentry.defined = 0; 
																	Fentry.id = $2; Fentry.arg_list = $4; 
																	Fentry.func_type = SymbolListMakeFunctionType(SymbolListTypeADDArrayList($1.intval, $1.int_list), $4);
																	Fentry.defined_line = PROGRAM_LineNumber; Fentry.valid = 1;
																	$$ = Fentry;										}
			;

formals		:	funcvars										{	$$ = $1;											}
			|	/* epsilon */									{	$$.clear();											}
			;

funcvars	:	funcvar											{	$$.clear(); $$.push_back($1);						}
			|	funcvars COMMA funcvar							{	$$ = $1; $$.push_back($3);							}
			;

funcvar		:	var												{	$$.var_type = $1.intval; $$.defined_line = PROGRAM_LineNumber;
																	$$.id = *$1.int_list.begin(); 
																	$$.const_sign = 0; $$.lvalue = 1;					}
			;

funcdef		:	type IDENT LPAREN formals RPAREN				{	TSymbolListFunctionEntry Fentry;
																	Fentry.id = $2; Fentry.arg_list = $4; 
																	Fentry.func_type = SymbolListMakeFunctionType(SymbolListTypeADDArrayList($1.intval, $1.int_list), $4);
																	Fentry.defined_line = PROGRAM_LineNumber; Fentry.valid = 1;
																	CheckMakeNewFuncDecl(Fentry);						
																	$$ = Fentry;

																	PROGRAM_func_ret = SymbolListTypeADDArrayList($1.intval, $1.int_list);
																	SymbolListIncLevel();
																	for (list <TSymbolListVariableEntry> :: iterator p = $4.begin(); p != $4.end(); p ++)
																	{
																		CheckMakeNewVarDecl(*p);
																	}
																	SymbolListNowLevel --;								}
					stmtblock									{	$$ = $6.Fentry;										}
			;

structdef	:	STRUCT IDENT									{	$$.intval = PROGRAM_LineNumber;						}
					fieldblock SEMICOLON						{	CheckMakeNewStructDef($2, $4, $3.intval);			}
			;

fieldblock	:	LBRACKET fields RBRACKET						{	$$ = $2;											}
			|	LBRACKET RBRACKET								{	SymbolListMakeNewStruct($$);						}
			;

fields		:	vardecl											{	SymbolListMakeNewStruct($$);
																	AddVars2Field($$, $1.intval, $1.int_list);			}
			|	fields vardecl									{	$$ = $1;
																	AddVars2Field($$, $2.intval, $2.int_list);			}
			;


stmtblock	:	LBRACKET 										{	SymbolListIncLevel();								}
					stmtstar RBRACKET							{	SymbolListDecLevel();								}
			;

stmtstar	:	stmts											{	}
			|	/* epsilon */									{	}
			;

stmts		:	stmts stmt										{	}
			|	stmt											{	}
			;

asmstar	:	asms												{	}
			|	/* epsilon */									{	}
			;

asms		:	asms asm										{	}
			|	asm												{	}
			;

asm			:	ASM LPAREN INT RPAREN SEMICOLON					{	}
			|	ASM LPAREN STRING RPAREN SEMICOLON				{	CheckASM(0, $3);									}
			|	ASM LPAREN STRING COMMA STRING RPAREN SEMICOLON	{	CheckASM(1, $3, $5);								}
			|	ASM LPAREN STRING COMMA STRING COMMA STRING RPAREN SEMICOLON
																{	CheckASM(2, $3, $5, $7);							}
			|	ASM LPAREN STRING COMMA STRING COMMA STRING COMMA STRING RPAREN SEMICOLON
																{	CheckASM(3, $3, $5, $7, $9);						}
			|	READREG LPAREN STRING COMMA IDENT RPAREN SEMICOLON
																{	CheckRegOperation(REG_OP_READ, $3, $5);				}
			|	WRITEREG LPAREN STRING COMMA IDENT RPAREN SEMICOLON		
																{	CheckRegOperation(REG_OP_WRITE, $3, $5);			}
			;

stmt		:	stmtblock										{	}
			|	vardecl											{	CheckMakeNewVarDecls($1.intval, $1.int_list);		}
			|	simplestmt SEMICOLON							{	}
			|	ifstmt											{	}
			|	whilestmt										{	}
			|	forstmt											{	}
			|	breakstmt SEMICOLON								{	}
			|	returnstmt SEMICOLON							{	}
			|	ASM LBRACKET asmstar RBRACKET SEMICOLON			{	}
			|	error											{	}
			;

simplestmt	:	expr											{	}
			|	/* epsilon */									{	}
			;

call		:	expr LPAREN actuals RPAREN						{	CheckCall($1, $3, $$);								}
			;

actuals		:	exprs											{	$$ = $1;											}
			|	/* epsilon */									{	$$.clear();											}
			;

forstmt		:	FOR LPAREN simplestmt SEMICOLON expr			{	CheckCondExpr($5);									}
					SEMICOLON simplestmt RPAREN					{	InLoopCount ++;										}
					stmt										{	InLoopCount --;										}
			;

whilestmt	:	WHILE LPAREN expr RPAREN						{	CheckCondExpr($3); InLoopCount ++;					}
					stmt										{	InLoopCount --;										}
			;

ifpart		:	IF LPAREN expr RPAREN							{	CheckCondExpr($3);									}

ifstmt		:	ifpart stmt %prec IFX							{}
			|	ifpart stmt ELSE stmt							{}
			;

returnstmt	:	RETURN											{	if (PROGRAM_func_ret != var_type_void)
																		errormsg(21, PROGRAM_LineNumber, "void", __vartype2str(PROGRAM_func_ret));
																														}
			|	RETURN expr										{	if (!CheckCastCompatibility(PROGRAM_func_ret, $2))
																		errormsg(21, PROGRAM_LineNumber, __vartype2str($2), __vartype2str(PROGRAM_func_ret));
																														}
			;

breakstmt	:	BREAK											{	if (InLoopCount == 0) errormsg(30, PROGRAM_LineNumber);
																														}
			;

exprs		:	expr											{	$$.clear(); $$.push_back($1);						}
			|	exprs COMMA expr								{	$$ = $1; $$.push_back($3);							}
			;

intblock	:	ints GTR										{	}
			|	LES GTR											{	}
			;
	
ints		:	LES INT											{	}
			|	ints COMMA INT									{	}
			;

expr		:	IDENT											{	GetVariable($1, $$);								}
			|	LPAREN type RPAREN expr	%prec FORCE				{	ForceCast($4, SymbolListTypeADDArrayList($2.intval, $2.int_list), $$);	}
			|	expr DOT IDENT									{	GetFieldVariable($1, $3, $$);						}
			|	expr arraysub									{	CheckFindArrayAddr($1, $2, $$);						}
			|	MUL expr %prec STAR								{	CheckAddPtr($2, $$);								}
			|	INT												{	MakeConstantIntExpr($$, $1, var_type_int);			}
			|	SYMNULL											{	MakeConstantIntExpr($$, 0, var_type_NULL);			}
			|	STRING											{	MakeConstantIntExpr($$, 1, SymbolListTypeADDStar(var_type_char));		}
			|	TRUE											{	MakeConstantIntExpr($$, 1, var_type_int);			}
			|	FALSE											{	MakeConstantIntExpr($$, 0, var_type_int);			}
			|	CHAR											{	MakeConstantIntExpr($$, $1, var_type_char);			}
			|	intblock										{	MakeConstantIntExpr($$, 1, SymbolListTypeADDStar(var_type_int));		}
			|	call											{	$$ = $1;											}
			|	expr LET expr									{	CheckMakeLet ($1, $3, $$);							}
			|	LPAREN expr RPAREN								{	$$ = $2;											}
			|	AND expr %prec REF								{	CheckAddRef($2, $$);								}
			|	expr LES expr									{	CheckExprBinaryRelational($1, $3, SRC_relational_LES, $$);				}
			|	expr GTR expr									{	CheckExprBinaryRelational($1, $3, SRC_relational_GTR, $$);				}
			|	expr LEQ expr									{	CheckExprBinaryRelational($1, $3, SRC_relational_LEQ, $$);				}
			|	expr GEQ expr									{	CheckExprBinaryRelational($1, $3, SRC_relational_GEQ, $$);				}
			|	expr EQL expr									{	CheckExprBinaryRelational($1, $3, SRC_relational_EQL, $$);				}
			|	expr NEQ expr									{	CheckExprBinaryRelational($1, $3, SRC_relational_NEQ, $$);				}
			|	expr LOGICAND expr								{	CheckExprBinaryRelational($1, $3, SRC_logical_AND, $$);					}
			|	expr LOGICOR expr								{	CheckExprBinaryRelational($1, $3, SRC_logical_OR, $$);					}
			|	NOT expr										{	CheckExprUnaryLogical($2, SRC_logical_NOT, $$);							}
			|	CALCNOT expr									{	CheckExprUnaryCalculational($2, SRC_calculational_NOT, $$);				}
			|	expr ADD expr									{	CheckExprBinaryCalculational($1, $3, SRC_calculational_ADD, $$);		}
			|	expr MINUS expr									{	CheckExprBinaryCalculational($1, $3, SRC_calculational_MINUS, $$);		}
			|	expr MUL expr									{	CheckExprBinaryCalculational($1, $3, SRC_calculational_MUL, $$);		}
			|	expr DIV expr									{	CheckExprBinaryCalculational($1, $3, SRC_calculational_DIV, $$);		}
			|	expr MOD expr									{	CheckExprBinaryCalculational($1, $3, SRC_calculational_MOD, $$);		}
			|	expr AND expr									{	CheckExprBinaryCalculational($1, $3, SRC_calculational_AND, $$);		}
			|	expr OR expr									{	CheckExprBinaryCalculational($1, $3, SRC_calculational_OR, $$);			}
			|	expr XOR expr									{	CheckExprBinaryCalculational($1, $3, SRC_calculational_XOR, $$);		}
			|	expr SHL expr									{	CheckExprBinaryCalculational($1, $3, SRC_calculational_SHL, $$);		}
			|	expr SHR expr									{	CheckExprBinaryCalculational($1, $3, SRC_calculational_SHR, $$);		}
			|	MINUS expr %prec UMINUS							{	CheckExprUnaryCalculational($2, SRC_calculational_MINUS, $$);			}
			|	expr PPLUS										{	CheckExprSelfAction($1, $$, SRC_calculational_ADD);						}
			|	expr MMINUS										{	CheckExprSelfAction($1, $$, SRC_calculational_MINUS);					}
			;

%%

int main(int argc, char* argv[])
{
	int filecnt = -1;
	for (int i = 1; i < argc; i++)
	{
		if (filecnt == -1 && argv[i][0] != '-')
		{
			filecnt = i;
		}
	}

	if (filecnt == -1)
	{
		printf("checker: no input file\n");
		return 1;
	}

	yyin = fopen(argv[filecnt], "r");
	PROGRAM_FileName = argv[filecnt];
	if (yyin == NULL)
	{
		printf("checker: %s: No such file\n", argv[filecnt]);
		return 1;
	}
	yyparse();
	if (errormsg_print() && chk_func_defined())
	{
		return 0;
	}
	else
	{
		return 1;
	}
}

⌨️ 快捷键说明

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