SNL语言词法编译器----编译原理课程设计1

SNL语言编译器实现与DFA分析 自动机是理论计算机科学和形式语言领域中广泛使用的一种抽象计算模型。在编译器的设计中,自动机对于模式的识别和语言的分析起到了至关重要的作用。根据自动机的特性和功能,我们可以将其分类为非确定性有限自动机(NFA)和确定性有限自动机(DFA)。NFA允许从任意状态出发,在一个输入符号下转移到多个可能的状态,而DFA对于任何给定的输入符号和当前状态,都只能转移到一个唯一的状态。DFA作为NFA的子集,具有以下特点:- 确定性:每个状态对于每个输入符号有且只有一条唯一的转移路径。 阅读详情

 主要思路:从一个文件中,得到一个个的字符,然后对字符进行判断处理,在判断的时候会用到DFA(有限自动机)进行状态之间的转换。

得到的单词主要分为几种类型:标识符、保留字、数字、标点符号、将他们分别进行处理,整理后放在一个token序列中。

token主要由两个部分组成:1)类型  2)内容

程序用到的知识点:

1)C语言文件的读写

举例:

if ((fw = fopen("D:\\jg.txt", "w")) == NULL)
	{
		printf("文件打开失败\n");
		exit(1);
	}
	else {....}

“w”参数部分是指文件的打开方式为只写

“r”只读

“w+”以读写打开方式打开文件,若无此文件,创建文件

“r+”以读写的方式打开文件,若无此文件,出错

*************************************************************************************************************************************************本代码中使用的文件处理函数:

fgetc(f);  //其中f为文件类型指针

ungetc(ch,f);//此函数的作用是将文件类型的指针返回一个位置,char型变量ch,写入这个位置

fprintf(".....",.......);  //将内容写入文件中

2)有限自动机的实现

主要是利用  if  .....else.....语句进行状态之间的转换。

3)全局变量和容器的使用

容器的库include<vector> 

申请一个库:vector<类型>名称

 

 

 

 

 

 

 

实验环境:VS2017

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
//定义两个表,分别为标识符表和常量表,为全局

vector<string>bta;
vector<string>cta;
int error = 0;//定义一个全局变量用来保存是否这个文件存在词法问题

//定义TOKEN结构
class Token
{
public:
	Token(string str, int i) //构造函数
	{
		type = str;
		id = i;
	};
	~Token() {};

	string type;
	int id;
};

class Scan 
{
public:
	bool reservedLookup(string str);//判断是是否为保留字
	Token* scanner(FILE *f);
	int addbta(string str);//查表,若表中含有该标识符返回标识符的id,
							//否则将该标识符加入表中
	int addcta(string str);
	bool Isother(char a);//判断是否为字母和数字以外其他的
	bool Isletter(char a);
	bool Isnumber(char a);
};


bool Scan::reservedLookup(string str) 
{
	printf("%s\n", str.c_str());
	string ta[21] =
	{ "begin","integer","char","program","array","of","record","end","var","proceduce"
		,"if","then","else","fi","while","do","endwh","read","write","return","type" };
	for (int i = 0; i < 21; i++) 
	{
		if (str == ta[i]) 
		{
			cout << "为保留字";
			
			printf("%s\n", str.c_str());
			return true;
		}
	}
	return false;
}

int Scan::addbta(string str) 
{
	for (int i = 0; i < bta.size(); i++) 
	{
		if (str == bta[i])
			return i;
	}
	//没找到,加入
	bta.push_back(str);
	return bta.size() - 1;
}

int Scan::addcta(string str) 
{
	for (int i = 0; i < cta.size(); i++) 
	{
		if (str == cta[i])
			return i;
	}
	cta.push_back(str);
	return cta.size() - 1;
}

bool Scan::Isother(char a) 
{
	if (a >= 'A'&&a <= 'Z')
		return false;
	if (a >= 'a'&& a <= 'z')
		return false;
	if (a >= '0'&& a <= '9')
		return false;
	return true;
}

bool Scan::Isletter(char a) 
{
	if (a >= 'A' && a <= 'Z')
		return true;
	if (a >= 'a'&& a <='z')
		return true;
	return false;
}

bool Scan::Isnumber(char a) 
{
	if (a >= '0' && a <= '9')
		return true;
	return false;
}

