词法分析器的设计与实现

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;
	else
		return 0;
}
//判断是不是字母
int isLetter(char c)
{
	if ((c<='z'&&c>='a')||(c>='A'&&c<='Z'))
		return 1;
	else
		return 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文库

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows - UWP - 为UWP应用创建桌面快捷方式

Windows - UWP - 为UWP应用创建桌面快捷方式 前言 这是一个较为简单的方式&#xff0c;不需要过多的命令行。 How 首先Win R -> shell:AppsFolder -> 回车&#xff0c; 这将显示电脑上的已安装应用&#xff08;Win32 & UWP&#xff09;&#xff1a; 找到想要创建…

38 | 浦发银行股票分析案例

本文将通过一个浦发银行股票分析案例,探讨如何从多个维度对股票进行分析,包括基本面、技术面和市场环境等因素。我们将深入挖掘浦发银行的财务数据、业务模式以及市场定位,以了解其内在价值和潜在风险。同时,我们还将考察技术面的指标,如价格走势、均线形态等,以揭示市场…

计算机网络—IP

这里写目录标题 IP的基本认识网络层与数据链路层有什么关系IP地址基础知识IP 地址的分类什么是A、B、C类地址广播地址用来做什么什么是D、E类广播多播地址用于什么IP分类的优点IP分类的缺点 无分类地址CIDR如何划分网络号和主机号怎么进性子网划分 公有 IP 地址与私有 IP 地址公…

java操作mongdb【超详细】

Java操作 搭建 搭建 依赖 <!--mongodb--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>配置文件 spring:data:mongodb:host…

回归预测 | MATLAB实现基于SSA-KELM-Adaboost麻雀算法优化核极限学习机结合AdaBoost多输入单输出回归预测

回归预测 | MATLAB实现基于SSA-KELM-Adaboost麻雀算法优化核极限学习机结合AdaBoost多输入单输出回归预测 目录 回归预测 | MATLAB实现基于SSA-KELM-Adaboost麻雀算法优化核极限学习机结合AdaBoost多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本…

Django配置(部署环境较乱,暂时启用)

django配置 web服务器中部署项目及WSGI简介 web服务器 WSGI 在IIS中部署django项目 安装 wfastcgi &#xff1a;pip install wfastcgi安装IIS&#xff1a; 以上选择项勾选后确定 将CGI文件复制到项目中&#xff0c; 将项目复制到IIS默认目录中 部署IIS 添加变量信息如下…

定义行业新标准?谷歌:折叠屏手机可承受20万次折叠

根据Patreon账户上的消息&#xff0c;Android专家Mishaal Rahman透露&#xff0c;谷歌计划推出新的硬件质量标准&#xff0c;以满足可折叠手机市场的需求。Android原始设备制造商&#xff08;OEM&#xff09;将需要完成谷歌提供的问卷调查&#xff0c;并提交样品设备进行严格审…

计算机网络 ARP协议 IP地址简述

ARP只能在一个链路或一段网络上使用

【设计模式——学习笔记】23种设计模式——解释器模式Interpreter(原理讲解+应用场景介绍+案例介绍+Java代码实现)

案例引入 通过解释器模式来实现四则运算&#xff0c;如计算ab-c的值&#xff0c;具体要求 先输入表达式的形式&#xff0c;比如abc-de&#xff0c;要求表达式的字母不能重复在分别输入a,b,c,d,e的值最后求出结果 传统方案 编写一个方法&#xff0c;接收表达式的形式&#xf…

【设计模式】MVC 模式

MVC 模式代表 Model-View-Controller&#xff08;模型-视图-控制器&#xff09; 模式。这种模式用于应用程序的分层开发。 Model&#xff08;模型&#xff09; - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑&#xff0c;在数据变化时更新控制器。View&#xff…

MES系统在机器人行业生产管理种的运用

机器人的智能水平也伴随技术的迭代不断攀升。 2021年的春晚舞台上&#xff0c;来自全球领先工业机器人企业abb的全球首款双臂协作机器人yumi&#xff0c;轻松自如地表演了一出写“福”字&#xff0c;赢得了全国观众的赞叹。 在汽车装配领域&#xff0c;一台机器人可以自主完成一…

OpenCV实例(八)车牌字符识别技术(一)模式识别

车牌字符识别技术&#xff08;一&#xff09;模式识别 1.模式识别流程2. 模式识别方式 影响并导致汽车牌照内字符出现缺损、污染、模糊等情况的常见因素有照相机的性能、采集车辆图像时光照的差异、汽车牌照的清洁度等。为了提高汽车牌照字符识别的准确率&#xff0c;本节将把英…

数学分析:曲线曲面积分

这一章还是很重要的&#xff0c;可以看到为什么dt1^dt2和dt1dt2是一样的。 可以看到&#xff0c;核心还是黎曼和&#xff0c;我们把两种微分的黎曼和都列出来&#xff0c;并且证明两个相等&#xff0c;即可。 这里要注意&#xff0c;微分形式的积分&#xff0c;在黎曼和的情况…

【CheatSheet】Python、R、Julia数据科学编程极简入门

《Python、R、Julia数据科学编程极简入门》PDF版&#xff0c;是我和小伙伴一起整理的备忘清单&#xff0c;帮助大家10分钟快速入门数据科学编程。 另外&#xff0c;最近 TIOBE 公布了 2023 年 8 月的编程语言排行榜。 Julia 在本月榜单中实现历史性突破&#xff0c;成功跻身 …

PyTorch 微调终极指南:第 1 部分 — 预训练模型及其配置

一、说明 如今&#xff0c;在训练深度学习模型时&#xff0c;通过在自己的数据上微调预训练模型来迁移学习已成为首选方法。通过微调这些模型&#xff0c;我们可以利用他们的专业知识并使其适应我们的特定任务&#xff0c;从而节省宝贵的时间和计算资源。本文分为四个部分&…

LabVIEW开发图像采集和基于颜色的隔离

LabVIEW开发图像采集和基于颜色的隔离 在当今的工业和工厂中&#xff0c;准确性和精度是决定特定行业生产力的两个重要关键点。为了优化生产力&#xff0c;各行各业正在从手动操作转向自动操作和控制。机器人技术在工业过程中的出现为人类提供了机械辅助。机器视觉在工业机器人…

flask-migrate使用

1.介绍 # 表,字段发生变化&#xff0c;都会有记录&#xff0c;自动同步到数据库中--》django支持这种操作 # 原生的sqlalchemy&#xff0c;不支持修改表的 # flask-migrate可以实现类似于django的 python manage.py makemigrations #记录 python manage.py migrate …

【【萌新的STM32学习-8】】

萌新的STM32学习-8 STM32CubeMX 是由 ST 公司开发的图形化代码自动生成工具&#xff0c;能够快速生成初始化代码&#xff0c; 如配置 GPIO&#xff0c;时钟树&#xff0c;中间件等&#xff0c;使用户专注于业务代码的开发。现在 ST 主推 HAL 库代码&#xff0c; 经典的标准外设…

数据结构【第4章】——栈与队列

队列是只允许在一端进行插入操作、而在另-端进行删除操作的线性表。 栈 栈与队列&#xff1a;栈是限定仅在表尾进行插入和删除操作的线性表。 我们把允许插入和删除的一端称为栈顶&#xff08;top&#xff09;&#xff0c;另一端称为栈底&#xff08;bottom&#xff09;&…

【大数据】Flink 详解(二):核心篇 Ⅱ

Flink 详解&#xff08;二&#xff09;&#xff1a;核心篇 Ⅱ 22、刚才提到 State&#xff0c;那你简单说一下什么是 State。 在 Flink 中&#xff0c;状态 被称作 state&#xff0c;是用来保存中间的计算结果或者缓存数据。根据状态是否需要保存中间结果&#xff0c;分为 无状…