词法分析程序

news2024/12/29 9:18:34

一、实验原理

1.1实验内容

通过本实验,应达到以下目标:
1.掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。
2.掌握词法分析的实现方法。
3.上机调试编出的词法分析程序。

1.2实验内容

词法分析是作为相对独立的阶段来完成的(对源程序或中间结果从头到尾扫描一次,并作相应的加工处理,生成新的中间结果或目标程序)。在词法分析过程中,编译程序是通过操作系统从外部介质中读取源程序文件中的各个字符的。同时,为正确地识别单词,有时还需进行超前搜紫和回退字符等操作。因此,为了提高读盘效率和便于扫描器进行工作,通常可采用缓冲输入的方案,即在内存中设置一个适当大小的输入缓冲区,让操作系统直接将磁盘上的源程序字符串分批送入此缓冲区中,供扫描器进行处理。

1.3设计过程:

设计函数如下:
int isNum( char c)//判断接收的字符是否是数字
int isLetter(char c)//判断接收的字符是否是字母
char getLetter(char *s)//读取指针所指的字符内容
void Print(char *s,int d)//打印输出信息
void Judge(char *s)//实现有限自动机的功能

二、实验目的

通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。

三、实验步骤

#include<string.h>
#include<stdio.h>
#define	MAX 22             /*分析表的最大容量*/
#define RES_MAX 10        /*关键字的最大长度*/
#define MAXBUF 255         /*缓冲区的大小*/

char ch = ' ';            /*存放读入当前的输入字符*/
int Line_NO;                /*纪录行号*/

struct keywords {  /*关键字*/ 
	char lexptr[MAXBUF];
	int token;
};
struct keywords symtable[MAX];
char str[MAX][10] = {"int", "char", "float", "main", "double", "case", "for", "if", "else", "do", "while", "void", "static", "return", "break", "struct", "const", "switch", "typedef"};

void init() {
	int j;
	for (j = 0; j < MAX; j++) {
		strcpy(symtable[j].lexptr, str[j]);//把右边的复制给左边 
		symtable[j].token = j + 3;//最小的token是int,最大的token是typedef
	}
}

/***************对关键字进行搜索**************/
int Iskeyword(char * is_res) {
	int i;
	for (i = 0; i < MAX; i++) {
		if ((strcmp(symtable[i].lexptr, is_res)) == 0) break;
	}
	if (i < MAX) return   symtable[i].token;
	else return 0;
}

/*****************判断是否为字母*****************/
int IsLetter(char c) {
	if (((c <= 'z') && (c >= 'a')) || ((c <= 'Z') && (c >= 'A'))) return 1;
	else return 0;
}

/*************判断是否为数字**************/
int IsDigit(char c) {
	if (c >= '0' && c <= '9') return 1;
	else return 0;
}

