当前位置:文档之家› 编译原理实验词法解析总结器的设计及实现.doc

编译原理实验词法解析总结器的设计及实现.doc

南华大学计算机科学与技术学院实验报告( 2018~2019学年度第二学期)课程名称编译原理实验名称词法分析器的设计与实现姓名学号专业班级地点教师1.实验目的及要求实验目的加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。

实验要求1.对单词的构词规则有明确的定义;2.编写的分析程序能够正确识别源程序中的单词符号;3.识别出的单词以 <种别码,值 >的形式保存在符号表中,正确设计和维护符号表;4.对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的词法分析;2.实验步骤1.词法分析规则<标识符 >::=< 字母 >|< 标识符 ><字母 >|< 标识符 ><数字 ><常数 >::=< 数字 >|< 数字序列 ><数字 ><数字序列 >:: =<数字序列 ><数字 >|< 数字 >|<.><字母 >::=a|b|c|⋯⋯|x|y|z<数字 >::=0|1|2|3|4|5|6|7|8|9<运算符 >::=< 关系运算符 >|< 算运算符 >|< 运算符 >|< 位运算符 >|< 运算符 ><算数运算符 >:: =+|-|*|/|...|--<关系运算符 >:: =<|>|!=|>=|<=|==<运算符 >::=&&| || |!<位运算符 >::=&| | |!<运算符 >::==|+=|-=|/=|*=<分界符 >:: = ,|;|(|)|{|}|:| // |/**/<保留字 >:: = main|if|else|while|do|for|...|void2.符号的符号种符号种main0>26if1>=27else2<28while3<=29do4!30for5!=31switch 6 = 32 case 7 == 33 int 8 ( 34 double 9 ) 35 float 10 { 36 long 11 } 37 void 12 ; 38 + 13 :39 += 14 | 40 ++ 15 || 41 - 16 数字42 -= 17 标识符43 -- 18 , 44 & 19 // 45 && 20 /**/ 46 # 21* 22*= 23/ 24/= 253.状态转换图空白字母数字/+!><,(&:{;其它字母与数字非字母与数字1 2数字非数字4 3其它6 5=7/ 8*9其它11 10= 12+ 13其它15 14=16其它17 18=19其它20 21 ..22 ..33344.算法分析①词法分析器工作的第一步是输入源程序文本。

为了更好地对单词符号识别,把输入串预处理一下。

预处理主要滤掉空格,跳过注释、换行符等。

②对预处理后的输入串依次扫描单个字符,使用 if-while嵌套语句和switch case 语句判断字符的类型,具体识别方法可看状态转换图。

有时为了确定词性,需要超前扫描,若超前扫描的字符对识别当前单词无用处,则需要退还给输入串,以备识别下一单词字符时使用。

③若读入的字符与单词符号编码表的字符匹配不上,则报错,并输出出错行数。

对识别处的单词符号以(单词符号,种别码)二元式的形式输出。

