词法分析实验报告

实验一 词法分析
1.实验目的
(1)根据 PL/0 语言的文法规范,编写PL/0语言的词法分析程序;或者调研词法分析程序的自动生成工具LEX或FLEX,设计并实现一个能够输出单词序列的词法分析器。
(2) 通过设计调试词法分析程序,实现从源程序中分出各种单方法;加深对课堂教学的理解;提高词法分析方法的实践能力。
(3)掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的法。
(4)掌握词法分析的实现方法。
(5)上机调试编出的词法分析程序。
2.实验内容
已给 PL/0 语言文法,输出单词符号(关键字、专用符号以及其它标记)。
把词法分析器设计成一个独立一遍的过程。
词法分析器的输出形式采用二元式序列,即:
(单词种类, 单词的值)。

3.实验步骤
(1)写出各个表达式的正则式
关键字的正则式

标识符的正则式

常数的正则式

运算符的正则式

界符的正则式

(2)根据正则式画出NFA

利用以上三条规则对r进行分裂:

(3)根据确定化的NFA画出DFA,并对DFA化简

根据化简规则发现B,D和C,E可以合并
简化后的DFA为:

(4)画出程序的算法流程图

(5)编写代码并测试结果
代码放在附录中(实验总结之后)

4.实验总结
(1)通过先写出正则式到NFA到DFA再到画出程序的流程图,一步一步的优化自己的编程流程,可以在自己脑海中形成清晰的框架,不会出现一些大的方向上的判断错误。
(2)在程序编写时,用到了C++自带的库函数strtok,可以将字符串按照给定的多个一位分割符进行分割,将界符,运算符和其他区分开,便于遍历。在调试程序过程中,一开始在多位运算符号的判定出现问题,字符串数组的下标的值未能及时修改。之后调用修改下标函数专门对下标进行修改。
(3)通过这次实验理解了从正则式到最简DFA的每一步的含义。正规式是正规集的表现形式,通过正规式更好的人工设计成NFA(NFA与正规式的等价性),根据NFA运用子集法转换成DFA,解决了更容易编程问题(DFA和NFA的等价性),最后用最小化简法对DFA进行化简,以达到最简的效果,有利于编程实现。
(4)通过这次实验对于之前学到的词法分析有了进一步的了解,加深了对于词法分析的步骤的理解与领悟。对于今后对编译原理的学习有很大的帮助。
5.附录(实验代码)
#include <bits/stdc++.h> //万能头文件
using namespace std;
string input; //输入全局
int cnt; //全局变量
bool judge (string input, string s) ///判断是否和目标串匹配
{
int i=0;
if (input.length()!=s.length()) return false;
else
{
for(i=0;i<s.length();i++)
{
if(input[i]!=s[i]) return false; ///遍历
}
return true;
}
}
void feifuhao(string p) ///判断非符号的程序,包含判断关键字,标识符,常数
{
if(judge (p,“begin”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“beginsym,”;
cout<<p;
cout<<")\n";
}
else if(judge (p,“call”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“callsym,”;
cout<<p;
cout<<")\n";
}
else if(judge (p,“const”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“constsym,”;
cout<<p;
cout<<")\n";
}
else if(judge (p,“do”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“dosym,”;
cout<<p;
cout<<")\n";
}
else if(judge (p,“end”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“endsym,”;
cout<<p;
cout<<")\n";
}
else if(judge (p,“if”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“ifsym,”;
cout<<p;
cout<<")\n";
}
else if(judge (p,“odd”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“oddsym,”;
cout<<p;
cout<<")\n";
}
else if(judge (p,“procedure”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“proceduresym,”;cout<<p;
cout<<")\n";
}
else if(judge (p,“read”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“readsym,”;cout<<p;
cout<<")\n";
}
else if(judge (p,“var”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“varsym,”;cout<<p;
cout<<")\n";
}
else if(judge (p,“then”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“thensym,”;cout<<p;
cout<<")\n";
}
else if(judge (p,“write”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“writesym,”;cout<<p;
cout<<")\n";
}
else if(judge (p,“while”)) ///判断是否跟目标串相同,相同的话输出结果
{
cout<<"(";
cout<<“whilesym,”;cout<<p;
cout<<")\n";
}
else
{
int flag=0;
for(int i=0;i<p.length();i++)
{
if(!isdigit(p[i])) //判断是否是标识符
{
flag=1;
cout<<"(";
cout<<“ident,”;
cout<<p;
cout<<")\n";
break;
}
}
if(!flag) //判断是否是数字
{
cout<<"(";
cout<<“number,”;
cout<<p;
cout<<")\n";
}
}
}
int change(string aa,int cnt) ///防止多个运算符组成,返回正确下标
{
int x=0;
char f[15]={’+’,’-’,’*’,’/’,’=’,’<’,’>’,’:’,’(’,’)’,’,’,’;’,’.’};
for(int i=0;i<13;i++)
{
if(aa[cnt]f[i])
{
x=i;
}
}
if(x
5)
{
if(aa[cnt+1]’>’) //如果运算符是两个符号组成,cnt+1
{
cnt=cnt+1;
return cnt;
}
else if(aa[cnt+1]
’=’) //判断两个运算符相连
{
cnt=cnt+1;
return cnt;
}
}
if(x==7) //判断:=
{
cnt=cnt+1;
return cnt;

}
return cnt;

}
void fuhao (string aa,int cnt) ///对运算符和界符的输出
{
int x=0;
char f[15]={’+’,’-’,’’,’/’,’=’,’<’,’>’,’:’,’(’,’)’,’,’,’;’,’.’};
for(int i=0;i<13;i++)
{
if(aa[cnt]f[i])
{
x=i;
}
}
if(x
0) cout<<"(plus,+)"<<endl;
if(x1) cout<<"(minus,-)"<<endl;
if(x
2) cout<<"(times,
)"<<endl;
if(x3) cout<<"(slash,/)"<<endl;
if(x
4) cout<<"(eql,=)"<<endl;
if(x5)
{
if(aa[cnt+1]
’>’)
{
cnt=cnt+1;
cout<<"(neq,<>)"<<endl;
}
else if(aa[cnt+1]’=’)
{
cout<<"(leq,<=)"<<endl;
}
else
{
cout<<"(lss,<)"<<endl;
}
}
if(x
6)
{
if(aa[cnt+1]’=’)
{
cout<<"(geq,>=)"<<endl;
}
else
{
cout<<"(gtr,>)"<<endl;
}
}
if(x
7)
{
cout<<"(becomes,:=)"<<endl;
}
if(x8) cout<<"(lparen,()"<<endl;
if(x
9) cout<<"(rparen,))"<<endl;
if(x10) cout<<"(comma,)"<<endl;
if(x
11) cout<<"(semicolon,😉"<<endl;
if(x==12) cout<<"(period,.)"<<endl;
}
int main()
{
string aa;
while(cin>>aa)
{
cnt=0;
const char d = " ±/=<>:(),;.";
char p;
///运用空格和运算符和界符分割字符串并且遍历
char buf[1001] ;
strcpy(buf , aa.c_str()); //字符串转成数组
p = strtok(buf,d); //p是一个char

while§
{
if(aa[cnt]==p[0]) //当前无符号
{
feifuhao§;
cnt=cnt+strlen§;
}
else ///当前是符号
{
fuhao(aa,cnt);
cnt=change(aa,cnt);
cnt=cnt+1;
feifuhao§;
cnt=cnt+strlen§;
}
p=strtok(NULL,d); //下移一位,进行遍历
}
for(int i=cnt;i<aa.length();i++)
{
//cout<<aa[i];
fuhao(aa,i); //防止最后有多个符号
} } return 0;}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值