编译原理实验一姓名:朱彦荣学号:20132184 专业:软件工程2 实验题目:词法分析完成语言:C/C++上级系统:VC++6.0日期:2015/11/7词法分析设计题目:手工设计c语言的词法分析器(可以是c语言的子集)设计容:处理c语言源程序,过滤掉无用符号,判断源程序中单词的合法性,并分解出正确的单词,以二元组形式存放在文件中。
设计目的:了解高级语言单词的分类,了解状态图以及如何表示并识别单词规则,掌握状态图到识别程序的编程。
结果要求:课程设计报告。
完成日期:第十五周提交报告一.分析要想手工设计词法分析器,实现C语言子集的识别,就要明白什么是词法分析器,它的功能是什么。
词法分析是编译程序进行编译时第一个要进行的任务,主要是对源程序进行编译预处理(去除注释、无用的回车换行找到包含的文件等)之后,对整个源程序进行分解,分解成一个个单词,这些单词有且只有五类,分别是标识符、保留字、常数、运算符、界符。
以便为下面的语法分析和语义分析做准备。
可以说词法分析面向的对象是单个的字符,目的是把它们组成有效的单词(字符串);而语法的分析则是利用词法分析的结果作为输入来分析是否符合语法规则并且进行语法制导下的语义分析,最后产生四元组(中间代码),进行优化(可有可无)之后最终生成目标代码。
可见词法分析是所有后续工作的基础,如果这一步出错,比如明明是‘<=’却被拆分成‘<’和‘=’就会对下文造成不可挽回的影响。
因此,在进行词法分析的时候一定要定义好这五种符号的集合。
下面是我构造的一个C语言子集。
第一类:标识符 letter(letter | digit)* 无穷集第二类:常数 (digit)+ 无穷集第三类:保留字(32)auto break case char const continuedefault do double else enum externfloat for goto if int longregister return short signed sizeof staticstruct switch typedef union unsigned voidvolatile while第四类:界符‘/*’、‘//’、 () { } [ ] " " ' 等第五类:运算符 <、<=、>、>=、=、+、-、*、/、^、等对所有可数符号进行编码:<$,0><auto,1>...<while,32><+,33><-,34><*,35></,36><<,37><<=,38><>,39><>=,40><=,41><==,42><!=,43><;,44><(,45><),46><^,47><,,48><",49><',50><#,51><&,52><&&,53><|,54><||,55><%,56><~,57><<<,58>左移<>>,59>右移<[,60><],61><{,62><},63><\,64><.,65><?,66><:,67><!,68> "[","]","{","}"<常数99 ,数值><标识符100 ,标识符指针>上述二元组中左边是单词的符号,右边为其种别码,其中常数和标识符有点特别,因为是无穷集合,因此常数用自身来表示,种别码为99,标识符用标识符符号表的指针表示(当然也可用自身显示,比较容易观察),种别码100。
根据上述约定,一旦见到了种别码syn=63,就唯一确定了‘}’这个单词。
下面是一些变量的约定://全局变量,保留字表static char reserveWord[32][20] = {"auto", "break", "case", "char", "const", "continue","default", "do", "double", "else", "enum", "extern","float", "for", "goto", "if", "int", "long","register", "return", "short", "signed", "sizeof", "static","struct", "switch", "typedef", "union", "unsigned", "void","volatile", "while"};//界符运算符表,根据需要可以自行增加static char operatorOrDelimiter[36][10]={"+","-","*","/","<","<=",">",">=","=","==","!=",";","(",")","^",",","\"","\'","#","&","&&","|","||","%","~","<<",">>","[","]","{","}","\\",".","\?",":","!"};static char IDentifierTbl[1000][50]={""};//标识符表char resourceProject[10000];//输入的源程序存放处,最大可以存放10000个字符。
char token[20]={0};//每次扫描的时候存储已经扫描的结果。
int syn=-1;//syn即为种别码,约定‘$’的种别码为0,为整个源程序的结束符号一旦扫描到这个字符代表扫描结束int pProject = 0;//源程序指针,始终指向当前源程序待扫描位置。
几个重要函数://查找保留字,若成功查找,则返回种别码//否则返回-1,代表查找不成功,即为标识符int searchReserve(char reserveWord[ ][20], char s[])/*********************判断是否为字母********************/bool IsLetter(char letter)/*****************判断是否为数字************************/bool IsDigit(char digit)/********************编译预处理,取出无用的字符和注释**********************/void filterResource(char r[],int pProject)/****************************分析子程序,算法核心***********************/ void Scanner(int &syn,char resourceProject[],char token[],int &pProject)下面说一下整个程序的流程:1.词法分析程序打开源文件,读取文件容,直至遇上’$’文件结束符,然后读取结束。
2.对读取的文件进行预处理,从头到尾进行扫描,去除//和/* */的容,以及一些无用的、影响程序执行的符号如换行符、回车符、制表符等。
但是千万注意不要在这个时候去除空格,因为空格在词法分析中有用,比如说int i=3;这个语句,如果去除空格就变成了“inti=3”,这样就失去了程序的本意,因此不能在这个时候去除空格。
3.选下面就要对源文件从头到尾进行扫描了,从头开始扫描,这个时候扫描程序首先要询问当前的字符是不是空格,若是空格,则继续扫描下一个字符,直至不是空格,然后询问这个字符是不是字母,若是则进行标识符和保留字的识别;若这个字符为数字,则进行数字的判断。
否则,依次对这个字符可能的情况进行判断,若是将所有可能都走了一遍还是没有知道它是谁,则认定为错误符号,输出该错误符号,然后结束。
每次成功识别了一个单词后,单词都会存在token[ ]中。
然后确定这个单词的种别码,最后进行下一个单词的识别。
这就是扫描程序进行的工作,可以说这个程序彻底实现了确定有限自动机的某些功能,比如说识别标识符,识别数字等。
为了简单起见,这里的数字只是整数。
4.主控程序主要负责对每次识别的种别码syn进行判断,对于不同的单词种别做出不同的反应,如对于标识符则将其插入标识符表中。
对于保留字则输出该保留字的种别码和助记符,等等吧。