词法分析器的设计与实现

1、实验目的及要求

1.1、实验目的

        加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。

1.2、实验要求

        1)对单词的构词规则有明确的定义;

        2)编写的分析程序能够正确识别源程序中的单词符号;

        3)识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护符号表;

        4)对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的词法分析;

2、实验步骤

2.1、词法分析规则

        <标识符>::=<字母>|<标识符><字母>|<标识符><数字>

        <常数>::=<数字>|<数字序列><数字>

        <数字序列>::=<数字序列><数字>|<数字>|<.>

        <字母>::=a|b|c|……|x|y|z

        <数字>::=0|1|2|3|4|5|6|7|8|9

        <运算符>::=<关系运算符>|<算术运算符>|<逻辑运算符>|<位运算符>|<赋值运算符>

        <算数运算符>::=+|-|*|/|...|--

        <关系运算符>::=<|>|!=|>=|<=|==

        <逻辑运算符>::=&&| || |!

        <位运算符>::=&| | |!

        <赋值运算符>::==|+=|-=|/=|*=

        <分界符>::=,|;|(|)|{|}|:| // |/**/

        <保留字>::=main|if|else|while|do|for|...|void

2.2、单词符号的编码

单词符号

种别码

单词符号

种别码

main

0

>

26

if

1

>=

27

else

2

<

28

while

3

<=

29

do

4

!

30

for

5

!=

31

switch

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

/=

25

2.3、状态转换图

2.4、算法分析

        ①词法分析器工作的第一步是输入源程序文本。为了更好地对单词符号识别,把输入串预处理一下。预处理主要滤掉空格,跳过注释、换行符等。

        ②对预处理后的输入串依次扫描单个字符,使用if-while嵌套语句和switch case语句判断字符的类型,具体识别方法可看状态转换图。有时为了确定词性,需要超前扫描,若超前扫描的字符对识别当前单词无用处,则需要退还给输入串,以备识别下一单词字符时使用。

        ③若读入的字符与单词符号编码表的字符匹配不上,则报错,并输出出错行数。对识别处的单词符号以(单词符号,种别码)二元式的形式输出。

3、实验内容

3.1、流程图

3.2、程序的变量与函数说明

  • input:全局字符数组,用来存放输入串
  • word:全局字符数组,用来存放获取到的单词符号,限定长度为8
  • ch:全局字符变量,用来存放最新读入的字符
  • syn:全局整型变量,表示单词符号的编码
  • p:全局整型变量,表示当前字符在input数组的位置
  • m:全局整型变量,表示最新读入的字符在word数组的下标
  • line:全局整型变量,当前行数
  • keyword:全局字符数组,存放关键字
  • init():获取输入串
  • isKey():判断关键字的函数,若参数数组中是关键字,则把syn置为该关键字对应的编码并返回1,否则返回0
  • isLetter():判断字母的函数,若参数字符是字母,则返回1,否则返回0
  • isDigit():判断数字的函数,若参数字符是数字,则返回1,否则返回0
  • isSpace():判断空白符的函数,若参数字符是空格、TAB或换行符,则返回1,否则返回0
  • scaner():扫描输入串的函数,对读出的字符进行判断,若是单词符号表中的符号,则将syn置为对应的编码

3.3、源代码