Token * Scan::scanner(FILE * f) //用来返回一个Token,然后将其加入到序列中,直到不产生
{
	char ch;
	string str = "";//初始为空串
	Token * t = NULL;
	ch = fgetc(f);
	if (ch != EOF) 
	{
		while (ch == ' ' || ch == '\n' || ch == '\t') 
		{
			ch = fgetc(f);
		}//去掉所有的空格

		//根据第一个字母判断各种状态
		if (Isletter(ch)) //如果第一个字母为英文字母
		{
			cout << "进入标识符状态" << endl;
			str = str + ch;
			ch = fgetc(f);
			while (Isletter(ch) || Isnumber(ch)) 
			{
				cout << "再次进入" << endl;
				str = str + ch;
				ch = fgetc(f);
			}
			if (Isother(ch)) //再次读入的不是一个字符或者数字
			{
				cout << "判断为其他的字符串" << endl;
				//将指针返回一个
				ungetc(ch,f);
				//判断是否为关键字
				if (reservedLookup(str)) 
				{
					//如果是保留字,生成一个新的token
					printf("%s\n", str.c_str());
					t = new Token(str, -2);
					return t;
				}
				else
				{
					//如果为标识符
					int id = addbta(str);
					printf("%s\n", str.c_str());
					t = new Token("标识符", id);
					return t;
				}
			}
		}

		if (Isnumber(ch)) 
		{
			cout << "进入数字状态" << endl;
			//如果第一个字符为一个数字
			str = str + ch;
			ch = fgetc(f);
			while (Isnumber(ch))
			{
				str = str + ch;
				ch = fgetc(f);
			}
			if (Isother(ch)) 
			{
				ungetc(ch, f);
				int id = addcta(str);
				t = new Token("数字", id);
				printf("%s\n", str.c_str());
				return t;
			}
		}

		if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' ||
			ch == ')' || ch == ';' || ch == '[' || ch == ']' || ch == '=')
		{
			cout << "进入运算符号状态" << endl;
			str += ch;
			t = new Token(str, -1);
			printf("%s\n", str.c_str());
			return t;
		}

		if(ch == ':')
		{
			cout << "进入:号状态" << endl;
			str = str + ch;
			ch = fgetc(f);
			if (ch == '=') 
			{
				str = str + ch;
				t = new Token(str, -1);
				printf("%s\n", str.c_str());
				return t;
			}
			else 
			{
				printf("非法符号 %c \n", ch);
				error = 1;
				return NULL;
			}
		}

		if (ch == '{') //注释部分的处理
		{
			cout << "进入注释处理状态" << endl;
			while (ch != '}') 
			{
				ch = fgetc(f);
			}
			t = new Token("zhushi", -4);
			return t;
		}

		if (ch == '.') 
		{
			cout << "进入数组下届判断状态" << endl;
			str = str + ch;
			ch = fgetc(f);
			if (ch == '.') 
			{
				str = str + ch;
				t = new Token("数组下限符", -1);
				printf("%s\n", str.c_str());
				return t;
			}
			else
			{
				return NULL;
			}
		}

		if (ch == ',') 
		{
			cout << "进入逗号判断状态" << endl;
			str = str + ch;
			ch = fgetc(f);
			if (Isnumber(ch) || Isletter(ch)) 
			{
				ungetc(ch, f);
				t = new Token(str, -1);
				printf("%s\n", str.c_str());
				return t;
			}
			else
			{
				str = str + ch;
				printf("非法符号 %s \n", str);
				error = 1;
				return NULL;
			}
		}

		printf("非法符号 %c \n", ch);
		error = 1;
		return NULL;
	}
	else
	{
		return NULL;
	}
}