3.实验内容1. 流程图2.程序的变量与函数说明(1)input全局字符数组,用来存放输入串(2)word全局字符数组,用来存放获取到的单词符号,限定长度为 8(3)ch全局字符变量,用来存放最新读入的字符(4)syn全局整型变量,表示单词符号的编码(5)p全局整型变量,表示当前字符在input 数组的位置(6)m全局整型变量,表示最新读入的字符在word 数组的下标(7)line全局整型变量,当前行数(8)keyword全局字符数组,存放关键字(9)init()获取输入串(10)isKey()判断关键字的函数,若参数数组中是关键字,则把 syn 置为该关键字对应的编码并返回 1,否则返回 0(11)isLetter()判断字母的函数,若参数字符是字母,则返回1,否则返回 0(12)isDigit()判断数字的函数,若参数字符是数字,则返回1,否则返回 0(13)isSpace()判断空白符的函数,若参数字符是空格、 TAB或换行符,则返回 1,否则返回 0(14)scaner()扫描输入串的函数,对读出的字符进行判断,若是单词符号表中的符号,则将 syn 置为对应的编码3.源程序#include <stdio.h>#include <string.h>char input[1000];// 输入串char word[8];// 获取到的单词char ch;int syn;// 种别码int p;int m;int line;// 行数//关键字charkeyword[][8]={"main","if","else","while","do","for","switch","case","int","double ","float","long","void"};void scaner(void);//获取输入串void init(){int i=0;printf("\n please input a string(end with '#'):\n");do{scanf("%c",&ch);input[i++]=ch;}while(ch!='#');}//判断是不是关键字int isKey(char *str){int n;for(n=0;n<13;n++){if(strcmp(str,keyword[n])==0){syn=n;return 1;}}return 0;}//判断是不是数字int isDigit(char c){if (c>='0'&&c<='9')return 1;else}//判断是不是字母int isLetter(char c){if ((c<='z'&&c>='a')||(c>='A'&&c<='Z')) return 1;elsereturn 0;}int isSpace(char c){if (c==' '||c=='\t'||c=='\n'){return 1;}return 0;}void main(){init();// 输入字符串line=0;p=0;do{scaner();{case -1:printf("you have input a wrong string in line %d\n",line);break;default:printf("( %s,%d )\n",word,syn);break;}}while(syn!=21);}void scaner(void){//清空 wordfor(m=0;m<8;m++){word[m] = ' ';}//读取字符ch=input[p++];m=0;//当 ch 为空格或换行符时,继续往下读while(isSpace(ch)){{line++;}ch=input[p++];}//如果以字母开头if(isLetter(ch)){// 如果往后是字母或数字,把字符存入word 中,然后往下继续读//串长超过 8 则截断while((isLetter(ch)||isDigit(ch))&&m<8){word[m++]=ch;ch=input[p++];}p--;syn=43;word[m++]='\0';isKey(word);//判断是不是关键字}//如果是以数字开头,并且往后是数字else if(isDigit(ch)){while((isDigit(ch)||ch=='.')&&m<8) {word[m++]=ch;ch=input[p++];}//如果数字之后是字母 ,则出错if (isLetter(ch)){while(!isSpace(ch)){ch=input[p++];}syn=-1;return ;}p--;syn=42;}else{switch(ch){//比较运算符case '<':word[m++]=ch;ch=input[p++];if(ch=='='){syn=29;word[m++]=ch;}else{syn=28;p--;}break;case '>':word[m++]=ch;ch=input[p++];if(ch=='='){syn=27;word[m++]=ch;}else{syn=26;p--;}break;case '!':ch=input[p++];if(ch=='='){syn=31;word[m++]=ch;}else{syn=30;p--;}break;case '=':word[m++]=ch;ch=input[p++];if(ch=='='){syn=33;word[m++]=ch;}else{syn=32;p--;}break;//算术运算符 +、-、* 、/ case '+':word[m++]=ch;ch=input[p++];if(ch=='+'){syn=15;word[m++]=ch;}else if(ch=='='){syn=14;word[m++]=ch;}else{syn=13;p--;}break;case '-':word[m++]=ch;ch=input[p++];if(ch=='-'){syn=18;word[m++]=ch;}else if(ch=='='){syn=17;word[m++]=ch;}else if (isDigit(ch)){while(isDigit(ch)){word[m++]=ch;ch=input[p++];}p--;syn=42;}else{syn=16;p--;}break;case '*':word[m++]=ch;ch=input[p++];if(ch=='='){syn=23;word[m++]=ch;}else{syn=22;p--;}break;case '/':word[m++]=ch;ch=input[p++];if(ch=='='){syn=25;word[m++]=ch;}//如果是单行注释,则读到换行符为止else if (ch=='/'){word[m++]=ch;syn=45;while (ch!='\n'){ch=input[p++];}line++;}//如果是多行注释,则读到匹配的 */ 为止else if(ch=='*'){word[m++]=ch;syn=46;int flag=1;while (flag){ch=input[p++];if (ch=='*'){if (input[p++]=='/'){word[m++]='*';word[m++]='/';flag=0;}else{p--;}}if (ch=='\n'){line++;}}}else{syn=24;p--;}break;//界符case '(':syn=34;word[m++]=ch;break;case ')':syn=35;word[m++]=ch;break;case '{':syn=36;word[m++]=ch;break;case '}':syn=37;word[m++]=ch;break;case ';':syn=38;word[m++]=ch;break;case '#':syn=21;word[m++]=ch;break;case ':':syn=39;word[m++]=ch;break;case ',':syn=44;word[m++]=ch;break;//逻辑运算符case '&':word[m++]=ch;ch=input[p++];if(ch=='&'){syn=20;word[m++]=ch;}else{syn=19;p--;}break;case '|':word[m++]=ch;ch=input[p++];if(ch=='|'){syn=41;word[m++]=ch;}else{syn=40;p--;}break;default:syn=-1;break;}}//字符串结束符word[m++]='\0';}4.实验结果因为 printf和""不是单词符号表中的符号,因而判定输入有错5.实验总结分析这个程序实现了对所选词法子集的单词识别,并对识别出的单词以二元式的形式输出,对于存在的一些词法错误,能够做出简单的错误处理,比如,若标识符以数字开头或单词符号在符号表中不存在,则输出错误信息,并给出行号;同时该程序也能清除掉源程序中的注释,识别出实型常数。

相关主题