#include <stdio.h>
#include <string.h>char input[1000];//输入串 
char word[8];//获取到的单词 
char ch;
int syn;//种别码 
int p; 
int m;
int line;//行数 
//关键字 
char keyword[][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;elsereturn 0;
}
//判断是不是字母
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();switch(syn){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)
{  //清空word for(m=0;m<8;m++) {word[m] = ' ';} //读取字符 ch=input[p++];m=0;//当ch为空格或换行符时,继续往下读 while(isSpace(ch)){if (ch=='\n'){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和""不是单词符号表中的符号,因而判定输入有错

 

 

 完整实验报告:词法分析器的设计与实现-C文档类资源-CSDN文库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/88657.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Towards Open World Object Detection【论文解析】

Towards Open World Object Detection 摘要1 介绍2 相关研究3 开放世界目标检测4 ORE:开放世界目标检测器4.1 对比聚类4.2 RPN自动标注未知类别4.3 基于能量的未知标识4.4 减少遗忘 5 实验5.1开放世界评估协议5.2 实现细节5.3 开放世界目标检测结果5.4 增量目标检测结果 6 讨论…

Postman

Postman 简介下载安装 简介 Postman 是一款用于测试和开发 API&#xff08;应用程序编程接口&#xff09;的工具&#xff0c;它提供了用户友好的界面和丰富的功能&#xff0c;帮助开发者轻松地创建、测试、调试和文档化各种类型的 API。无论是在构建 Web 应用、移动应用还是其…

2023.08.13 学习周报

文章目录 摘要文献阅读1.题目2.要点3.问题4.解决方案5.本文贡献6.方法6.1 特征选择6.2 时间序列平稳性检测与数据分解6.3 基于GRU神经网络的PM2.5浓度预测 7.实验7.1 网络参数7.2 实验结果7.3 对比实验 8.讨论9.结论10.展望 PINNS模型1.自动微分2.全连接神经网络3.PINNs模型的P…

优雅地处理RabbitMQ中的消息丢失

目录 一、异常处理 二、消息重试机制 三、错误日志记录 四、死信队列 五、监控与告警 优雅地处理RabbitMQ中的消息丢失对于构建可靠的消息系统至关重要。下面将介绍一些优雅处理消息丢失的方案&#xff0c;包括异常处理、重试机制、错误日志记录、死信队列和监控告警等。…

Mac 卸载appium

安装了最新版的appium 2.0.1,使用中各种问题&#xff0c;卡顿....,最终决定回退的。记录下卸载的过程 1.打开终端应用程序 2.卸载全局安装的 Appium 运行以下命令以卸载全局安装的 Appium&#xff1a; npm uninstall -g appium 出现报错&#xff1a;Error: EACCES: permiss…

vue3项目中引入dialog插件,支持最大最小化、还原、拖拽

效果图&#xff1a; 上图是layui-vue组件库中的layer插件&#xff0c;我的项目使用的是element-plus组件库&#xff0c;在用不上layui组件库的情况下&#xff0c;就单独引入layui/layer-vue这个弹层插件就可以了 npm地址&#xff1a;layui/layer-vue - npm layui-vue组件库地址…

推荐几款流行的项目管理系统,助力高效团队协作!

项目式管理是目前非常流行的企业管理方法&#xff0c;这种方法让是如何在确保时间、技术、经费和性能指标的条件下&#xff0c;以尽可能高的效率完成预定目标&#xff0c;让所有与企业相关方满意。在这种模式下&#xff0c;团队的层次关系不再那么重要&#xff0c;大家以项目结…

【对于一维信号的匹配】对一个一维(时间)信号y使用自定义基B执行匹配追踪(MP)研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Android Https

本质&#xff1a;在客户端和服务端使用非对称加密协商出一套对称密钥&#xff0c;每次发送数据前加密&#xff0c;收到后解密&#xff0c;达到加密传输 http ssl 在http之下增加了安全层&#xff0c;用于保障http的加密传输 HTTPS连接 TLS连接步骤 1.客户端发送 client h…

Profibus DP主站转Modbus TCP网关profibus主站模拟软件

捷米JM-DPM-TCP网关。这款产品在Profibus总线侧实现了主站功能&#xff0c;在以太网侧实现了ModbusTcp服务器功能&#xff0c;为我们的工业自动化网络带来了全新的可能。 捷米JM-DPM-TCP网关是如何实现这些功能的呢&#xff1f;首先&#xff0c;让我们来看看它的Profibus总线侧…

HCIP学习--BGP3

目录 前置内容 BGP下一跳的修改问题 BGP的属性 配置 PrefVal权重属性 负载分担 LocPrf 负载分担 NextHop AS-PATH Ogn 配置 MED 配置 BGP选路规则 BGP的社团属性 配置及解释 前置内容 HCIP学习--BGP1_板栗妖怪的博客-CSDN博客 HCIP学习--BGP2_板栗妖怪的博客…

Linux 终端命令之文件浏览(4) head, tail

Linux 文件浏览命令 cat, more, less, head, tail&#xff0c;此五个文件浏览类的命令皆为外部命令。 hannHannYang:~$ which cat /usr/bin/cat hannHannYang:~$ which more /usr/bin/more hannHannYang:~$ which less /usr/bin/less hannHannYang:~$ which head /usr/bin/he…

Baumer工业相机堡盟工业相机如何通过BGAPISDK设置相机的固定帧率(C#)

Baumer工业相机堡盟工业相机如何通过BGAPI SDK设置相机的固定帧率&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机的固定帧率功能的技术背景CameraExplorer如何查看相机固定帧率功能在BGAPI SDK里通过函数设置相机固定帧率 Baumer工业相机通过BGAPI SDK设置相机固定帧…

剑指 Offer 32 - II. 从上到下打印二叉树 II

题目描述 从上到下按层打印二叉树&#xff0c;同一层的节点按从左到右的顺序打印&#xff0c;每一层打印到一行。 示例 思路 采用队列存储二叉树&#xff0c;利用BFS算法对树进行从上到下的层次遍历 如何存储每一层的元素&#xff1f;——利用for循环把当前队列的元素存储进…

计算机基础概论

一、计算机的组成 1.计算机组成的五大部件 &#xff08;1&#xff09;运算器&#xff1a;也叫算术逻辑单元&#xff0c;完成对数据的各种常规运算&#xff0c;如加减乘除&#xff0c;也包括逻辑运算&#xff0c;位移&#xff0c;比较等。 &#xff08;2&#xff09;控制器&a…

Linux 共享内存mmap,进程通信

文章目录 前言一、存储映射 I/O二、mmap&#xff0c; munmap三、父子进程间 mmap 通信四、非血缘关系进程间 mmap 提通信五、mmap 匿名映射区总结 前言 进程间通信是操作系统中重要的概念之一&#xff0c;使得不同的进程可以相互交换数据和进行协作。其中&#xff0c;共享内存…

.bit域名调研

.bit域名研究 问题&#xff1a; .bit域名和ENS域名的相同点&#xff1f;不同点&#xff1f;有什么关系&#xff1f; .bit的定义 .bit 是基于区块链的&#xff0c;开源的&#xff0c;跨链去中心化账户系统.bit 提供了以 .bit 为后缀的全局唯一的命名体系&#xff0c;可用于加密…

SpringBoot复习:(36)国际化

一、Resources目录下建立一个目录&#xff08;比如international)来存储资源文件 message.properties 空的&#xff0c;但不能没有 message_zh_CN.properties hello您好message_en_us.properties hellohello world二、自动配置类MessageSourceAutoConfiguration 常量MESSAGE…

学习笔记整理-JS-02-基本类型

文章目录 一、数据类型简介和检测1. JavaScript中两大数据类型 二、基本数据类型1. 数字类型2. 字符串类型3. 布尔类型4. undefined类型5. null 三、数据类型的转换1. 数据类型的转换 四、重点内容 一、数据类型简介和检测 1. JavaScript中两大数据类型 基本数据类型 Number S…

【Linux 网络】 数据链路层协议

数据链路层协议 数据链路层解决的问题以太网协议认识以太网以太网帧格式 认识MAC地址对比理解MAC地址和IP地址认识MTUMTU对IP协议的影响MTU对UDP协议的影响MTU对于TCP协议的影响ARP协议ARP协议的作用ARP协议的工作流程ARP数据报的格式 总结 数据链路层解决的问题 IP拥有将数据跨…