/***************分析程序**************/
void analyse(FILE *fpin, FILE *fpout) {
	/* 输入缓冲区,存放一个单词符号 */
	char arr[MAXBUF];
	int j = 0;
	while ((ch = fgetc(fpin)) != EOF) {
		/*碰到空格、tab则跳过*/
		if (ch == ' ' || ch == '\t') {}
		else if (ch == '\n') {
			Line_NO++;
		}
		/*********************字符串的处理*************************/
		else if (IsLetter(ch)) {
			while (IsLetter(ch) | IsDigit(ch) | ch == '_') {
				if ((ch <= 'Z') && (ch >= 'A'))
					ch = ch + 32; /*忽略大小写,转化成小写*/
				arr[j] = ch;
				j++;
				ch = fgetc(fpin);
			}
			/*输入指针回退一个字符*/
			fseek(fpin, -1L, SEEK_CUR);//后退一个字节;                                设置文件指针fpin的位置
			arr[j] = '\0';
			j = 0;
			if (Iskeyword(arr)) {  /*如果是关键字*/
				fprintf(fpout, "%s\t\t%d\t\t关键字\n", arr, Iskeyword(arr));
			} else
				fprintf(fpout, "%s\t\t%d\t\t标识符\n", arr, 1); /*普通标识符*/
			/*************************数字的处理****************************/
		} else if (IsDigit(ch)) {
			int s = 0;
			while (IsDigit(ch) | IsLetter(ch)) {
				if (IsLetter(ch)) {
					arr[j] = ch;
					j++;
					ch = fgetc(fpin);
					s = 1;
				} else if (IsDigit(ch)) {
					arr[j] = ch;
					j++;
					ch = fgetc(fpin);
				}
			}
			fseek(fpin, -1L, SEEK_CUR);
			arr[j] = '\0';
			j = 0;
			if (s == 0)
				fprintf(fpout, "%s\t\t%d\t\t无符号整数\n", arr, 2) ;
			else if (s == 1)
				fprintf(fpout, "%s\t\t%d\t\t错误\n", arr, 3) ;
		} else switch (ch) {
				case'+' :
					fprintf(fpout, "%s\t\t%d\t\t运算符\n", "+", 41);
					break;
				case'-' :
					fprintf(fpout, "%s\t\t%d\t\t运算符\n", "-", 42);
					break;
				case'*' :
					fprintf(fpout, "%s\t\t%d\t\t运算符\n", "*", 43);
					break;
				case'(' :
					fprintf(fpout, "%s\t\t%d\t\t分界符\n", "(", 25);
					break;
				case')' :
					fprintf(fpout, "%s\t\t%d\t\t分界符\n", ")", 26);
					break;
				case'[' :
					fprintf(fpout, "%s\t\t%d\t\t分界符\n", "[", 27);
					break;
				case']' :
					fprintf(fpout, "%s\t\t%d\t\t分界符\n", "]", 28);
					break;
				case';' :
					fprintf(fpout, "%s\t\t%d\t\t分界符\n", ";", 29);
					break;
				case'=' :
					fprintf(fpout, "%s\t\t%d\t\t运算符\n", "=", 45);
					break;
				case'.' :
					fprintf(fpout, "%s\t\t%d\t\t分界符\n", ".", 30);
					break;
				case',' :
					fprintf(fpout, "%s\t\t%d\t\t分界符\n", ",", 31);
					break;
				case':' :
					fprintf(fpout, "%s\t\t%d\t\t分界符\n", ":", 32);
					break;
				case'{' :
					fprintf(fpout, "%s\t\t%d\t\t分界符\n", "{", 33);
					break;
				case'}' :
					fprintf(fpout, "%s\t\t%d\t\t分界符\n", "}", 34);
					break;
				case'>' : {
					ch = fgetc(fpin);
					if (ch == '=')
						fprintf(fpout, "%s\t\t%d\t\t运算符\n", ">=", 46);
					else {
						fprintf(fpout, "%s\t\t%d\t\t运算符\n", ">", 47);
						fseek(fpin, -1L, SEEK_CUR);
					}
				}
				break;

				case'<' : {
					ch = fgetc(fpin);
					if (ch == '=')
						fprintf(fpout, "%s\t\t%d\t\t运算符\n", "<=", 48);
					else if (ch == '>')
						fprintf(fpout, "%s\t\t%d\n", "<>", 50);
					else {
						fprintf(fpout, "%s\t\t%d\t\t运算符\n", "<", 49);
						fseek(fpin, -1L, SEEK_CUR);
					}
				}
				break;
				/***************出现在/  /之间的全部作为注释部分处理*******************/
				case'/' : {
					ch = fgetc(fpin);
					if (ch == '*') {
						while (ch != '/' && ch != EOF) {
							ch = fgetc(fpin);
						}
						if (ch == EOF)
							fprintf(fpout, "缺少一个'/'");
					} else {
						fprintf(fpout, "%s\t\t%d\t\t运算符\n", "/", 44);
						fseek(fpin, -1L, SEEK_CUR);
					}
				}
				break;
				/***************非法字符*******************/
				default :
					fprintf(fpout, "在第%d行无法识别的字符\t%c\n", Line_NO, ch);
			}
	}
}

int main() {
	char in_fn[25], out_fn[25];
	FILE * fpin, * fpout;

	printf("输入分析目标文件名:\n");
	scanf("%s", in_fn);
	printf("输入要保存分析的目标文件名:\n");
	scanf("%s", out_fn);
	printf("保存成功!\n");
	fpin = fopen(in_fn, "r");
	fpout = fopen(out_fn, "w");
	init();
	analyse(fpin, fpout);
	fclose(fpin);
	fclose(fpout);

	return 0;
}

四、实验结果及分析

在这里插入图片描述

图4.1 可执行应用程序

在这里插入图片描述

图4.2 分析目标文件

在这里插入图片描述

图4.3 保存分析目标文件

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C# 事件

一 C#中的事件 大致上&#xff1a;事件-----回调函数&#xff1b; 二 用户界面中的事件 ① 按钮点击事件 ② 基本的写法 this.button1.Clicknew System.EventHandler(this.button1_Click); private void button1_Click(object sender,EventHandler e) {this.label1.TextDat…

C++智能指针weak_ptr

C智能指针weak_ptr 学习路线&#xff1a;C智能指针shared_ptr->C智能指针unique_ptr->C智能指针weak_ptr 简介&#xff1a;本文讲解常用的智能指针的用法和原理&#xff0c;包括shared_ptr,unique_ptr,weak_ptr。 概述 weak_ptr设计的目的是为配合 shared_ptr 而引入…

静电场方程与边界面上的衔接条件 工程电磁学 P6

我们现在已经知道两个公式 我们可以得到微分形式 对于体密度&#xff0c;面密度&#xff0c;线密度&#xff0c;点电荷的理解 很多同学会问空间中为什么要有面密度&#xff0c;线密度的存在呢&#xff1f; 其实这个是模型的需要&#xff0c;因为介质不一定是连续的&#xff0…

如何设计一个高性能的图 Schema

本文整理自青藤云安全工程师——文洲在青藤云技术团队内部分享&#xff0c;分享视频参考&#xff1a;https://www.bilibili.com/video/BV1r64y1R72i 图数据库的性能和 schema 的设计息息相关&#xff0c;但是 NebulaGraph 官方本身对图 schema 的设计其实没有一个定论&#xff…