int main(void) 
{
	FILE *fp;
	if ((fp = fopen("D:\\ce.txt", "r")) == NULL) 
	{
		printf("文件打开失败\n");
		exit(1);
	}


	/*char a;
	a = fgetc(fp);
	printf("%c\n", a);
	cout << "ceshi shifouleyi " << endl;*/

	Scan * scan = new Scan();
	vector<Token>t;//本容器用来存储所有的Token序列
	//申请第一个节点
	Token *token = NULL;
	while ((token = scan->scanner(fp))!= NULL)
	{
		t.push_back(*token);
		token = NULL;
	}
	//关闭文件
	fclose(fp);
	//将得到的list中的内容写到一个新的文件中,这个文件由程序生成。需要调用函数
	int i = 0;

	//判断是是否有错误
	if (error == 1) 
	{
		cout << "有错误" << endl;
	}
	else
	{
		//第一步打印标识符表

		printf("打印标识符表\n");
		for (i; i < bta.size(); i++)
		{
			printf("%d---%s\n", i, bta[i].c_str());
		}

		printf("打印数字表\n");
		for (i = 0; i < cta.size(); i++)
		{
			printf("%d---%s\n", i, cta[i].c_str());
		}

		printf("打印所有的Token序列\n");
		for (i = 0; i < t.size(); i++)
		{
			printf("%d---%s---%d\n", i, t[i].type.c_str(), t[i].id);
		}

	}


	//将所得到的及结果放到一个文件中进行存储
	//这里需要进行文件的写操作

	FILE *fw;
	if ((fw = fopen("D:\\jg.txt", "w")) == NULL)
	{
		printf("文件打开失败\n");
		exit(1);
	}
	else 
	{
		for (i = 0; i < t.size(); i++)
		{
			if (t[i].type != "zhushi") 
			{
				fprintf(fw, "[%s]---[%d]\n", t[i].type.c_str(), t[i].id);
			}
			
		}
		
	}
	fclose(fw);
	system("pause");
	return 0;
}


在编写程序过程中遇到的问题:

1.C语言中string类型的输出:

在采用printf或者cout<<进行输出的时候都会出现乱码的现象,但是利用字符串调用.c_str()函数该现象就会消失

原因:printf函数是针对char*的,故要正确显示,通过c_str()返回首地址。

2)VS2017在使用文件打开或者关闭的时候会出现unsafe错误

处理办法:右键工程名----->属性---->C/C++----->预处理器------>预处理器定义---->在右边的输入框中加入_CRT_SECURE_NO_WARNINGS 然后点击保存。

3)C++中可以使用流的方式读取文件的内容,以getline函数读内容,举例如下:

#include <fstream>




char buffer[256];
	fstream ex("D:\\ce.txt");//注意这个地方一定要是两个\\,否则是识别不出来的
	if (!ex.is_open()) 
	{
		cout << "文件打开失败" << endl;
		exit(0);
	}
	while (!ex.eof()) 
	{
		ex.getline(buffer, 13);
		cout << buffer << endl;
	}

4.字符串可以利用+号直接在后面追加 ,或者可以利用append函数(该函数也是将字符加入当当前字串的尾部)

本文章参考资料:https://blog.youkuaiyun.com/kyt511/article/details/46490845

https://www.cnblogs.com/zyrblog/p/6885922.html

 

 

吉林大学编译原理课程设计与实验解析 编译器是一个复杂的软件系统,负责将高级语言编写的源代码转换成机器语言编写的可执行程序。它涉及到了一系列的处理过程,包括词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等。语义分析是编译过程中的一个关键步骤,它的目的是检查程序中是否存在违反编程语言语义规则的情况。在SNL语言的语义分析阶段,编译器需要确保程序的每个部分都有明确的含义,符合语言定义的语义约束。语义规则通常包括:类型检查:确保表达式中的操作数类型一致,并且符合操作符的要求。作用域规则。 阅读详情

相关推荐

基于SNL语言的编译原理实验项目实战

SNL(Simple Nested Language)是一种为教学和编译器开发实验设计的简化编程语言。其设计初衷是为了降低学习编译器构建过程的门槛,同时具备足够表达能力以演示完整的编译流程。SNL语言在结构上模拟了现代高级语言(如C、Java)的基本语法结构,但去除了复杂的特性,如指针、多线程、泛型等,从而使其更适合教学和编译器实现的原型设计。SNL语言的应用场景主要包括:编译原理教学实验:用于展示词法分析、语法分析、语义分析、中间代码生成等阶段的实现。编译器课程项目。

weixin_32251525的博客 350

编译原理SNL语言编译器实验报告

完成实验内容 实验要求: (1)设计并实现SNL程序设计语言的编译程序 (2)四个必做: 词法分析模块 语法分析模块(递归下降方法) 语法分析模块(LL(1)方法) 语义分析模块 (3)编程语言不限 小组成员任务完成情况 姓名 具体完成任务 工作量占比 语法分析程序(递归下降法和LL1) ...

m0_46475420的博客 3396

SNL编译器设计与实现:词法、语法及语义分析全流程实战

