编译原理实验1 - 词法分析器

词法分析

实验目的:设计编制并调制一个词法分析程序

实验要求:

1.待分析的简单词法

(1)关键字:begin,if,then,while,do,then

(2)运算符和界限符:  := , +,-,*,/,<, <=, <>, >, >=, = ;,,(,),#

(3)其他单词是标识符(ID)和整形常量(NUM),以下是正规是定义

         ID = letter(letter|digital)*

         NUM = digital digital*

(4)空格由空白,制表符和换行符组成,空格一般用来分割ID,NUM,运算符,界限符,保留字,词法分析阶段一般被忽略

2.各种单词符号对应的特种码

3.词法分析器程序的功能

输入:所给文法的源程序字符串

输出:二元组序列

核心代码介绍:

保留字查询

int searchReserve(char reserveWord[][20], char s[])
{
	for (int i = 0; i < 6; i++)
		if (strcmp(reserveWord[i], s) == 0)  return i + 1;
	return -1;//否则返回-1,代表查找不成功,即为标识符
}

保留字检索函数,由于只有6个保留字,没有在关键字查找里面使用自动机,而是采用的暴力破解直接匹配

两个简单的函数判断是否是字母或者数字,内联函数

bool IsLetter(char letter);			//字母	
bool IsDigital(char digital);		//数字	

修饰函数:除去源代码中的注释多余空格

int CodeProcessing(char str[], int iProjectLong);		//修饰

两个输出函数,错误输出和一般输出

void PrintData(const char str[], int pFlag);		//输出
void PrintData(const char str[], int pFlag,const char ErrorStr[]);		//输出错误

pFlag为特种码,str传入字符串,ErrorStr错误代码

 

关键函数:词法分析函数ScanfProject(char str[], const int strLength);  

确定自动机,使用switch实现

附一张测试结果图

最后源代码奉上

欢迎大佬打赏

#include<stdio.h>
#include"base.h"
#include<string.h>


static char reserveWord[6][20] = {   //1-6
	"begin","if","then","while","do","end"
};


int searchReserve(char reserveWord[][20], char s[]);   //保留字	
bool IsLetter(char letter);			//字母	
bool IsDigital(char digital);		//数字	
int CodeProcessing(char str[], int iProjectLong);		//修饰
void ScanfProject(char str[], const int strLength);		//扫描程序
void PrintData(const char str[], int pFlag);		//输出
void PrintData(const char str[], int pFlag, const char ErrorStr[]);		//输出错误
int main()
{
	char str[10000];
	int TabCount = 0;   //回车标记数
	int szCount = 0;    //字符计数
	int szTureLength = 0;//实际长度
	FILE *fpin, *fpout;
	if (NULL == (fpin = fopen("sz.txt", "r")))
	{
		puts("文件读取失败或者文件不存在 \n");
		return 0;
	}

	do
	{
		str[szCount] = fgetc(fpin);
	} while (EOF != str[szCount++] /* condition */);

	str[szCount] = '\0';

	szTureLength = CodeProcessing(str, szCount);
	/*for (int i = 0; i < szTureLength; i++)
	{
		putchar(str[i]);
	}*/
	ScanfProject(str, szTureLength);







	return 0;

}



int searchReserve(char reserveWord[][20], char s[])
{
	for (int i = 0; i < 6; i++)
		if (strcmp(reserveWord[i], s) == 0)  return i + 1;
	return -1;//否则返回-1,代表查找不成功,即为标识符
}



bool inline IsLetter(char letter)
{
	if (letter >= 'a'&&letter <= 'z' || letter >= 'A'&&letter <= 'Z' || letter == '_') return true;
	else return false;
}



inline bool IsDigital(char digital)
{
	if (digital >= '0'&& digital <= '9') return true;
	else return false;
}



void PrintData(const char str[], int pFlag)
{

	printf("( %s , %d )\n", str, pFlag);

}
void PrintData(const char str[], int pFlag, const char ErrorStr[])
{
	
		printf("(%s %s , 错误)\n", str, ErrorStr);
	
}
int CodeProcessing(char str[], const int iProjectLong)

{
	//代码优化
	char tempString[10000];
	int count = 0;

	for (int i = 0; i < iProjectLong - 1; i++)
	{
		switch (str[i])
		{
		case '/':
			//去掉注释
			switch (str[i + 1])
			{
			case '/':
				i++;
				while ('\n' != str[++i]);

				tempString[count++] = '\n';

				break;
			case '*':
				i++;			//添加换行检测,输出错误行码
				do
				{
					i++;
				} while ('*' != str[i] && '/' != str[i + 1] && i < iProjectLong);
				i++;
				if (iProjectLong <= i) printf("error : 注释结束符/n");
				i++;
				break;

			default:
				break;
			}
		case ' ':
			//多余空格处理
			while (' ' == str[i + 1])
				i++;
			break;

		default:
			break;
		}
		tempString[count++] = str[i];
	}
	tempString[count] = '\0';
	strcpy(str, tempString);
	return count;
}