Codeforces Round #837 (Div. 2) C. Hossam and Trainees

Problem - C - Codeforces 翻译&#xff1a; 胡萨姆有&#x1d45b;名学员。他给&#x1d456;-th的学员分配了一个号码&#x1d44e;&#x1d456;。 一双&#x1d456;-th和&#x1d457;-th(&#x1d456;≠&#x1d457;)学员被称为成功的如果有一个整数&#x1d465;(&…

基于springboot的企业员工工资管理系统(财务系统)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

Vue渲染器(二):挂载与更新

渲染器&#xff08;二&#xff09;&#xff1a;挂载与更新 前面介绍了渲染器的基本概念和整体框架&#xff0c;接下来就可以介绍渲染器的核心功能&#xff1a;挂载与更新。 1.挂载子节点和元素的属性&#xff1a; vnode.children的值为字符串类型时&#xff0c;会把它设置为…

019 | 在线电影娱乐网站系统设计含论文 | 大学生毕业设计 | 极致技术工厂

作为一个在线电影娱乐网站系统&#xff0c;它展示给浏览者的是各种电影信息&#xff0c;把这些信息能够按用户的需要友好的展示出来是很重要的&#xff0c;同时&#xff0c;能够实现对这些信息的有条不紊的管理也是不可以忽视的。对浏览者和会员的功能而言叫做前台实现&#xf…

[附源码]Node.js计算机毕业设计电子购物商城Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

[附源码]计算机毕业设计电商小程序Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis MavenVue等等组成&#xff0c;B/S模式…

【GRU时序预测】基于卷积神经网络结合门控循环单元CNN-GRU实现时间序列预测附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

代码随想录训练营第49天|LeetCode 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II

参考 代码随想录 题目一&#xff1a;LeetCode 121. 买卖股票的最佳时机 注意这个题只买卖一次&#xff01;&#xff01; 贪心 class Solution { public:int maxProfit(vector<int>& prices) {int low INT_MAX;int result 0;for(int i 0; i < prices.size(…

Redis框架(十):大众点评项目 订单功能 Redis实现全局唯一ID、 秒杀基本环境

大众点评项目 订单功能 秒杀基本环境需求&#xff1a;订单功能 秒杀基本环境Redis实现全局唯一ID业务实现代码总览总结SpringCloud章节复习已经过去&#xff0c;新的章节Redis开始了&#xff0c;这个章节中将会回顾Redis实战项目 大众点评 主要依照以下几个原则 基础实战的Dem…

揭秘!全球2022年Salesforce不同招聘职位的平均薪资

Salesforce可以说是发展最快的企业软件公司。此外&#xff0c;还一直被评选为全球最佳工作场所之一&#xff0c;2021年赢得了Glassdoor评选的最佳工作场所&#xff0c;并且在《财富》杂志的100家最佳工作公司中排名第四。除了非常重视员工福利&#xff0c;强调工作与生活的平衡…

在WSL中配置GPU环境

首先需要明确一点&#xff0c;虽然我们通过安装WSL获得了linux开发环境&#xff0c;但是我们最终使用的GPU还是在windows当中的&#xff0c;所以还是需要在系统中安装对应的驱动。 第一步&#xff1a;在window上根据显卡型号和版本安装驱动 这里参考之前的步骤就行 第二步&a…

HPC走出全新路线:《开放架构HPC技术与生态白皮书》注解

文|智能相对论 作者|叶远风 数字经济大时代&#xff0c;创新驱动大环境&#xff0c;HPC已不再是阳春白雪&#xff0c;而受到越来越多人的关注。 HPC&#xff0c;即High Performance Computing&#xff0c;高性能计算。对普通人来说&#xff0c;没有听过HPC&#xff0c;但肯定…

使用docker-compose搭建mysql主从复制

使用docker-compose搭建mysql主从复制&#xff1a; Mysql的主从【快速】搭建编写脚本编写 master.sh 脚本编写 slave.sh 脚本编写docker-compose.yml文本测试阶段主从同步效果主从环境重启容器被删除&#xff0c;重新启动从节点关闭&#xff0c;主节点继续写入数据从节点删除&a…

[附源码]计算机毕业设计的云网盘设计Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis MavenVue等等组成&#xff0c;B/S模式…

阻塞队列BlockingQueue与同步队列SynchronousQueue

阻塞队列&#xff08;BlockingQueue&#xff09; 什么情况下我们会使用阻塞队列&#xff1f; 多线程并发处理&#xff0c;线程池&#xff01; 使用队列 添加 移除 BlockingQueue四组API 方式有返回值&#xff0c;抛出异常 有返回值&#xff0c;不抛出异常 阻塞等待 超时等待 …

Kubelet v1.25.x源码——StatusManager

1. 环境说明 Kubernetes源码版本&#xff1a;remotes/origin/release-1.25 Kubernetes编译出来的Kubelet版本&#xff1a;Kubernetes v1.24.0-beta.0.2463ee7799bab469d7 Kubernetes集群实验环境&#xff1a;使用Kubernetes v1.25.4二进制的方式搭建了一个单节点集群 K8S 单节…