【编译原理】词法分析(C/C++源代码+实验报告)

article/2025/11/1 12:48:28

文章目录

    • 1 实验目的和内容
      • 1.1实验目的
      • 1.2实验内容
    • 2 设计思想
      • 2.1单词种类及其正规式
      • 2.2 根据正规式构造NFA
      • 2.3根据NFA构造DFA
        • 2.3.1根据替换规则构造未化简的DFA
        • 2.3.2最小化DFA
    • 3算法流程
    • 4源程序
    • 5调试数据
      • 5.1 测试样例一
      • 5.2 测试样例二
      • 5.3 测试样例三
    • 6实验调试情况及体会
      • 6.1 实验调试情况
      • 6.2 实验体会

1 实验目的和内容

1.1实验目的

(1)根据 PL/0 语言的文法规范,编写PL/0语言的词法分析程序;或者调研词法分析程序的自动生成工具LEX或FLEX,设计并实现一个能够输出单词序列的词法分析器。

(2)通过设计调试词法分析程序,实现从源程序中分离出各种类型的单词;加深对课堂教学的理解;提高词法分析方法的实践能力。

(3)掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。

(4)掌握词法分析的实现方法。

(5)上机调试编出的词法分析程序。

1.2实验内容

根据PL/0语言的文法规范,编写PL/0语言的词法分析程序。要求:

(1)把词法分析器设计成一个独立一遍的过程。

(2)词法分析器的输出形式采用二元式序列,即:(单词种类, 单词的值)

2 设计思想

2.1单词种类及其正规式

(1)基本字

单词的值单词类型正规式r
beginbeginsymbegin
callcallsymcall
constconstsymconst
dodosymdo
endendsymend
ififsymif
oddoddsymodd
procedureproceduresymprocedure
readreadsymread
thenthensymthen
varvarsymvar
whilewhilesymwhile
writewritesymwrite

(2)标识符

单词的值单词类型正规式r
标识符ident(字母)(字母|数字)*

(3)常数

单词的值单词类型正规式r
常数number(数字)(数字)*

(4)运算符

单词的值单词类型正规式r
+plus+
-minus-
*times*
/slash/
=eql=
<>neq<>
<lss<
<=leq<=
>gtr>
>=geq>=
:=becomes:=

(5)界符

单词的值单词类型正规式r
(lparen(
)rparen)
comma
semicolon
.period.

2.2 根据正规式构造NFA

下面我们根据上述的正规式来构造该文法的NFA,如下图所示,其中状态0为初态,凡带双圈的状态均为终态,状态24是识别不出单词符号的出错情形,其他状态的识别情况如下图中右边的注释所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OhJ7v6Vz-1634111070587)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps31BD.tmp.jpg)]

图1 根据正规式构造的NFA

2.3根据NFA构造DFA

2.3.1根据替换规则构造未化简的DFA

替换规则如下图所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HFAVteHG-1634111070596)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps31BE.tmp.png)]

图2 替换规则

根据替换规则对NFA进行分裂,结果如下图所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3vOblCqT-1634111070603)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps31BF.tmp.jpg)]

图3 未化简DFA

2.3.2最小化DFA

一个确定有限自动机M的化简是指,寻找一个状态数比M少的DFA M’,使得L(M)=L(M’)。一个DFA M的状态最小化过程旨在将M的状态集分割成一些不相交的子集,使得任何不同的两子集中的状态都是可区别的,而同一子集中的任何两个状态都是等价的。最后,在每个子集中选一个代表,同时消去其它的等价状态。

最小化后的DFA如下图所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YVEoWkgp-1634111070618)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps31C0.tmp.jpg)]

图4 最小化DFA

3算法流程

词法分析程序的输入是源程序,输出是一个个单词符号的二元组,它的任务是从左至右逐个字符地对源程序进行扫描,产生一个个的单词符号,把作为字符串的源程序改造成为单词符号串的中间程序。

首先逐行扫描源程序,然后遍历串的每一个字符,判断字符是不是空格、数学、字母、运算符或者界符,再进行下一步的判断,如果不符合这几种情况,将会归入出错处理。完整算法流程如下图所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b7U8mCuv-1634111070621)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps31C1.tmp.jpg)]

图5 算法流程图

4源程序

