260 likes | 835 Views
C_Minus Compiler Project. What do we support?. 数据类型: Integer, char, float,void 数据类型:数组,函数 算术运算符:+、-、*、/; 关系运算符:>、<、>=、<=、==、!=; 逻辑运算符:与、或、非; 语句结构:条件句、循环语句、说明语句、赋值语句、 转移语句等。. What do we generate?. P-Code 数学运算 : adi, adf, subi, subf, multi, multf, divi, divf
E N D
What do we support? 数据类型: Integer, char, float,void 数据类型:数组,函数 算术运算符:+、-、*、/; 关系运算符:>、<、>=、<=、==、!=; 逻辑运算符:与、或、非; 语句结构:条件句、循环语句、说明语句、赋值语句、 转移语句等。
What do we generate? P-Code 数学运算 :adi, adf, subi, subf, multi, multf, divi, divf 关系运算 :grt, les, leq, geq, equ, neq 流程控制 :fjp, ujp, lab 函数 :mst, cup, ret, ent load & store :lodi, lodf, lodc, lodci, lodcf, lodcc, lda, sto, stn
开始 词法分析 语法分析 语法树 代码生成 类型检查 建立符号表 符号表 结束 How do we do it?
C_Minus的语法树(数据结构1) enum NodeKind {StmtK,ExpK,DeclK}; enum StmtKind {IfK,WhileK,ForK,ReturnK,CompoundK}; enum ExpKind {TypeK,OpK,NotK,ArrayK,ConstK,IdK,CallK}; enum DeclKind {VarDeclK,FuncDeclK,FuncDefK,ParamK};
C_Minus的语法树(数据结构2) struct TreeNode{ struct TreeNode * child[MAXCHILDREN]; struct TreeNode * sibling; int lineno; NodeKind nodekind; union {StmtKind stmt; ExpKind exp; DeclKind decl; } kind; union { TokenType op; int vali; float valf; char valch; char *name; ExpType vartype; } attr; ExpType type; /* for type checking of exps */ VarKind varK; };
While: StmtK Test: ExpK Body: StmtK If: StmtK Test: ExpK Body: stmtK Else: stmtK C_Minus 的语法树(语句1) If statement While statement
For: stmtK Initial: ExpK Test:ExpK Operation:ExpK Body:StmtK Return:StmtK Body : StmtK C_Minus 的语法树(语句2) For statement Return statement
Compound:StmtK StmtK/DeclK StmtK/DeclK C_Minus 的语法树(语句3) Compound statement
ArrayK ExpK CallK Name:IdK Arg:ExpK Arg:ExpK C_Minus 的语法树(表达式1) 数组 函数
FuncDeclK Return Type: TypeK Name:IdK Param_list VarDeclK TypeK Var-list C_Minus 的语法树(声明1) 变量声明 函数声明
FuncDeclK Return Type: TypeK Name:IdK Param_list CompoundK C_Minus 的语法树(声明2) 函数定义
Symbol Table 示例程序: fn( ){ int m; if ( ){int n; …} else {int I; …} } int u; main( ){ char c; … }
Fn , u m c n i Symbol Table 第一层:函数和全局变量 第2,3,4…层:局部变量
Symbol Table的数据结构 struct SymTab{ BucketList * hashTable[SIZE]; SymTab * child; //指向下一层的符号表 SymTab * parent; //指向上层的符号表 SymTab * sibling; //指向同层的符号表 };
Bucklist 的数据结构 struct BucketList{ char * name; char * fname; LineList * lines; entryType entrytype; int memloc; int size; paramType * param; struct BucketList * next; };
Symbol Table的接口函数(1) int st_insert( char * name, int lineno, ExpType type, ExpKind kind, int size = -1); int st_insert( char * name, int lineno, ExpType type, TreeNode * params); int st_lookup ( char * , Result &); int st_funclookup(char *, ExpType, TreeNode * params); int st_funclookup(char *, Result &);
Symbol Table的接口函数(2) int st_setLoc(char * name ,int memloc ); void st_newBuck(); void st_delBuck(); void st_reset(); void st_inFunc(char * name); void st_outFunc(); void printSymTab(FILE * listing);
Type Checking的实现 struct TreeNode{ ………………. ………………. ExpType type; /* for type checking of exps */ VarKind varK; /* Array/Func/Norm */ }; 通过对树的后序遍历实现。首先计算一个结点的儿子的类型,存放在结点的type成员变量中,然后根据结点类型进行类型检查。
示例 • (1) int x[10]; • Fn(x); x.varK = Array x.type = Integer • X[1] = 9; x.varK = Norm x.type = Integer • int Fn( ); • x = Fn( ); Fn.varK = Func Fn.type = Integer
运算规则 类型计算的规则有以下几条: IdK,ArrayK,ConstK的type由建立符号表的过程中赋值 算术运算符的type等于两端的类型(允许int到float型的转换); 逻辑运算符的type为Boolean; 类型不匹配的情况有以下几种: 操作符的两端类型不一致(int和float可以转换除外); if,for,while语句的条件不是Boolean类型; Return type和函数定义不一致;
Control Macros • /* set NO_PARSE to TRUE to get a scanner-only compiler */ • #define NO_PARSE FALSE • /* set NO_ANALYZE to TRUE to get a parser-only compiler */ • #define NO_ANALYZE FALSE • /* set NO_CODE to TRUE to get a compiler that does not • * generate code • */ • #define NO_CODE FALSE
Some Global Variables? • int TraceScan; • int TraceParse; • int TraceAnalyze; • int TraceCode;
Important Functions int getToken(); /*取得一个Token*/ void yyerror(const char * message); /*打印错误信息*/ void emitComment(char *c); /*在P-Code中打印注释*/ void emitCode(char *s); /*输出一条P-Code*/ void codeGen(TreeNode * syntaxTree, char * codefile); /*代码生成部分 的接口*/
Code Generate • 执行代码生成任务的函数是: static void cGen( TreeNode * tree) • 它由根结点遍历语法树每个节点,并对每个结点递归地生成P-code。 • 先对语法树的结点分成三大类:语句结点(StmtK),表达式结点(ExpK),声明结点(DeclK),然后逐个用对应函数进行处理。三个函数分别是: genStmt(tree); genExp(tree, TRUE); genDecl(tree);
Code Generate switch (tree->nodekind) { case StmtK: genStmt(tree); break; case ExpK: genExp(tree, TRUE); //set to TRUE for destructive store break; case DeclK: genDecl(tree); break; } cGen(tree->sibling);