1、编译原理课程设计报告课题名称: C-语言编译器设计 提交文档学生姓名: 李杰 提交文档学生学号: 0743041240 同组 成 员 名 单: 无 指导 教 师 姓 名: 金军 指导教师评阅成绩: 指导教师评阅意见: . . 提交报告时间: 2010 年 6 月 10 日STARTINNUMdigitINIDletterwhite spaceINASSIN , = = != = ; , ( ) /* */3、其他标记是 ID 和 NUM,通过下列正则表达式定义:ID = letter letter* NUM = digit digit* letter = a|z|A|Z digit = 0|9
2、4、空格由空白、换行符和制表符组成。空格通常被忽略,除了它必须分开 ID、NUM 关键字。5. 注释用通常的 C 语言符号 / * . . . * /围起来。注释可以放在任何空白出现的位置( 即注释不能放在标记内)上,且可以超过一行。注释不能嵌套各单词的状态转换图(DFA 图如下)词法结构见文件“globals.h“中。(3)分析器:分析树结构见文件“globals.h“中。C的 BNF 语法如下:(4) 代码设 计说明:程序结构:语法分析函数 parse 通过调用词法分析函数 getToken 实现语法分析。文件和函数的设计说明:文件 main.c 包含相应头文件,及 main 函数的实现;
3、文件golbals.h 包含符号表和分析数的数据结构及在其它文件中使用的变量;文件 util.h 和util.c 实现与词法分析和语法分析输出相关的函数 printToken 和 printTree,以及分析树节点初始化相关的函数 newStmtNode,newExpNode(Expkind)和 copyString;文件 scan.h 和scan.c 实现词法分析,主要函数为 getToken;文件 parse.h 和 parse.c 实现语法分析,函数为与文法规则对应的函数。关键数据结构3. 程序代码实现文件 main.c 代码如下:/实验建立 C-编译器。只含有 scanner 和 pa
4、rser 部分。#include“globals.h“#include “util.h“#include “scan.h“#include “parse.h“/全局变量和标志int lineno=0;FILE*source;FILE*listing;FILE*code;int EchoSource=TRUE;int TraceScan=TRUE;int TraceParse=TRUE;int Error=FALSE;int main(int argc,char*argv)TreeNode*syntaxTree;char pgm120; /代码文件名if(argc!=2)fprintf(stde
5、rr,“usage:%s C:source.c n“,argv0);return -1;strcpy(pgm,argv1);if (strchr(pgm,.)=NULL) strcat(pgm,“.tny“); source=fopen(pgm,“r“);if(source=NULL)fprintf(stderr,“file %s not found n“,pgm);return -1;listing=stdout;fprintf(listing,“n C-COMPILATION: %sn“,pgm);/ while (getToken()!=ENDFILE);EchoSource=FALSE
6、;TraceScan=FALSE;syntaxTree=parse();if(TraceParse) fprintf(listing,“nSyntax treen:“);printTree(syntaxTree);fclose(source);return 0;文件 globals.h 代码如下:#ifndef _GLOBALS_H_#define _GLOBALS_H_#include #include #include #include #ifndef FALSE#define FALSE 0#endif#ifndef TRUE#define TRUE 1#endif#define MAX
7、RESERVED 6typedef enumENDFILE,ERROR,IF,ELSE,INT,RETURN,VOID,WHILE, /关键字ID,NUM,ASSIGN,EQ,LT,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,SEMI,BT,LQ,BQ,UEQ,DOU,LZGH,RZGH,LDGH,RDGH,/特殊字符 TokenType;extern FILE* source ;extern FILE* listing;extern FILE* code;extern int lineno;/语法分析树typedef enum Stmtk,Expk Nodekin
8、d;typedef enum IfK,ElseK,IntK,ReturnK,VoidK,WhileK,AssignK,HanK,HanshutiK Stmtkind;typedef enum Opk,Constk,Idk,Vark Expkind;typedef enum Void,Integer,Boolean ExpType;#define MAXCHILDREN 3typedef struct treeNodestruct treeNode*childMAXCHILDREN;struct treeNode*sibling;int lineno;Nodekind nodekind;unio
9、n Stmtkind stmt; Expkind exp; kind;union TokenType op;int val;char*name; attr;ExpType type; TreeNode;extern int EchoSource;extern int TraceScan;extern int TraceParse;extern int Error;#endif文件 util.h 代码如下:#ifndef _UTIL_H_#define _UTIL_H_void printToken( TokenType, const char*) ;/为分析树TreeNode*newStmtN
10、ode(Stmtkind);TreeNode*newExpNode(Expkind);char*copyString( char*);void printTree( TreeNode*);#endif文件 util.c 代码如下:#include “globals.h“#include “util.h“void printToken( TokenType token, const char* tokenString ) switch (token) case IF:case INT:case ELSE:case RETURN:case VOID:case WHILE:fprintf(listi
11、ng,“reserved word: %sn“,tokenString);break;case ASSIGN: fprintf(listing,“=n“); break;case LT: fprintf(listing,“n“); break;case LQ: fprintf(listing,“=n“); break;case UEQ: fprintf(listing,“!=n“); break;case DOU: fprintf(listing,“,n“); break;case LZGH: fprintf(listing,“n“); break;case RZGH: fprintf(lis
12、ting,“n“); break;case LDGH: fprintf(listing,“n“); break;case RDGH: fprintf(listing,“n“); break;case ENDFILE: fprintf(listing,“EOFn“); break;case NUM:fprintf(listing,“NUM, val= %sn“,tokenString);break;case ID:fprintf(listing,“ID, name= %sn“,tokenString);break;case ERROR:fprintf(listing,“ERROR: %sn“,t
13、okenString);break;default: /* should never happen */fprintf(listing,“Unknown token: %dn“,token);TreeNode*newStmtNode(Stmtkind kind)TreeNode*p=(TreeNode*)malloc(sizeof(TreeNode);int k;if(p=NULL) fprintf(listing,“out of memory error at line %dn“,lineno); elsefor(k=0;kchildk=NULL; p-sibling=NULL;p-node
14、kind=Stmtk;p-kind.stmt=kind;p-lineno=lineno;return p;TreeNode*newExpNode(Expkind kind)TreeNode*p=(TreeNode*)malloc(sizeof(TreeNode);int k;if(p=NULL) fprintf(listing,“out of memory error at line %dn“,lineno); elsefor(k=0;kchildk=NULL; p-sibling=NULL;p-nodekind=Expk;p-kind.exp=kind;p-lineno=lineno;p-t
15、ype=Void;return p;char*copyString( char*s)int i;char*p;if(s=NULL) return NULL; i=strlen(s)+1;p=malloc(i);if(p=NULL) fprintf(listing,“out of memory error at line %dn“,lineno); else strcpy(p,s); return p;static indentno=0;#define INDENT indentno+=2#define UNINDENT indentno-=2static void printSpace(voi
16、d)int k;for(k=0;knodekind=Stmtk)switch (t-kind.stmt)case IfK:fprintf(listing,“Ifn“);break;case IntK:fprintf(listing,“Intn“);break;case VoidK:fprintf(listing,“Voidn“);break;case ReturnK:fprintf(listing,“Returnn“);break;case WhileK:fprintf(listing,“Whilen“);break;case AssignK:fprintf(listing,“Assign t
17、o: %sn“,t-attr.name);break;case HanK:fprintf(listing,“Hanshun“);break;case HanshutiK:fprintf(listing,“Hanshutin“);break;default:fprintf(listing,“Unknown stmt kindn“);break;else if(t-nodekind=Expk) switch (t-kind.exp)case Opk:fprintf(listing,“Op:“);printToken(t-attr.op,“0“);break;case Constk:fprintf(
18、listing,“Const: %dn“,t-attr.val);break;case Idk:fprintf(listing,“Id: %sn“,t-attr.name);break;case Vark:fprintf(listing,“Vark: %dn“,t-attr.val);break;default:fprintf(listing,“Unknown exp kindn“);break;else fprintf(listing,“Unknown exp kindn“); for(i=0;ichildi); t=t-sibling;UNINDENT;文件 scan.h 代码如下:#if
19、ndef _SCAN_H_#define _SCAN_H_#define MAXTOKENLEN 40extern char tokenStringMAXTOKENLEN+1;TokenType getToken(void);#endif文件 scan.c 代码如下:#include“globals.h“#include “util.h“#include “scan.h“/DFA 中的状 态typedef enumSTART,INID,INNUM,DONE,INASSIGN,INCOMMENT,ZHU,ZZHU StateType;char tokenStringMAXTOKENLEN+1;#
20、define BUFLEN 256 /代码文件的行数static char lineBufBUFLEN; /保存当前行static int linepos=0; /lineBuf 中的当前位置static int bufsize=0; /buffer 串的大小static int EOF_Flag=FALSE;/获取字符从 lineBufBUFLEN中static int getNextChar(void) if(!(linepos:1 、) f1=1;state=INASSIGN; else if(c= “); fprintf(listing,“Syntax error at line %d
21、: %sn“,lineno,me); Error=TRUE;static void match(TokenType ex)if(token=ex) token=getToken();else syntaxError(“unexoected token-“);printToken(token, tokenString);fprintf(listing,“ “); static TreeNode*program() TreeNode* t=declaration();TreeNode* p=t; while(token!=INT)printToken(token, tokenString);tok
22、en=getToken();while(token=INT)|(token=VOID) TreeNode* q;q=declaration();if(q!=NULL)if(t=NULL) t=p=q;else p-sibling=q;p=q;return t;static TreeNode*declaration(void)TreeNode* t=NULL;if(token=INT) t=newStmtNode(IntK);match(INT);if(token=VOID) t=newStmtNode(VoidK);match(VOID);if(t!=NULL)p=newExpNode(Idk
23、); p-attr.name=copyString(tokenString); t-child0=p;match(ID); if(token=LPAREN) else if(token=LZGH)|(token=SEMI) t-child1=var_declaration(); else syntaxError(“unexpected token-“);printToken(token, tokenString);return t;static TreeNode*func_declaration(void) TreeNode* t=newStmtNode(HanK);match(LPAREN)
24、;t-child0=params(); /*get the param list*/match(RPAREN);t-child1=compound_stmt();return t;static TreeNode*var_declaration(void) TreeNode* t=NULL;if(token=LZGH) match(LZGH);t=newExpNode(Vark);if(t!=NULL) else syntaxError(“unexpected token-“);printToken(token, tokenString);match(NUM);match(RZGH);match
25、(SEMI); else match(SEMI); /将;号辨别放在 declaration 中return t;static TreeNode*params(void) TreeNode* t=NULL;if(token=VOID) t=newStmtNode(VoidK);match(VOID);else if(token=INT) t=param_list();else syntaxError(“unexpected token-“);printToken(token, tokenString);return t;static TreeNode*param_list(void) Tree
26、Node* t=param();TreeNode* p=t; while(token=DOU) TreeNode*q=NULL;match(DOU);q=param();if(q!=NULL)if(t=NULL) t=p=q;else p-sibling=q;p=q;return t;static TreeNode*param(void) TreeNode* t=NULL;if(token=INT) t=newStmtNode(IntK);match(INT);if(token=ID) TreeNode* p=NULL;p=newExpNode(Idk); p-attr.name=copySt
27、ring(tokenString); t-child0=p;match(ID);else syntaxError(“unexpected token-“);printToken(token, tokenString);if(token=LZGH)t-child1=newExpNode(Vark);match(RZGH);else return t; else syntaxError(“unexpected token-“);printToken(token, tokenString);return t;static TreeNode*compound_stmt(void) TreeNode*
28、t=newStmtNode(HanshutiK);match(LDGH);if(token=INT) t-child1=local_var_declaration();if(token=RDGH) match(RDGH);return t;else t-child2=statement_list(); else if(token=RDGH) match(RDGH);return t;else t-child0=statement_list();while(token!=RDGH)match(RDGH);return t;static TreeNode*local_var_declaration
29、(void) TreeNode*t=NULL;TreeNode* s=t;while(token=INT) TreeNode* q=newStmtNode(IntK);match(INT);if(q!=NULL)p=newExpNode(Idk); p-attr.name=copyString(tokenString); match(ID);p-child1=var_declaration();q-child0=p; if(t=NULL) t=s=q; else s-sibling=q;s=q; else syntaxError(“unexpected token-“);printToken(
30、token, tokenString);return t;static TreeNode*statement_list(void) TreeNode* t=statement(); TreeNode*p=t;while (IF = token|token=LDGH|ID = token|WHILE = token|RETURN =token) TreeNode* q;q=statement();if(q!=NULL)if(t=NULL) t=p=q;else p-sibling=q;p=q;return t;static TreeNode*statement(void) TreeNode* t
31、=NULL;switch(token)case IF:t=selection_stmt(); break;case ID:t=expression_stmt(); break;case SEMI:t=expression_stmt(); break;case WHILE:t=iteration_stmt(); break;case RETURN:t=return_stmt(); break;case LDGH:t=compound_stmt(); break;default:syntaxError(“unexpected token-“);printToken(token, tokenStri
32、ng);token=getToken();break;return t;static TreeNode*selection_stmt(void) TreeNode* t=newStmtNode(IfK);match(IF);match(LPAREN);if(t!=NULL) t-child0=expression();match(RPAREN);t-child1=statement();if(token=ELSE) match(ELSE);if(t!=NULL) t-child2=statement();return t;static TreeNode*expression_stmt(void
33、) TreeNode* t=NULL;if(token=SEMI) return t;else t=expression();match(SEMI);return t;static TreeNode*iteration_stmt(void) TreeNode* t=newStmtNode(WhileK);match(WHILE);match(LPAREN);if(t!=NULL) t-child0=expression();match(RPAREN);if(t!=NULL) t-child1=statement(); return t;static TreeNode*return_stmt(void) TreeNode* t=newStmtNode(ReturnK);match(RETURN);if (token=SEMI) match(SEMI);return t;