#include <iostream>
#include <string>
using namespace std;//用于识别是基本字或标识符
void Letter(string str)
{//识别基本字if(str=="begin")cout<<"(beginsym,begin)"<<endl;else if(str=="call")cout<<"(callsym,call)"<<endl;else if(str=="const")cout<<"(constsym,const)"<<endl;else if(str=="do")cout<<"(dosym,do)"<<endl;else if(str=="end")cout<<"(endsym,end)"<<endl;else if(str=="if")cout<<"(ifsym,if)"<<endl;else if(str=="odd")cout<<"(oddsym,odd)"<<endl;else if(str=="procedure")cout<<"(proceduresym,procedure)"<<endl;else if(str=="read")cout<<"(readsym,read)"<<endl;else if(str=="then")cout<<"(thensym,then)"<<endl;else if(str=="while")cout<<"(whilesym,while)"<<endl;else if(str=="var")cout<<"(varsym,var)"<<endl;else if(str=="write")cout<<"(writesym,write)"<<endl;//识别标识符elsecout<<"(ident,"<<str<<")"<<endl;
}int main()
{string str1,str;while(cin>>str1){//读入代码(字符串形式)str = str+' '+str1;}//开始处理读入的代码int length_str = str.length();for(int i=0;i<length_str;i++){//当遇到空格或换行时,跳过继续执行if(str[i]==' ' || str[i]=='\n') continue;//识别常数else if(isdigit(str[i])){string digit;//以字符串形式表示这个常数while(isdigit(str[i])){digit +=str[i];i++;}i--;cout<<"(number,"<<digit<<")"<<endl;}//识别基本字或标识符else if(isalpha(str[i])){string lett;//以字符串形式表示这个基本字或者标识符while(isdigit(str[i])||isalpha(str[i])){lett +=str[i];i++;}i--;Letter(lett);}//识别运算符else{switch(str[i]){case '+':cout<<"(plus,+)"<<endl;break;case '-':cout<<"(minus,-)"<<endl;break;case '*':cout<<"(times,*)"<<endl;break;case '/':cout<<"(slash,/)"<<endl;break;case '=':cout<<"(eql,=)"<<endl;break;case '<':i++;if(str[i]=='>'){cout<<"(neq,<>)"<<endl;}else if(str[i]=='='){cout<<"(leq,<=)"<<endl;}else{i--;cout<<"(lss,<)"<<endl;}break;case '>':i++;if(str[i]=='='){cout<<"(geq,>=)"<<endl;}else{i--;cout<<"(gtr,>)"<<endl;}break;case ':':i++;if(str[i]=='='){cout<<"(becomes,:=)"<<endl;}break;//识别界符case '(':cout<<"(lparen,()"<<endl;break;case ')':cout<<"(rparen,))"<<endl;break;case ',':cout<<"(comma,,)"<<endl;break;case ';':cout<<"(semicolon,;)"<<endl;break;case '.':cout<<"(period,.)"<<endl;break;//错误处理default:cout<<"error"<<endl;break;}}}cout<<"Yes,it is correct."<<endl;return 0;
}

5调试数据

5.1 测试样例一

【样例输入】
const a=10;
var b,c;
begin
read(b);
c:=a+b;
write(c)
end. 【样例输出】
(constsym,const)
(ident,a)
(eql,=)
(number,10)
(semicolon,;)
(varsym,var)
(ident,b)
(comma,,)
(ident,c)
(semicolon,;)
(beginsym,begin)
(readsym,read)
(lparen,()
(ident,b)
(rparen,))
(semicolon,;)
(ident,c)
(becomes,:=)
(ident,a)
(plus,+)
(ident,b)
(semicolon,;)
(writesym,write)
(lparen,()
(ident,c)
(rparen,))
(endsym,end)
(period,.)

样例一结果如下所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CAa5qua2-1634111070628)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps3201.tmp.jpg)]

图6 样例一测试结果

5.2 测试样例二

【样例输入】
const a=10;
var b,c,d;
begin
read(b);
read(c);
d:=a+b+c;
write(d)
end. 【样例输出】
(constsym,const)
(ident,a)
(eql,=)
(number,10)
(semicolon,;)
(varsym,var)
(ident,b)
(comma,,)
(ident,c)
(comma,,)
(ident,d)
(semicolon,;)
(beginsym,begin)
(readsym,read)
(lparen,()
(ident,b)
(rparen,))
(semicolon,;)
(readsym,read)
(lparen,()
(ident,c)
(rparen,))
(semicolon,;)
(ident,d)
(becomes,:=)
(ident,a)
(plus,+)
(ident,b)
(plus,+)
(ident,c)
(semicolon,;)
(writesym,write)
(lparen,()
(ident,d)
(rparen,))
(endsym,end)
(period,.)

样例二结果如下所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jq1UW1qK-1634111070632)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps3202.tmp.jpg)]

图7 样例二测试结果

5.3 测试样例三

【样例输入】
const a=10;
const b=10;
var c;
begin
c:=a+b;
write(c)
end.【样例输出】
(constsym,const)
(ident,a)
(eql,=)
(number,10)
(semicolon,;)
(constsym,const)
(ident,b)
(eql,=)
(number,10)
(semicolon,;)
(varsym,var)
(ident,c)
(semicolon,;)
(beginsym,begin)
(ident,c)
(becomes,:=)
(ident,a)
(plus,+)
(ident,b)
(semicolon,;)
(writesym,write)
(lparen,()
(ident,c)
(rparen,))
(endsym,end)
(period,.)

