版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、编译原理课程设计报告 xx xxxxxxxxx 编译原理课程设计报告课题名称: C-词法扫描器及语法分析器实现 提交文档学生姓名: 提交文档学生学号: 同组 成 员 名 单: 无 指导 教 师 姓 名: 金军 指导教师评阅成绩: 指导教师评阅意见: . . 提交报告时间:2014年 6月 xx日目录目录21 课程设计目标22 分析与设计42.1 程序结构43 程序代码实现93.1 代码结构93.2.1 globals.h93.2.2 scan.c113.2.3 parser.c183.4 util.c303.5 test.cpp364 测试结果384.1.给出标准测试程序的词法和语法分析结果:
2、384.1.1 词法分析结果384.1.2 语法分析结果414.2.修改代码后的结果:424.2.1修改425. 本课程设计我的独创工作446.总结44 1 课程设计目标学生在学习编译原理课程过程中,结合各章节的构造编译程序的基本理论,要求用C或C+语言描述及上机调试,实现一个 C-Minus 小编译程序(包括词法分析,语法分析等重要子程序),使学生将理论与实际应用结合起来,受到软件设计等开发过程的全面训练,从而提高学生软件开发的能力。 要求:(1)设计词法分析器设计各单词的状态转换图,并为不同的单词设计种别码。将词法分析器设计成供语法分析器调用的子程序。功能包括:a. 具备预处理功能。将不翻
3、译的注释等符号先滤掉,只保留要翻译的符号串,即要求设计一个供词法分析调用的预处理子程序;b. 能够拼出语言中的各个单词;c. 返回(种别码, 属性值)。(2)语法分析要求用学习过的自底向上或自顶向下的分析方法等,实现对表达式、各种说明语句、控制语句进行语法分析。若语法正确,则用语法制导翻译法进行语义翻译;生成并打印出语法树;若语法错误,要求指出出错性质和出错位置(行号)。2 分析与设计2.1 程序结构本程序采用C+语言以面向对象的思想编写,程序分为两部分:词法分析(Scanner)和语法分析(Parser)。扫描程序执行词法分析,并将字符序列收集到token中,并将每一行的Token打印出来。
4、l 实现方法:Scanner:手工实现Parser:递归下降l 系统总图:ParserScannersource code Token Syntax Tree 程序流程:在程序中,词法分析获取所有Token,并将获取的Token存储在scanner对象的tokenString中。然后Parser类的语法分析程序就根据tokenString中的Token进行语法分析,生成语法树,最后打印语法树。同时,这也是程序的流程。整体程序流程图开始删除注释出错词法分析TF结束语法分析出错出错输出出错信息TFFT从文件获取源代码l 扫描器:C惯用的词法1、语言的关键字:else if int return v
5、oid while2、专用符号:+ - * / < <= > >= = != = ; , ( ) /* */3、其他标记是ID和NUM,通过下列正则表达式定义:ID = letter letter*NUM = digit digit*letter = a|.|z|A|.|Zdigit = 0|.|94、空格由空白、换行符和制表符组成。空格通常被忽略,除了它必须分开ID、NUM关键字。5. 注释用通常的C语言符号/ * . . . * /围起来。注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。注释不能嵌套。DFA图如下:初始状态设置为START,
6、当需要得到下一个token时,取得此token的第一个字符,并且按照DFA与对此字符的类型的分析,转换状态。重复此步骤,直到DONE为止,输出token类型。参考课本中所给的TINY扫描程序的DFA,C-的DFA不同之处在于注释以及(= =,! = ,< =, > =)的处理:1. 注释部分参考了课本中C风格注释的DFA; Other other *54321 / * * / Other other 2. 处理(= =,! = ,< =, > =)时并没有新建状态,而是在状态INASSIGN中分了4种情况,通过一个变量分别处理。INENDCOMMENTl 语法分析: C
7、-语法与语义:1. program declaration-list 2. declaration-list declaration-list declaration | declaration 3. declaration var-declaration | fun-declaration 4. var-declaration type-specifier ID ; | type-specifier ID NUM ; 5. type-specifier int | void 6. fun-declaration type-specifier ID ( params ) compound-st
8、mt (在课后解释中compound-stmt前面没有“|”符号) 7. params params-list | void 8. param-list param-list , param | param 9. param type-specifier ID | type-specifier ID 10. compound-stmt local-declarations statement-list 11. local-declarations local-declarations var-declaration | empty 12. statement-list statement-li
9、st statement | empty 13. statement expression-stmt | compound-stmt | selection-stmt | iteration-stmt | return-stmt 14. expression-stmt expression ; | ; 15. selection-stmt if ( expression ) statement | if ( expression ) statement else statement 16. iteration-stmt while(expression) statement 17. retur
10、n-stmt return ; | return expression ; 18. expression var = expression | simple-expression 19. var ID | ID expression 20. simple-expression additive-expression relop additive-expression | additive-expression 21. relop <= | < | > | >= | = | != 22. additive-expression additive-expression ad
11、dop term | term 23. addop + | - 24. term term mulop factor | factor 25. mulop * | / 26. factor ( expression ) | var | call | NUM 27. call ID ( args ) 28. args arg-list | empty 29. arg-list arg-list , expression | expressionl 代码设计格式:程序结构:语法分析函数parser通过调用词法分析函数getToken实现语法分析。文件和函数的设计说明:文件main.c包含相应头文件
12、,及main函数的实现;文件golbals.h包含符号表和分析数的数据结构及在其它文件中使用的变量;文件util.h 和util.c实现与词法分析和语法分析输出相关的函数printToken和printTree,以及分析树节点初始化相关的函数newStmtNode,newExpNode(Expkind)和copyString;文件scan.h 和scan.c实现词法分析,主要函数为getToken;文件parser.h 和parser.c实现语法分析,函数为与文法规则对应的函数。3 程序代码实现3.1 代码结构3.2.1 globals.h#ifndef _GLOBALS_H_#define
13、_GLOBALS_H_#include <STDIO.H>#include <STDLIB.H>#include <CTYPE.H>#include <STRING.H>#include<iostream>#include <direct.h>using namespace std;#ifndef FALSE#define FALSE 0#endif#ifndef TRUE#define TRUE 1;#endif/ 保留字的个数#define MAXRESERVED 6typedef enum/book-keeping
14、tokensENDFILE,ERROR,/reserved wordsIF,ELSE,INT,RETURN,VOID,WHILE,/multicharacter tokensID,NUM,/special symbols/LBRACKET/RBRACKET - LBRACE/RBRACE ASSIGN,EQ,LT,RT,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,SEMI,LBRACKET,RBRACKET,NEQ,COMMA,LBRACE,RBRACE,LTEQ,RTEQTokenType;extern FILE* source; /源代码文件extern FIL
15、E* listing; /listing output text fileextern FILE* code; /extern int lineno; /语法分析树typedef enum NodeKindStmtK, ExpK, DeclarationK,;typedef enum StmtKindIfK, WhileK, AssignK, ReturnK, VoidK,;typedef enum ExpKindOpK, ConstK, IdK, Array_expK,Function_expK,;typedef enum ExpTypeVoid,Integer;typedef enum D
16、eclarationKind FunctionK, VarK, ArrayK, ParaMeterK ;#define MAXCHILDREN 3typedef struct treeNodestruct treeNode *declaration;struct treeNode *childMAXCHILDREN;struct treeNode *sibling;struct treeNode *params;int lineno;NodeKind nodekind;union kindStmtKind stmt;ExpKind exp;DeclarationKind declaration
17、;kind;struct MyStruct TokenType op;int val;char *name;int size;attr;ExpType type;TreeNode;extern int EchoSource;extern int TraceScan;extern int TraceParse;extern int TraceAnalyze;extern int TraceCode;extern int Error;#endif3.2.2 scan.c最主要的过程是GetToken,它消耗输入字符并根据DFA图返回下一个被识别的记号。这个实现利用了双重嵌套情况分析,以及一个有关状
18、态的大型情况列表,在大列表中是基于当前输入字符的单独列表。记号本身被定义成globals.h中的枚举类型。扫描程序的状态也被定义为一个枚举类型,位于扫描程序之中。扫描程序使用了三个全局变量,文件变量source,listing.在globals.h中声明且在main.c中被分配和初始化的整型变量lineno。由getToken过程完成的额外的簿记如下所述:表reserved和过程reservedlookup完成位于由getToken的主要循环识别的标识符之后的保留字的查找,currentToken的值也随之改变。标志变量save被用作指示是否将第一个字符增加到tokenString之上;由于需
19、要包括空白格和非消耗的先行,因此这些东西都是必要的。到扫描程序的字符输入由getNextChar函数提供,该函数将一个256字符缓冲区内部的lineBuf中的字符取到扫描程序中,如果已经耗尽了这个缓冲区,且假设每一次都获取了一个新的源代码行,那么getNextChar就利用fget从source文件更新该缓冲区。最后由于从INUM和INID到最终状态的转换是非消耗的。可以通过一个ungetnextChar的过程在输入缓冲区的反填一个字符来完成这一任务。#include "globals.h"#include "util.h"#include "
20、scan.h"typedef enum START, INASSIGN, INCOMMENT,INENDCOMMENT,INNUM, INID, DONE,INLT,INRT ,INNEQStateType;char tokenStringMAXTOKENLEN+1;#define BUFLEN 1024static char lineBufBUFLEN;static int linepos=0;static int bufsize=0;/getNextChar 从lineBuf获得下一个非空字符,读入新的一行如果lineBuf 耗尽static char getNextCHar(v
21、oid)if (!(linepos<bufsize)lineno+;if (fgets(lineBuf,BUFLEN-1,source)if (EchoSource)fprintf(listing,"%4d,%s",lineno,lineBuf);bufsize=strlen(lineBuf);linepos=0;return lineBuflinepos+;else return EOF;else return lineBuflinepos+; / backtracks one character in lineBufstatic void ungetNextCha
22、r(void)linepos-;/查找表的保留字static struct char *str;TokenType tok;reservedWordsMAXRESERVED="if",IF,"int",INT,"else",ELSE,"return",RETURN,"void",VOID,"while",WHILE;/查找一个标识符,看看这是否是一个保留字/使用线性搜索static TokenType reservedLookup(char *s)int i;for(i=0;
23、i<MAXRESERVED;+i)if(!strcmp(s,reservedWordsi.str)return reservedWordsi.tok;return ID;TokenType getToken(void)/索引存储为“tokenString”int tokenStringIndex = 0;/返回当前tokenTokenType currentToken;/当前状态总是以START开始StateType state = START;/指示存放至tokenString的标志int save=TRUE;while (state != DONE)int c = getNextCH
24、ar();save = TRUE;switch (state)case START:if (isdigit(c)state = INNUM;else if (isalpha(c)state =INID;else if (c = '=')state =INASSIGN;else if (c = ' ') |(c = 't') | (c = 'n')save = FALSE;else if (c = '/') /遇到"/"则假定就是注释,进入注释状态state = INCOMMENT;save =
25、FALSE;else if (c = '>')state = INRT;else if (c = '<')state = INLT;else if (c = '!')state = INNEQ;elsestate = DONE;switch (c)default:currentToken = ERROR;break;case EOF:save = FALSE;currentToken = ENDFILE;break;case '':currentToken = LBRACKET;break;case ''
26、;:currentToken = RBRACKET;break;case ',':currentToken = COMMA;break;case '+':currentToken = PLUS;break;case '-':currentToken = MINUS;break;case '*':currentToken = TIMES;break;case '':currentToken = LBRACE;break;case '':currentToken = RBRACE;break;case
27、'(':currentToken = LPAREN;break;case ')':currentToken = RPAREN;break;case '':currentToken = SEMI;break;break;/*=注释改动=*/case INENDCOMMENT:if (c = '*'&&getNextCHar() = '/') /token是*且下一个token是/则结束注释save = FALSE;state = START; /注释不作处理,直到注释结束,elsesave = FAL
28、SE;state = INENDCOMMENT;break;case INCOMMENT:if (c = '*') /“/”后是*则进入注释/ungetNextChar();save = FALSE; state = INENDCOMMENT; /若是注释开头,转入注释结尾处理else if (c = EOF)state = DONE;currentToken = ENDFILE;else / “/”后不是*则为除法ungetNextChar();save = FALSE;currentToken = OVER;state = DONE;break;/*=赋值改动=*/case
29、 INASSIGN:state = DONE;if (c = '=') /下一个仍是等号就为相等currentToken = EQ;else /否则回退,ungetNextChar();save = FALSE;currentToken = ASSIGN;break;/*=小于等于=*/case INLT:state = DONE;if (c = '=')currentToken = LTEQ;elseungetNextChar();save = FALSE;currentToken = LT;break;/*=大于等于=*/case INRT:state =
30、DONE;if (c = '=')currentToken = RTEQ;elseungetNextChar();save = FALSE;currentToken = RT;break;/*=不等于=*/case INNEQ:state = DONE;if (c = '=')currentToken = NEQ;elseungetNextChar();save = FALSE;currentToken = ERROR;break;case INNUM:if (! isdigit(c)ungetNextChar();save = FALSE;state = DO
31、NE;currentToken = NUM;break;case INID:if (!isalpha(c)ungetNextChar();save = FALSE;state = DONE;currentToken = ID;break;case DONE:default:fprintf(listing, "Scanner Bug:state=%dn", state);state = DONE;currentToken = ERROR;break;if (save) && (tokenStringIndex <= MAXTOKENLEN)tokenSt
32、ringtokenStringIndex+ = (char)c;if (state = DONE)tokenStringtokenStringIndex = '0'if (currentToken = ID)currentToken = reservedLookup(tokenString);if (TraceScan)fprintf(listing, "t%d:", lineno);printToken(currentToken, tokenString);return currentToken;3.2.3 parser.c#include"gl
33、obals.h"#include"util.h"#include"scan.h"#include"parse.h"static TokenType token; /holds current tokenstatic TreeNode * stmt_sequence(void);static TreeNode * statement(void);static TreeNode * if_stmt(void);static TreeNode * while_stmt(void);/自定义函数static TreeNode * r
34、eturn_stmt(void);static TreeNode * int_stmt(void);static TreeNode * void_stmt(void);static TreeNode * declaration(void);static TreeNode * parameter(void);static TreeNode * exp(void);static TreeNode * simple_exp(void);static TreeNode * term(void);static TreeNode * factor(void);static void inFunction(
35、void);static void syntaxError(char *message)fprintf(listing, "n>>>");fprintf(listing, "Syntax error at line %d: %s", lineno, message);Error = TRUE;static void match(TokenType expected)if (token = expected)token = getToken();elsesyntaxError("unexpected token->&quo
36、t;);printToken(token, tokenString);fprintf(listing, " ");TreeNode * stmt_sequence(void)TreeNode *t = statement();TreeNode *p = t;while (token != ENDFILE) && (token != RBRACE) )TreeNode *q;/match(SEMI);q = statement();if (token != RBRACE)if (q != NULL)if (t = NULL)t = p = q;elsep-&g
37、t;sibling = q;p = q;return t;TreeNode * statement(void)TreeNode *t = NULL;switch (token)case IF:t = if_stmt();break;case WHILE:t = while_stmt();break;case ID: /若为ID不直接进行赋值,进入 exp()至factor(),将赋值加入至factor()t = exp();break;case RETURN:t = return_stmt();break;case INT:t = int_stmt();break;case VOID:t =
38、void_stmt();break;case SEMI:match(SEMI);break;default:syntaxError("unexpected token -> ");printToken(token, tokenString);token = getToken();break;return t;TreeNode *declaration(void)TreeNode *t = newDeclarationNode(token);if (t != NULL)/名称token = getToken();/ID赋给t->
39、 = copyString(tokenString);token = getToken();/token是"(" 则为函数声明if (token = LPAREN)t->kind.declaration = FunctionK;match(LPAREN);TreeNode *paramets = parameter(); /函数参数匹配if (paramets != NULL)t->child0 = paramets;match(RPAREN);match(LBRACE);/匹配函数体TreeNode *body = stmt_sequence();if (bo
40、dy = NULL)syntaxError("error body! ");elset->child1 = body;match(RBRACE);/token后不是(则是变量声明else/普通变量类型t->kind.declaration = VarK;/进入数组类型if (token = LBRACKET)match(LBRACKET);t->kind.declaration = ArrayK;t->attr.size = atoi(tokenString);token = getToken();match(RBRACKET);match(SEMI
41、);return t;TreeNode *parameter(void)TreeNode *t = NULL;if (token = VOID)match(VOID);/结束else if (token = RBRACE)return t;/有参数elset = newDeclarationNode(token);token = getToken();t-> = copyString(tokenString);token = getToken();/数组if (token = LBRACKET)t->kind.declaration = ArrayK;match(
42、LBRACKET);t->attr.size = 0;match(RBRACKET);/IDelset->kind.declaration = VarK;if (token = COMMA)match(COMMA);t->sibling = parameter();return t;TreeNode *if_stmt(void)TreeNode *t = newStmtNode(IfK);match(IF);if (t != NULL)match(LPAREN);t->child0 = exp();match(RPAREN);if (t != NULL)/如果带大括号i
43、f (token = LBRACE)match(LBRACE);while (token != RBRACE)t->child1 = statement();match(RBRACE);/无括号elset->child1 = statement();if (token = ELSE)match(ELSE);if (t != NULL)/如果带大括号if (token = LBRACE)match(LBRACE);while (token != RBRACE)t->child2 = statement();match(RBRACE);/无括号elset->child2 =
44、 statement();return t;TreeNode *while_stmt(void)TreeNode *t = newStmtNode(WhileK);match(WHILE);TreeNode *p = NULL;match(LPAREN);while (token != RPAREN)if (t->child0 = NULL)p = exp();t->child0 = p;elsep = p->child0;p = exp();match(RPAREN);/while函数大括号可有可无/如果有括号if (token = LBRACE)match(LBRACE)
45、;while (token!=RBRACE)t->child1 = statement();match(RBRACE);/无elset->child1 = statement();if (token = SEMI)match(SEMI);return t;TreeNode *return_stmt(void)TreeNode *t = newStmtNode(ReturnK);t-> = copyString(tokenString);match(RETURN);if (token != SEMI)t->child0 = exp();match(SEM
46、I);return t;TreeNode *int_stmt(void)TreeNode *t = newDeclarationNode(INT);match(INT);t-> = copyString(tokenString);match(ID);/函数if (token = LPAREN)match(LPAREN);t->kind.declaration = FunctionK;if (token = VOID)match(VOID);else/函数参数匹配inFunction();match(RPAREN);/函数体match(LBRACE);while (token != RBRACE)statement();match(RBRACE);/数组else if (token = LBRACKET)t->kind.exp = Array_expK;match(LBRACKET);t->child0 = exp();match(RBRACKET);/变量if (token = SEMI)t->kind.declaration = VarK;match(SEMI);return t;/void 函数TreeNode *void_stmt(void)TreeNode *t =
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 教育领域中的创新驱动决策实践
- 教育领域中的数字化创新实践
- 家庭营养教育在儿童成长中的重要性
- 推动医疗技术进步的农业科技合资项目研究
- 家长在构建良好亲子关系中的角色与技巧
- 家校合作在远程教育中的应用
- Unit 6 Reading 1 说课稿 2024-2025学年译林版英语七年级上册
- 《第二单元 用金山画王画画:4.2 画柿子》说课稿-2023-2024学年新世纪版(2023)三年级下册
- 第3课 古代印度(新说课稿)2023-2024学年九年级上册历史(部编版)
- 高中信息技术必修说课稿-4.2.2 表格数据的图形化5-教科版
- 高中英语新课程标准试题含答案(四套)
- 当前中国个人极端暴力犯罪个案研究
- 食品欺诈预防控制程序分享
- 员工辞职报告下载(6篇)
- 建筑节能PPT 课件
- GB/T 31525-2015图形标志电动汽车充换电设施标志
- GB/T 17906-2021消防应急救援装备液压破拆工具通用技术条件
- GB/T 16674-1996六角法兰面螺栓小系列
- GB/T 13436-2008扭转振动测量仪器技术要求
- 高低压配电柜-福建宁德核电站投标书
- 干燥综合症护理课件
评论
0/150
提交评论