编译器作为连接高级编程语言与机器指令的核心工具,其内部结构具有高度系统化和模块化的特征。本章将从整体视角出发,深入剖析编译器的基本组成模块及其协同工作机制。首先介绍编译过程的五大核心阶段:词法分析、语法分析、语义分析、中间代码生成与优化、目标代码生成,明确各阶段的功能边界与数据传递方式。graph LRA[源代码] --> B(词法分析)B --> C[Token流]C --> D(语法分析)D --> E[语法树]E --> F(语义分析)F --> G[带类型信息的AST]

weixin_34162851的博客 818

snl编译器

天下月色共三分的博客 497

SNL语言编译器VC6.0完整工程:词法语法分析、AST构建、中间代码生成与目标输出

一套可在Visual C++ 6.0环境下直接编译运行的SNL语言编译器源码工程,覆盖编译全流程:scan.cpp实现字符流扫描与词法单元识别;parseLL1.cpp基于LL(1)文法完成自顶向下语法分析;treetodemi.cpp构建抽象语法树并生成midcode.txt中间表示;midtodemi.cpp和tm.cpp进一步处理中间代码;out.cpp输出最终目标代码。配套界面模块(faceView.cpp、faceDoc.cpp、ChildFrm.cpp等)提供可视化交互支持,indialog.c

yellow的专栏 204

深入探索SNLC编译程序及其实现过程