样例三结果如下所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w7rpU4Kf-1634111070634)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps3203.tmp.jpg)]

图8 样例三测试结果

6实验调试情况及体会

6.1 实验调试情况

由上一步中的三个测试样例可以得到,所有的测试样例均得到了相应的输出结果,说明代码编写成功,并且在代码中设置了出错处理,以便解决其他情况。

6.2 实验体会

本次实验通过先写出正规式到NFA到DFA再到画出程序的流程图,一步一步地优化自己的编程流程,可以在自己脑海中形成清晰的框架,不会出现一些大的方向上的判断错误。同时也理解了从正规式到最小化DFA的每一步的含义。正规式是正规集的表现形式,通过正规式更好的人工设计成NFA(NFA与正规式的等价性),根据NFA运用子集法转换成DFA,解决了编程问题(DFA和NFA的等价性),最后用最小化简法对DFA进行化简,以达到最简的效果,有利于编程实现。

在程序编写时,用到了C++自带的头文件string,可以很好地处理输入串并对串进行分割,将界符、运算符和其他区分开,便于遍历。在调试程序过程中,一开始出现空格和换行无法识别的情况,于是就把这种情况单独编写了一个函数进行识别,便于串的后续识别。

通过这次实验对之前学到的词法分析有了进一步的了解,加深了对于词法分析的步骤的理解与领悟,对于今后对编译原理的学习有很大的帮助。

最后,感谢刘善梅老师和其他同学在这次实验中给予我的帮助,不胜感激!


http://chatgpt.dhexx.cn/article/Ovx90v8L.shtml

相关文章

session 每次请求都会产生新的sessionID

问题描述&#xff1a; 最近在写一个项目时&#xff0c;在运行项目后每刷新一次都会产生一个新的Session ID&#xff0c;导致无法取值。 原因分析&#xff1a; 搞了很久发现是URL路径的问题&#xff0c;把http://localhost:8080//的双斜杠该为单斜杠就行了 解决方案&#xf…

JavaWeb - Cookie、Session、SessionId 详解

一、概述 会话&#xff08;Session&#xff09;跟踪是Web程序中常用的技术&#xff0c;用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份&#xff0c;Session通过在服务器端记录信息确定用户身份。 本章将系统地讲述Co…

JSESSIONID和sessionid的区别

要保持登陆状态&#xff0c;但是sessionid 和 JSESSIONID的值不一致&#xff0c; 情况一&#xff1a;部署到测试机上&#xff0c;利用本机登陆网页&#xff0c;sessionid和jsessionid不一样。 情况二&#xff1a;部署在本机&#xff0c;本机登陆页面&#xff0c;sessionid和js…

关于两次访问接口的sessionid不一致问题

在测试验证邮箱、注册逻辑时&#xff0c;出现验证码错误的问题。验证码是存放在session内的&#xff0c;在排除了逻辑代码的问题后&#xff0c;检查出这两次访问接口的sessionid并不一致&#xff0c;而在swagger测试接口时是一致的。因此我比较了swagger与ajax请求/响应头的区别…

cookie、session、sessionid 与jsessionid

cookie、session、sessionid 与jsessionid&#xff0c;要想明白他们之间的关系&#xff0c;下面来看个有趣的场景来帮你理解。 我们都知道银行&#xff0c;银行的收柜台每天要接待客户存款/取款业务&#xff0c;可以有几种方案&#xff1a; 凭借柜台职员的记忆&#xff0c;由收…

如何根据sessionID获取session解决方案

点个赞&#xff0c;看一看&#xff0c;好习惯&#xff01;本文 GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录&#xff0c;这是我花了3个月总结的一线大厂Java面试总结&#xff0c;本人已拿腾讯等大厂offer。 另外&#xff0c;原创文章首发在我的个人博客&#…

sessionId的生成过程和过期时间

支持作者 最便宜的卫生纸 浏览器第一次请求服务器时&#xff0c;服务器会生成一个sessionId&#xff0c;并返回给浏览器&#xff0c;这个sessionId会被保存在浏览器的会话cookie中。如下图 在浏览器不关闭的情况下&#xff0c;之后的每次请求请求头都会携带这个sessionId到服务…

session,sessionid,cookie之间的关系解析

session&#xff0c;sessionid&#xff0c;cookie之间的关系解析 文章目录 session&#xff0c;sessionid&#xff0c;cookie之间的关系解析1.简介2.session和cookie定义&#xff0c;创建&#xff0c;周期和联系2.1cookie2.2session 3.如果禁用cookie后&#xff0c;如何解决账号…