void ScanfProject(char str[], const int strLength)  //dfa
{
	/*
	标识符: 字母开头
	保留字: 查
	常数:
	运算符: + - * / < > = ~~~
	界符:

	*/
	char szIdentifier[255];//标识符
	char szoper[3];		//操作
	char szLimit[3];
	char szDigital[255];

	//标识符中只能出现数字字母  出现其他字符或空格次标识符结束
	 //扫描开始
	int Length = 0;
	while (Length < strLength)		//每一个词组循环
	{
		int iFlag = RESTART;
		int num = 0;
		int ierror = 0;			//计数
		switch (str[Length])		//
		{
			//标识符
			/*
				字母开头,可以包喊数字字母,扫描到其他符号时进行关键字检查

			*/


			//标示符数字先不进行判断,最后判断
		case ':':
		{
			if ('=' == str[Length + 1])
			{
				strcpy(szoper, ":=");

				PrintData(szoper, 18);
				Length++;
				Length++;
				break;
			}
			else
			{
				strcpy(szoper, ":");

				PrintData(szoper, 17);
				Length++;
				break;
			}
		}
		case '\n':

			Length++;
			break;
		case ' ':

			Length++;
			break;
		case '<':
		{
			if ('>' == str[Length + 1])
			{
				strcpy(szoper, "<>");

				PrintData(szoper, 21);
				Length++;
				Length++;
				break;
			}
			else if ('=' == str[Length + 1])
			{
				strcpy(szoper, "<=");

				PrintData(szoper, 22);
				Length++;
				Length++;
				break;
			}
			else
			{
				strcpy(szoper, "<");


				PrintData(szoper, 20);
				Length++;
				break;
			}
		}
		case '>':
		{
			if ('=' == str[Length + 1])
			{
				strcpy(szoper, ">=");


				PrintData(szoper, 24);
				Length++;
				Length++;
				break;
			}
			else
			{

				strcpy(szoper, ">");

				PrintData(szoper, 23);
				Length++;
				break;
			}
		}
		case ';':
		{

			PrintData(";", 26);
			Length++;
			break;
		}
		case '\0':
		{
			Length++;
			break;
		}
		case '(':
		{

			PrintData("(", 27);
			Length++;
			break;
		}
		case '=':
		{

			PrintData("=", 25);
			Length++;
			break;
		}
		case ')':
		{

			PrintData(")", 28);
			Length++;
			break;
		}
		case '#':
		{

			PrintData("#", 0);
			Length++;
			break;
		}
		case '+':
		{
			PrintData("+", 13);
			Length++;
			break;
		}

		case '-':
		{
			PrintData("-", 14);
			Length++;
			break;
		}

		case '*':
		{
			PrintData("*", 15);
			Length++;
			break;
		}

		case '/':
		{
			PrintData("/", 16);
			Length++;
			break;
		}



		default:

		{//字母,数字,保留字分析
			if (IsLetter(str[Length]))  //letter(letter|digital)*自动机
			{
				szIdentifier[0] = str[Length];
				Length++;
				num++;
				while ((IsLetter(str[Length]) || IsDigital(str[Length])) && num < 255)
				{
					szIdentifier[num] = str[Length];
					Length++;
					num++;
				}
				if (255 < num)
				{
					PrintData(" 程序 ", OVERLENGTH, " ");
					break;
				}
				else
				{
					szIdentifier[num] = '\0';
					int temp = searchReserve(reserveWord, szIdentifier);
					if (-1 == temp)
					{
						PrintData(szIdentifier, 10);

						break;
					}
					else
					{
						PrintData(szIdentifier, temp);
						break;
					}
				}

			}
			else if (IsDigital(str[Length]))
			{
				szDigital[0] = str[Length];
				Length++;
				num++;
				while (IsDigital(str[Length]) && num < 255)
				{
					szDigital[num] = str[Length];
					Length++;
					num++;
				}
				if (255 < num)
				{
					PrintData("", OVERLENGTH, "");
					break;
				}
				else
				{
					szDigital[num] = '\0';
					PrintData(szDigital, 11);
					break;
				}


			}
			else
			{
				szIdentifier[0] = str[Length];
				szIdentifier[1] = '\0';
				PrintData(szIdentifier, ERROR, " 未定义标示");

				Length++;
				break;
			}

		}





		}
	}



}














base.h :



#pragma once

//???flag
#define RESTART 0x0000

//??????flag
#define OVERLENGTH 0x0101  //???????
#define ERROR 0x0102        //自传参

//??????
#define IDENTIFIER  0x0001  //????????
#define RESERVEWORD 0x0002  //??????
#define OPERLIMIT   0x0003  //?????
#define DIGITAL     0x0004  //????
#define OPERATOR    0x0005  //??????









保留字越多,词法分析器越复杂,6个保留字...........

 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值