htmltable {th, td {th {pre {简介:编译器是将高级编程语言转换为机器可执行指令的关键工具。SNLC编译器展示了编译过程的各个阶段,包括词法分析、语法分析、语义分析、优化和代码生成。通过分析两个示例文件(a.txt和easy.txt),学习者可以理解编译器如何处理错误和正确源代码,从而编写和调试更高效的程序。本文提供了对编译原理的深入理解,并强调了编程中对底层计算机系统运作的认识的重要性。

weixin_31597759的博客 878

编译原理课程设计实验报告——snl语言

编译原理课程设计实验报告——snl语言 【下载地址】编译原理课程设计实验报告snl语言 本项目展示了编译原理课程设计的核心成果,围绕snl语言编译器的设计与实现展开。实验从词法分析入手,利用有限自动机识别关键字、标识符等基本元素;接着深入语法设计,采用递归下降与LL1分析法构建语法分析器;随后探讨语义规则,确保变量声明、...

gitblog_06799的博客 906

SNL编译器(网页版)

SNL编译器的网页版本,可以实现词法分析,语法分析并画出语法树,语义分析等等

编译原理课程设计---用java写的SNLCompiler(简单嵌套语言SNL的编译程序)

SNLCompiler词法分析截图SNLCompiler的语法分析截图简介:SNLCompiler是一个针对教学语言SNL(Simple Nest Language,其语法与pascal类似)的编译程序,SNLCompiler具有单步执行的功能,可以单独执行词法分析,语法分析等,并显示执行后得到的每一步的详细结果,现在仅提供了词法分析、语法分析中的递归下降法、LL(1)分析方法

fuliangliang的Blog 6236

SNL语言编译器C++实现

从词法分析到目标代码生成 各个部分都有。

SNL编译器java实现

学校SNL语言的编译器java实现,包括词法分析,语法分析,语义分析。有程序界面,非命令行操作。

编译原理课程设计实验报告snl语言:编译的艺术与实现

编译原理课程设计实验报告snl语言:编译的艺术与实现 【下载地址】编译原理课程设计实验报告snl语言 本项目展示了编译原理课程设计的核心成果,围绕snl语言编译器的设计与实现展开。实验从词法分析入手,利用有限自动机识别关键字、标识符等基本元素;接着深入语法设计,采用递归下降与LL1分析法构建语法分析器;随后探讨语义规则,...

gitblog_06735的博客 467

SNL.rar_SNL_compiler_编译器_语义_语义分析

snl编译器还可以语义分析,非常强大,snl是一种教学语言,简单

从零构建SNL语言编译器:C++实现编译原理核心流程详解

编译器是计算机科学的核心系统软件,负责将高级编程语言翻译成机器可执行的低级代码。其工作原理遵循经典的编译流程,主要包括词法分析、语法分析、语义分析、中间代码生成和代码生成等阶段。在工程实践中,通过手写编译器能深入理解抽象语法树(AST)、符号表、类型系统等关键数据结构的底层实现,掌握递归下降语法分析、语法制导翻译等核心算法。这种实践对于构建复杂软件系统、提升对程序运行机制的理解具有重要价值。本文以教学语言SNL为例,详细阐述了如何运用C++17标准,不依赖外部工具,纯手写实现一个完整的编译器,涵盖了从源代码

weixin_30647065的博客 341

Jupyter Notebook 命名出现“error”且运行后没反应

Jupyter Notebook 命名出现“error”且运行后没反应提前声明错误截图(方便大家看看是不是自己的错误)解决方法 提前声明 我的问题是在看到答主 @开始King的回答后才解决的,因为答主大大的文章后面有些地方不是很详细,我在这里再在King大大的基础上完善一下子 错误截图(方便大家看看是不是自己的错误) 1.命名失败,上面出现一个“error”字样 2.运行失败,无论是点击上方的运行按钮还是按快捷键shift+enter 都只会向下再增加一个代码块,而不会运行程序。 (也不是很多人出现的[*

qq_52770743的博客 1万+

金仓数据库KCM认证考试介绍【2025年4月更新】

金仓数据库认证资深专家KCM认证考试介绍

qq709869231的博客 3227

词法分析器

这学期的编译原理要做一个完整的编译器,我选择了SNL,这两天把词法分析器写了,话说用java正不习惯;稍微注意了一下写注释 好吧,这个词法分析器其实很简单,就是切词,然后把切出来的词归类,分成保留字,符号,变量等等 从一个source.txt中读取源程序,然后产生一个token链 好吧直接上代码: scanner.java:(主要)   /**********************/

李世操的空间 1620

微信自动化必备软件:inspect(获取微信界面元素)

SaveButton10015.2:1 ✅(合格)Passed ✅说明这个控件完全符合无障碍标准。

Ven%的博客 1381

SNL编译器开发

 最近编译原理实验课,要求我们做一个SNL语言的语法词法分析器,用时四周。接下来几周我将记录每天的工作。   第一天就简要介绍下SNL的语言吧(简单的具有嵌套过程的程序设计语言),Small NestedLanguage(SNL)即简单的具有嵌套过程的程序设计语言,是一种教学用的过程式语言,最初由《编译程序的设计与实现》一书的作者设计并实现了其编译程序(SNLC)。该语言具有标准数据类...

weixin_30516243的博客 1223

Synares病毒实战:如何手动清除C盘隐藏的Synaptics.exe(附资源修复脚本)

本文详细介绍了Synares感染型病毒的手动清除方法,该病毒伪装成Synaptics触摸板驱动,感染EXE和XLSX文件。文章提供了从病毒行为分析、母体清除到被感染文件修复的全流程指南,并附有实用的资源修复脚本和防御加固方案,帮助用户彻底清除这一顽固病毒。

lg888的博客 2348

Hugging Face快速入门(重点讲解模型(Transformers)和数据集部分(Datasets))

1. Hugging Face是什么,提供了哪些内容 2. Hugging Face模型的使用(Transformer类库) 3. Hugging Face数据集的使用(Datasets类库)

iioSnail的博客 8万+

【免费下载】 SNL语言编译器:C++实现的编译原理学习利器

SNL语言编译器:C++实现的编译原理学习利器 【下载地址】SNL语言编译器C实现 本仓库提供了一个完整的SNL语言编译器的C++实现。该编译器涵盖了从词法分析到目标代码生成的各个部分,为学习和研究编译原理提供了宝贵的参考资源 项...

gitblog_09704的博客 847

动态SLAM中的YOLO与ORB-SLAM3融合:实时目标检测与动态点云滤除实战

本文介绍了如何结合YOLOv5目标检测与ORB-SLAM3视觉SLAM系统,实现动态环境下的目标检测与视觉SLAM任务。文章详细阐述了从源码下载、依赖安装(包括libtorch配置)、编译运行步骤(包括ROS环境和非ROS环境下的编译方法),到RGBD-TUM数据集准备与关联处理的全流程。同时针对常见错误提供了解决方案,如libtorch路径配置、ROS环境冲突等。最后展示了系统运行方法,并探讨了未来可能的优化方向,包括增强目标检测能力和改进动态环境下的地图构建。该集成系统为机器人智能导航和环境感知提供了有

LXY_LOVE36的博客 237
上一篇: 编程练习3:ASCII码排序
下一篇: MVC模式主要架构代码及思路
coding_diamond
博客等级 码龄8年 8粉丝 131原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值