资源描述
辅导教师 张静 成绩
实验日期
实验时间
1实验名称 :词法分析器的设计与实现
2、实验目的
(1)掌握C语言单词符号的划分、正规式、状态转换图及词法分析器的实现。
(2)掌握词法分析程序的作用。
3、实验要求
(1)对任给的一个C语言源程序,能够滤掉空格、回车换行符、tab键及注释。
(2)识别各类单词符号,如关键字、标识符、运算符、常数、界符,结果以二元式形式输出,并构造符号表。
(3)输出有词法错误的单词及所在行号。(在此阶段只能识别有限的词法错误)
4、实验原理
根据扫描到的单词符号的第一个字符的种类,分别转到相应的程序进行处理。这些程序的功能就是识别以相应字符开头的各类单词符号。
5、实验步骤
(1)根据C语言各类单词的正规式,构造能识别各类单词的状态转换图。
(2)根据状态转换图,构造识别各类单词的词法分析器。
6、状态转换图及词法分析程序
状态转换图:
0
1
3
2
4
5
6
7
空白
字母
非字母与数字
字母或数字
数字
非数字
运算符
界符
其他
*
*
*
*
*
词法分析程序:
#include<stdio.h>
#include<stdlib.h>
#include<string>
#include<iostream>
using namespace std;
string keywords[20]={"include","void","main","int","char","float","double","if","else","then","break","continue","for","do","while","printf","scanf","begin","end","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(int 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(int t=0;t<pp;t++)
{
if(strcmp(id[t].c_str(),wordbuf)==0)
{
flagg=t;
}
}
if(flagg!=-1) printf(" (id,%d) ",flagg);
else
{
id[pp]=wordbuf;
printf(" (id,%d) ",pp);
pp++;
}
}
else
{
printf(" (");
for(int i=0;i<n;i++)
{
printf("%c",wordbuf[i]);
}
printf(",-) ");
}
return st;
}
int number(int st) //识别整数
{
char numbuf[20]=" ";
int n=0;
int k=0;
int flag=0;
for( ; ; )
{
numbuf[n]=rz[st];
st++;
n++;
if(choice2(rz[st])==1)
{
numbuf[n]=rz[st];
}
else if((k==0)&&(rz[st]=='.'))
{
numbuf[n]=rz[st];
k++;
}
else if(choice1(rz[st])==1)
{
numbuf[n]=rz[st];
flag=1;
continue;
}
else break;
}
if(flag==0)
{
int flagg=-1;
for(int t=0;t<qq;t++)
if(strcmp(nu[t].c_str(),numbuf)==0)
flagg=t;
if(flagg!=-1) printf(" (nu,%d) ",flagg);
else
{
nu[qq]=numbuf;
printf(" (nu,%d) ",qq);
qq++;
}
}
else
{
printf(" (");
for(int i=0;i<n;i++) printf("%c",numbuf[i]);
printf(",error digital!) ");
}
return st;
}
int anotation(int st) //处理除号/和注释
{
char tabuf[9999]=" ";
int n=0;
st++;
if(rz[st]=='/')
{
printf(" (//,-) ");
st++;
while(rz[st]!=10)
{
tabuf[n]=rz[st];
st++;
n++;
}
printf(" \n 注释");
for(int i=0;i<n;i++)
printf("%c",tabuf[i]);
}
else if(rz[st]=='*')
{
printf(" (/*,-) ");
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')
{
printf("(/* error!!\n)");
return st+1;
}
} printf(" \n 注释");
for(int i=0;i<n;i++)
printf("%c",tabuf[i]);
printf(" (*/,-) ");
st=st+2;
}
else if(rz[st]=='=')
{
st++;
printf(" (/*,-) ");
}
else printf(" (/,-) ");
return st;
}
int other(int st) //函数识别其他特殊字符
{
switch(rz[st])
{
case '=': st++;
if(rz[st]=='=')
{
st++;
printf(" (rlop,==) ");
}
else printf(" (rlop,=) ");
break;
case '+': st++;
if(rz[st]=='=')
{
st++;
printf(" (+=,-) ");
}
else if(rz[st]=='+')
{
st++;
printf(" (++,-) ");
}
else printf(" (+,-) ");
break;
case '-': st++;
if(rz[st]=='=')
{
st++;
printf(" (-=,-) ");
}
else if(rz[st]=='-')
{
st++;
printf(" (--,-) ");
}
else printf(" (-,-) ");
break;
case '*': st++;
if(rz[st]=='=')
{
st++;
printf(" (*=,-) ");
}
else printf(" (*,-) ");
break;
case '>': st++;
if(rz[st]=='=')
{
st++;
printf(" (rlop,>=) ");
}
else printf(" (rlop,>) ");
break;
case '<': st++;
if(rz[st]=='=')
{
st++;
printf(" (rlop,<=) ");
}
else printf(" (rlop,<) ");
break;
case '%': st++;
if(rz[st]=='=')
{
st++;
printf(" (\%=,-) ");
}
else printf(" (\%,-) ");
break;
case '!': st++;
if(rz[st]=='=')
{
st++;
printf(" (!=,-) ");
}
else printf(" (!,wrong thing!) ");
break;
case '&': st++;
if(rz[st]=='&')
{
st++;
printf(" (&&,-) ");
}
else printf(" (&,worng word!) ");
break;
case '|': st++;
if(rz[st]=='|')
{
st++;
printf(" (||,-) ");
}
else printf(" (|,worng 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++;
printf("\n");
break;
case 34: st++;
printf(" (\",-) ");
break;
case 39: st++;
printf(" (',-) ");
break;
default: printf(" (%c,worng thing) ",rz[st]);
st++;
}
return st;
}
int choice(int st) //根据读入的单词的第一个字符确定调用不同的单词识别函数
{
if(choice1(rz[st])==1)
st=alpha(st);
else if(choice2(rz[st])==1)
st=number(st);
else if(rz[st]=='/')
st=anotation(st);
else st=other(st);
return st;
}
int main()
{
int i=0;
FILE *fp;
char name[10];
printf("请输入文件名:\n");
scanf("%s",&name);
if((fp=fopen(name,"r"))==NULL)
{
printf("Open 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<<endl<<" 程序中标示符如下 "<<endl;
for(int i=0;i<pp;i++)
cout<<i<<" "<<id[i]<<endl;
cout<<" 程序中数字如下"<<endl;
for(int j=0;j<qq;j++)
cout<<j<<" "<<nu[j]<<endl;
system("pause");
}
7、测试及结果
测试代码:
int choice(int st) //根据读入的单词的第一个字符确定调用不同的单词识别函数
{
if(choice1(rz[st])==1)
st=alpha(st);
else if(choice2(rz[st])==1)
st=number(st);
else if(rz[st]=='/')
st=anotation(st);
else st=other(st);
return st;
}
测试结果:
8、心得
通过本次的实验,使我真正的了解词法分析器的实现过程,让我更加深刻领悟词法分析器的实现原理。虽然在本次实验中遇到了各种各样的困难和错误,但在同学们的帮助下我都一一克服了,使得词法分析器能够正确的识别相应的词法和表达式。
在做实验的过程中,总是会忽略各种细节,从而导致经常修改一些很小的低级错误才能使程序正常运行,不仅浪费时间,还影响对其他地方的修改,并且在很多步骤处理上,方法不正确。使结果不能符合要求,深刻体会到了自己在编程方面与别人的差距,在今后的学习中,我会注意改正自己在这方面的缺点,促使自己的编程水平不断进步。编译原理是一门专业学科,对于现阶段的我来说,只能掌握它的一些基本原理和概念,对于一些更深层的知识还是有很多难以理解的地方。但在这次实验过程中,锻炼了自己的思考能力,也锻炼了自己的动手编程能力,对于将知识的转化有了很大的帮助。
辅导教师 张静 成绩
实验日期
实验时间
1实验名称 计算器的设计与实现
2、实验目的
掌握自上而下语法分析方法、自下而上语法分析方法
3、实验要求
(1)实验内容
设计及实现计算表达式的计算器。
表达式中可包含+、-、*、/、(、)等运算符。
(2)实验要求:
对已给的一个二元式形式表达式,能够检查有无语法错误。并指定出错位置。
将表达式的语法树输出(或将语法分析过程输出)。
4、实验原理
根据算符优先分析思想实现语法分析程序。
5、实验步骤
(1)根据文法构造语法分析表。
(2)编写总控程序实现语法分析。
6、算符优先分析表及语法分析程序
算符优先分析表:
语法分析程序:
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 99
void translate(char str[],char exp[]) /*将算术表达式转换成后缀表达式*/
{
struct
{
char data[MaxSize];
int top; /*top为栈顶*/
}op; /*定义一个含data和top的结构体*/
char ch;
int i = 0,t = 0;
op.top = -1;
ch = str[i]; /*将str的每一个数转换成ch*/
i++;
while(ch != '\0') /*ch对应不同的符号的时候对应的转换情况*/
{
switch(ch)
{
case '(': /*当是的时候将此括号存入栈op*/
op.top++;op.data[op.top]=ch;
break;
case ')':
while(op.data[op.top] != '(') /*括号内的转换优先级最高故先提
取表达式*/
{
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 '/':
while(op.top == '/'||op.top == '*') /*优先级*/
{
exp[t] = op.data[op.top];
op.top--;
t++;
}
op.top++;
op.data[op.top] = ch;
break;
case ' ': /*忽略空格排除误操作*/
break;
default:
while(ch >= '0'&&ch <= '9')
{
exp[t] = ch;t++;
ch = str[i];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 >= '0'&&ch <= '9') /*从后缀表达式中获取操作数
#作用在此体现*/
{
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 main() /*可以提到前面去*/
{
char str[MaxSize],exp[MaxSize]; /*str为算术表达式,exps为后缀表达式*/
printf("请输入一个求值表达式\n");
gets(str); /*输入一个算术表达式*/
printf("原表达式是:%s\n",str);
translate(str,exp); /*将算术表达式转换成后缀表达式*/
printf("后缀表达式%s\n",exp);
printf("计算结果:%g\n",cal_value(exp));/*通过后缀表达式来求值*/
system("pause");
return 0;
}
7、测试及结果
8、心得
此次实验,经过对计算器的设计与实现,让我对编译原理的基本知识有了深入的了解,加强了对语法分析的认识, 掌握了自上而下语法分析方法、自下而上语法分析方法。熟悉了算符优先分析思想实现语法分析程序。在代码调试过程中结果出现许多无法解释的错误,但仍旧坚持下来了,最终调试出了结果。通过这次实验,我的动手实践能力得到很大的提高。
展开阅读全文