dubbox拦截器配置

dubbo是一个被国内很多互联网公司广泛使用的开源分布式服务框架&#xff0c;即使从国际视野来看应该也是一个非常全面的SOA基础框架。作为一个重要的技术研究课题&#xff0c;在当当网我们根据自身的需求&#xff0c;为Dubbo实现了一些新的功能&#xff0c;并将其命名为Dubbox&…

Springboot+Dubbox 提供Rest服务实践

背景 在开发过程中&#xff0c;dubbo接口自测时&#xff0c;通过控制台的invoke方式调用dubbo服务不方便&#xff0c;主要体现在入参设置和入参保存上&#xff08;invoke方式调用dubbo服务请参考&#xff1a;命令行中调用dubbo服务及入参写法_Ypc_victor的专栏-CSDN博客&#…

Dubbo2

一、基础知识 1、分布式基础理论 1.1&#xff09;、什么是分布式系统&#xff1f; 《分布式系统原理与范型》定义&#xff1a; “分布式系统是若干独立计算机的集合&#xff0c;这些计算机对于用户来说就像单个相关系统” 分布式系统&#xff08;distributed system&#…

Dubbox 是什么?

1. Dubbo是什么&#xff1f; Dubbo是一个分布式服务框架&#xff0c;致力于提供高性能和透明化的RPC远程服务调用方案&#xff0c;以及SOA服务治理方案。简单的说&#xff0c;dubbo就是个服务框架&#xff0c;如果没有分布式的需求&#xff0c;其实是不需要用的&#xff0c;只…

分布式服务框架 dubbo/dubbox 入门示例

http://www.cnblogs.com/Javame/p/3632473.html 1. Dubbo是什么&#xff1f; Dubbo是一个分布式服务框架&#xff0c;致力于提供高性能和透明化的RPC远程服务调用方案&#xff0c;以及SOA服务治理方案。简单的说&#xff0c;dubbo就是个服务框架&#xff0c;如果没有分布式的…

SpringBoot整合Dubbox(无XML配置)

##简介 Dubbox是当当网对阿里的Dubbo进行增强的一个分支。在使用springboot之后&#xff0c;我们发现很多配置并不一定要使用xml。这篇文章的目的是让你使用Dubbox时能像使用springboot的其它功能一样可以在application.properties中配置。 ##基础整合 进入https://github.co…

Dubbo进阶(十一)—— Dubbo与DubboX区别

前世今生 Dubbo源于阿里的淘宝网开源分布式服务架构&#xff0c;致力于提供高性能和透明化的RPC远程服务调用方案&#xff0c;是SOA服务化治理方案的核心框架。淘宝网将其开源之后&#xff0c;得到了很多的拓展和支持&#xff08;比较出名的有&#xff1a;当当网的扩展版本dub…

[Dubbox基础]-- 文档

一、网址 官方&#xff1a;https://github.com/dangdangdotcom/dubbox 参考&#xff1a;https://www.douban.com/note/488997143/ 二、说明 1、问题&#xff1a;https://github.com/dangdangdotcom/dubbox/issues 2、主要&#xff1a; Dubbox now means Dubbo eXtensions. …

浅谈Dubbox原理

Dubbox介绍 Dubbox是一个分布式服务框架&#xff0c;前身是阿里旗下的开源项目Dubbo&#xff0c;后来阿里停止维护&#xff0c;当当网在Dubbo的基础上进行优化&#xff0c;并继续维护&#xff0c;为了与原来的Dubbo区分故将其改名为Dubbox&#xff0c;当当网在其原有的基础上实…

Dubbox 和Dubbo 为何选择

1. 前言 随着现在互联网行业的发展&#xff0c;越来越多的框架、中间件、容器等开源技术不断地涌现&#xff0c;更好地来服务于业务&#xff0c;解决实现业务的问题。然而面对众多的技术选择&#xff0c;我们要如何甄别出适合自己团队业务的技术呢&#xff1f;对于人来说&#…

springboot整合dubbox

简介 今天咱们来看看怎么利用Spring Boot整合Dubbox来开发去中心化的微服务。 系统环境 本文基于Jdk1.8/Maven 3.3.9/Spring Boot 1.4.2.RELEASE/Dubbo 2.8.5.SNAPSHOT(Dubbox后续开源版本)/ZooKeeper3.4.8 Zookeeper环境搭建 下载并安装启动 下载 wget http://mirrors.h…

Dubbo

协议&#xff1a; Dubbo是一种分布式服务框架也是一种协议&#xff0c;dubbo框架默认使用dubbo协议。dubbo协议是阿里巴巴自己实现的一种应用层协议&#xff0c;传输层还是TCP。所以Dubbo协议与HTTP、FTP&#xff0c;SMTP这些应用层协议是并列的概念。除了默认的Dubbo协议&…