词法分析器-计算器-设计与实现实验报告:词法分析器c

  辅导教师 张静 成绩

 实验日期

 实验时间

 1实验名称:词法分析器的设计与实现

 2、实验目的(1) 掌握C语言单词符号的划分、正规式、状态转换图及词法分析器的实现。

 (2) 掌握词法分析程序的作用。

 3、实验要求

 (1) 对任给的一个C语言源程序,能够滤掉空格、回车换行符、tab键及注释。

 (2) 识别各类单词符号,如关键字、标识符、运算符、常数、界符,结果以二 元式形式输出,并构造符号表。

 (3) 输出有词法错误的单词及所在行号。(在此阶段只能识别有限的词法错误)

 4、实验原理

 根据扫描到的单词符号的第一个字符的种类,分别转到相应的程序进行处 理。这些程序的功能就是识别以相应字符开头的各类单词符号。

 5、实验步骤

 (1) 根据C语言各类单词的正规式,构造能识别各类单词的状态转换图。

 (2) 根据状态转换图,构造识别各类单词的词法分析器 。

 6、状态转换图及词法分析程序

 状态转换图:

 词法分析程序:

 #i nclude<stdio.h>

 #i nclude<stdlib.h>

 #in clude<stri ng>

 #in clude<iostream>

 using n amespace std;

 stri ng

 keywords[20]={"i nclude","void","ma in"," in t","char","float","double","if","else","then ","break","co ntin ue","for","do","while","pri ntf","sca nf","begi n","e nd","return"};

 char rz[99999]="";

 string id[10000];

 int pp=0;

 string nu[10000];

 int qq=0;

 int choice1(char a) //判断是否是字母

 {

 if((a>='a'&&a<='z')||(a>='A'&&a<='Z'))

 return 1;

 else return 0;

 }

 int choice2(char a) 〃判断是否是数字

 {

 if(a>='0'&&a<=9)

 return 1;

 else return 0;

 int alpha(i nt st) 〃识别保留字和标识符

 {

 char wordbuf[20]="";

 int n=0;

 for(;;)

 {

 wordbuf[ n]=rz[st];

 st++;

 n++;

 if((choice2(rz[st])==1)||(choice1(rz[st])==1)||(rz[st]=='_')) wordbuf[ n]=rz[st];

 else break;

 }

 int flag=0;

 for(int k=0;k<20;k++)

 {

 if(strcmp(keywords[k].c_str(),wordbuf)==0) flag=1;

 } if(flag==0)

 {

 int flagg=-1;

 for(i nt t=0;t<pp;t++)

 {

 if(strcmp(id[t].c_str(),wordbuf)==0)

 { _

 flagg=t;

 }

 }

 if(flagg!=-1) pri ntf(" (id,%d) ",flagg);

 else

 {

 id[pp]=wordbuf;

 printf(" (id,%d) ",pp); pp++;

 }

 }

 else

 {

 printf(" (");

 for(i nt i=0;i <n ;i++)

 {

 prin tf("%c",wordbuf[i]);

 }

 prin tf(",-)");

 }

 return st;

 }

 int number(i nt st) // 识别整数

 {

 char numbuf[20]="";

 int n=0;

 int k=0;

 int flag=0;

 for(;;)

 {

 nu mbuf[ n]=rz[st];

 st++;

 n++;

 if(choice2(rz[st])==1)

 {

 nu mbuf[ n]=rz[st];

 }

 else if((k==0)&&(rz[st]=='.'))

 {

 nu mbuf[ n]=rz[st]; k++;

 }

 else if(choice1(rz[st])==1)

 {

 nu mbuf[ n]=rz[st];

 flag=1; con ti nue;

 }

 else break;

 }

 if(flag==0)

 {

 int flagg=-1;

 for(i nt t=0;t<qq;t++)

 if(strcmp( nu[t].c_str(), nu mbuf)==0) flagg=t;

 if(flagg!=-1) printf(" (nu,%d) ",flagg); else

 {

 nu[qq]=nu mbuf; printf(" (n u,%d) ",qq);

 qq++;

 }

 }

 else

 {

 printf(" (");

 for(int i=0;i<n;i++) printf("%c",numbuf[i]); prin tf(",error digital!)");

 }

 return st;

 }

 int anotation(int st) 〃处理除号/和注释

 {

 char tabuf[9999]="";

 int n=0;

 st++;

 if(rz[st]=='/')

 {

 prin tf(" (//,-)");

 st++;

 while(rz[st]!=10)

 {

 tabuf[ n]=rz[st]; st++;

 n++;

 } printf(" \n 注释"); for(i nt i=0;i <n ;i++) prin tf("%c",tabuf[i]);

 }

 else if(rz[st]=='*')

 {

 prin tf(" (/*,-)");

 st++;

 int stt=st+1;

 while(1)

 { if(rz[st]=='*'&&rz[st+1]=='/') break; tabuf[ n]=rz[st];

 st++; n++;

 if(rz[st+1]=='\0')

 {

 prin tf("(/* error!!\n)");

 return st+1;

 }

 } printf(" \n 注释");

 for(i nt i=0;i <n ;i++) prin tf("%c",tabuf[i]);

 prin tf(" (*/,-)");

 st=st+2;

 }

 else if(rz[st]=='=')

 {

 st++;

 prin tf(" (/*,-)");

 }

 else printf(" (/,-) ");

 return st;

 }

 in t other(i nt st) //函数识别其他特殊字符

 {

 switch(rz[st])

 {

 case '=': st++; if(rz[st]=='=')

 { st++; prin tf(" (rlop,==)");

 } else prin tf(" (rlop,=)");

 break;

 case '+': st++;

 if(rz[st]=='=') { st++;

 printf(" (+=,-)");

 } else if(rz[st]=='+')

 { st++; printf(" (++,-)");

 } else printf(" (+,-)"); break;

 case '-': st++;

 if(rz[st]=='=')

 J

 st++;

 prin tf(" (-=,-)");

 }

 else if(rz[st]=='-')

 {

 st++;

 prin tf(" (--,-)");

 }

 else printf(" (-,-)"); break;

 case '*': st++;

 if(rz[st]=='=')

 {

 st++; prin tf(" (*=,-)");

 }

 else printf(" (*,-)"); break;

 case '>': st++;

 if(rz[st]=='=')

 {

 st++;

 prin tf(" (rlop,>=)");

 }

 else printf(" (rlop,>)"); break;

 case '<': st++;

 if(rz[st]=='=')

 {

 st++;

 prin tf(" (rlop,<=)");

 }

 else printf(" (rlop,<)"); break;

 case %: st++;

 if(rz[st]=='=')

 {

 st++;

 prin tf(" (\%=,-)");

 }

 else printf(" (\%,-)"); break;

 case '!': st++;

 if(rz[st]=='=')

 { st++;

 prin tf(" (!=,-)");

 }

 else printf(" (!,wrong thing!) "); break;

 case &: st++;

 if(rz[st]=='&')

 { st++;

 printf(" (&&,-)");

 }

 else prin tf(" (&, worng word!) "); break;

 case T: st++;

 if(rz[st]==T)

 { st++;

 printf(" (||,-)");

 }

 else prin tf(" (|,wor ng word!) "); break;

 case '{': st++;

 printf(" ({,-)");

 break; case '}': st++;

 printf(" (},-)");

 break;

 case '(': st++;

 printf(" ((,-)");

 break;

 case ')': st++;

 printf(" (),-)");

 break;

 case '[': st++; printf(" ([,-)");

 break;

 case ']': st++; printf(" (],-)");

 break;

 case ':': st++;

 printf(" (:,-)");

 break;

 case #: st++;

 printf("倂,-)");

 break;

 case ';': st++;

 printf(" (;,-)");

 break;

 case '.': st++;

 printf(" (.,-)");

 break;

 case ',': st++; printf(" (,,-)");

 break;

 case ' ': st++;

 break;

 case ' ': st++;

 break;

 case 10: st++;

 prin tf("\n");

 break;

 case 34: st++;

 prin tf(" (\",-)");

 break;

 case 39: st++;

 printf(" (',-)");

 break;

 default: printf(” (%c,wor ng thing) ",rz[st]);

 st++;

 }

 return st;

 }

 int choice(i nt st) //根据读入的单词的第一个字符确定调用不同的单词识别

 函数

 {

 if(choice1(rz[st])==1)

 st=alpha(st);

 else if(choice2(rz[st])==1)

 st=nu mber(st);

 else if(rz[st]=='/')

 st=a no tati on( st);

 else st=other(st);

 return st;

 }

 int mai n()

 L

 int i=0;

 FILE *fp;

 char n ame[10];

 printf("请输入文件名:\n"); scan f("%s",&n ame);

 if((fp=fope n(n ame,"r"))==NULL) {

 prin tf("Ope n error!"); exit(0);

 }

 char ch=fgetc(fp); while(ch!=EOF)

 {

 rz[i]=ch; i++;

 ch=fgetc(fp);

 }

 fclose(fp);

 int j=0;

 while(rz[j]!='\0')

 j=choice(j);

 cout?e ndlvv" 程序中标示符如下 "<<e ndl;

 for(int i=0;i<pp;i++)

 couW "<<id[i]<<e ndl;

 cout?"程序中数字如下"<<endl;

 for(i nt j=0;j<qq;j++) coutvvjvv" "<<nu [j]<<e ndl;

 system("pause");

 }

 7、测试及结果

 测试代码:

 int choice(i nt st) //根据读入的单词的第一个字符确定调用不同的单词识别

 函数

 {

 if(choice1(rz[st])==1) st=alpha(st);

 else if(choice2(rz[st])==1)

 st=nu mber(st); else if(rz[st]=='/') st=a no tati on( st); else st=other(st); return st;

 }

 测试结果:

 8心得

 通过本次的实验,使我真正的了解词法分析器的实现过程,让我更加深刻 领悟词法分析器的实现原理。虽然在本次实验中遇到了各种各样的困难和错误, 但在同学们的帮助下我都一一克服了,使得词法分析器能够正确的识别相应的词 法和表达式。

 在做实验的过程中,总是会忽略各种细节,从而导致经常修改一些很小的低 级错误才能使程序正常运行,不仅浪费时间,还影响对其他地方的修改,并且在 很多步骤处理上,方法不正确。使结果不能符合要求,深刻体会到了自己在编程 方面与别人的差距,在今后的学习中,我会注意改正自己在这方面的缺点, 促使 自己的编程水平不断进步。编译原理是一门专业学科,对于现阶段的我来说,只 能掌握它的一些基本原理和概念,对于一些更深层的知识还是有很多难以理解的 地方。但在这次实验过程中,锻炼了自己的思考能力,也锻炼了自己的动手编程 能力,对于将知识的转化有了很大的帮助。

 辅导教师 张静 成绩

 实验日期 实验时间

 1实验名称计算器的设计与实现

 2、 实验目的掌握自上而下语法分析方法、自下而上语法分析方法

 3、 实验要求

 实验内容

 设计及实现计算表达式的计算器。

 表达式中可包含+、-、*、/、(、)等运算符。

 实验要求:

 对已给的一个二元式形式表达式,能够检查有无语法错误。并指定出错位 置。

 将表达式的语法树输出(或将语法分析过程输出) 。

 4、 实验原理

 根据算符优先分析思想实现语法分析程序。

 5、 实验步骤

 根据文法构造语法分析表。

 编写总控程序实现语法分析。

 6、算符优先分析表及语法分析程序

 算符优先分析表:

 —

 *

 /

 T

 (

 )

 ■

 1

 ■F

 >

 >

 >

 一

 >

 >

 <

 <

 >

 *

 >

 >

 1/

 >

 >

 rr

 >

 A

 >

 A

 -ff

 A

 <

 £

 <

 *

 二

 )

 >

 A

 >

 >

 >

 >

 i

 >

 >

 >

 #

 <

 <

 ■

 语法分析程序:

 #i nclude<stdio.h>

 #i nclude<stdlib.h>

 #defi ne MaxSize 99

 void tran slate(char str[],char exp[]) /*将算术表达式转换成后缀表达式 */

 {

 struct

 {

 char data[MaxSize]; int top;

 }op;

 构体*/

 char ch;

 int i = 0,t = 0;

 op.top = -1;

 ch = str[i];

 i++;

 while(ch != '\0')

 应的转换情况*/

 {

 switch(ch)

 {

 /*top为栈顶*//*

 /*top为栈顶*/

 /*定义一个含data和top的结

 /*将str的每一个数转换成ch*/

 /*ch对应不同的符号的时候对

 /*当是.的时候 将此括号存入

 栈 op*/

 op.top++;op.data[op.top]=ch;

 break;

 case ')':

 先级最咼强故先提

 先级最咼强故先提

 取表达式*/

 {

 exp[t]=op.data[op.top];

 op.top--;

 t++;

 }

 op.top--;

 break;

 case '+':

 case '-':

 while(op.top != -1&&op.data[op.top] !='(')

 exp[t] = op.data[op.top];

 op.top--;

 t++;

 }

 op.top++; /*恢复可插入位置*/

 op.data[op.top] = ch;

 break;

 case case '/':

 /*优先级

 /*优先级*/

 {

 exp[t] = op.data[op.top];

 op.top--;

 t++;

 }

 op.top++;

 op.data[op.top] = ch;

 casebreak;

 case

 /*忽略空格珂i排除误操

 作*/

 break;

 default:

 while(ch >= '0'&&ch <= 9)

 {

 exp[t] = ch;t++;

 ch = str[i];i++;

 exp[t] = '#';

 观也为了以后好

 分隔操作数*/

 t++;

 }

 ch = str[i];

 i++;

 }

 while(op.top != -1)

 {

 exp[t] = op.data[op.top];

 t++;

 op.top--;

 }

 exp[t] = '\0';

 /*分隔操作数为了美

 /*得到剩下的部分*/

 /*表达式结束*/

 }

 float cal_value(char exp[]) {

 struct

 {

 float data[MaxSize];

 int top;

 }st; /*操作数栈*/

 float d;

 char ch;

 int t = 0;

 st.top = -1;

 ch = exp[t];

 t++;

 while(ch != '\0')

 {

 switch(ch) /* 运算主体 */

 {

 case '+':

 st.data[st.top-1] = st.data[st.top-1]+st.data[st.top];

 st.top--;

 break;

 case '-':

 st.data[st.top-1] = st.data[st.top-1]-st.data[st.top];

 st.top--;

 break;

 case

 st.data[st.top-1] = st.data[st.top-1]*st.data[st.top];

 st.top--;

 break;

 case '/':

 if(st.data[st.top] != 0)

 st.data[st.top-1]=st.data[st.top-1]/st.data[st.top];

 else

 {

 printf("\n\t 除 0 是错误的");

 }

 st.top--;

 break;

 default:

 d=0;

 while(ch >= 'O'&&ch <= 9) /* 从后缀表达

 式中获取操作数珥f

 #作用在此体现*/

 {

 d = 10*d+ch-'0';

 ch=exp[t];

 t++;

 }

 st.top++;

 st.data[st.top] = d;

 ch = exp[t];

 t++;

 }

 return st.data[st.top];

 }

 int mai n()

 {

 char str[MaxSize],exp[MaxSize];

 后缀表达式*/

 printf("请输入一个求值表达式\n");

 gets(str);

 printf("原表达式是:%s\n",str);

 tran slate(str,exp);

 表达式*/

 printf("后缀表达式 %s\n",exp);

 /*可以提到前面去*//*str为算术表达式,exps为/*输入一个算术表达式*//*将算术表达式转换成后缀

 /*可以提到前面去*/

 /*str为算术表达式,exps为

 /*输入一个算术表达式*/

 /*将算术表达式转换成后缀

 return 0;

  }

 7、测试及结果

 L' CAU se r&\Adm' n i strator\C eskto p\c ak.exe

 r^-

 r^-宵

 8心得

 此次实验,经过对计算器的设计与实现,让我对编译原理的基本知识有了深 入的了解,加强了对语法分析的认识,掌握了自上而下语法分析方法、自下而上 语法分析方法。熟悉了算符优先分析思想实现语法分析程序。在代码调试过程中 结果出现许多无法解释的错误,但仍旧坚持下来了,最终调试出了结果。通过这 次实验,我的动手实践能力得到很大的提高。

推荐访问:词法 分析器 计算器 实验 报告