词法分析器(纯c语言)

一、原文章:词法分析器(分析C语言)

二、该词法分析器种别码表

 三、词法分析器实现思路描述:

1.首先用一个数组来存储txt文本中非空白字符,并将存储字符的个数记录下来。

2.用scan()函数扫描数组中的字符,用index来定位当前扫描到的字符位置。

3.判断当前字符是哪种类型:

   (1)若是字母,则有可能是关键字或标识符,需继续看下一个字符。若是关键字,再判断具体是哪个种别码;若是标识符,种别码为0。

   (2)若是数字,是常量,种别码为24。

   (3)若是运算符或界符,则需继续看下一个字符(因为可能是<=、>=、==、!=),再判断具体是哪个种别码。

   (4)若不是以上三种,则输出。

二、用C语言改写并优化:

#pragma warning(disable:4996)
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

const int MAXN = 1000;
const int MINN = 20;


bool isKey(char* s)  //是否是关键字
{
	const char* letter[6] = { "main","int","if","else","while","do" };
	for (int i = 0; i < 6; i++)
	{
		if (strcmp(s, letter[i]) == 0)
			return true;
	}
	return false;
}
bool isOpebounder(char s) //是否是界符或运算符
{
	const char* str = "><=!(){},;+-*/";
	if (memchr(str, s, strlen(str)) != NULL)
		return true;
	else
		return false;
}
int kindofKey(char* str) //判断哪种关键字 并返回其种别码
{
	const char* key[6] = { "main","int","if","else","while","do" };
	const int arr[6] = { 1,2,3,4,5,6 };
	for (int i = 0; i < 6; i++)
	{
		if (strcmp(str, key[i]) == 0)
			return arr[i];
	}
}
int kindofOpebounder(char* str) //判断哪种运算符和界符 并返回其种别码
{
	const char* opebounder[17] = { "<",">","!=",">=","<=","==",",",";","(",")","{","}","+","-","*","/","=" };
	const int arr[MINN] = { 7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 };
	for (int i = 0; i < 17; i++)
	{
		if (strcmp(str, opebounder[i]) == 0)
			return arr[i];
	}
}
char* firstLetter(char* s) //首字符为字母
{
	int size = 0;//单词长度
	char str[MINN] = ""; //单词
	char c;    //存储当前字符的下一个 方便作为实参以识别类型
	str[size++] = *s; //保存当前字符并增加长度


	while (c = *(s + size))
	{
		if (islower(c) || isdigit(c)) //下一个字符是字母或数字则保存在str中
			str[size++] = c;
		else
			break;
		if (isKey(str)) //如果单词恰好是关键字 则终止循环
			break;
	}

	return str;
}


char* firstNumber(char* s) //首字符为数字
{
	int size = 0;
	char str[MINN] = "";
	char c;

	str[size++] = *s;

	while (c = *(s + size))
	{
		if (isdigit(c)) //下一个字符是字母或数字则保存在str中
			str[size++] = c;
		else
			break;
	}
	return str;

}
char* firstOpebounder(char* s) //首字符为运算符和界符
{
	char arr[MINN] = ">=<!";
	char str[MINN] = "";
	char c = *(s + 1);
	str[0] = *s;

	if (memchr(arr, *s, strlen(arr)) != NULL)
	{
		if (c == '=')
			str[1] = '=';
	}
	return str;
}
int Type(char* s) //判断单词的首字母为哪种类型
{
	if (islower(*s))
		return 1;
	else if (isdigit(*s))
		return 2;
	else if (isOpebounder(*s))
		return 3;
	else
		return 4;
}
void scan(char* s, int n)
{
	for (int index = 0; index < n;index++)
	{
		char str[MINN] = ""; //存储单词
		switch (Type(s + index))
		{
		case 1:
		{

			//首字符为字母 可能是关键字或标识符 接下来持续读取字母形成单词
			strcpy(str, firstLetter(s + index));
			if (isKey(str))
				printf("(%s,%d)\n", str, kindofKey(str));
			else
				printf("(%s,0)\n", str);
			index += (strlen(str) - 1);
			break;
		}
		case 2:
		{
			//首字符为数字,只能是常量
			strcpy(str, firstNumber(s+index));
			printf("(%s,24)\n", str);
			index += (strlen(str) - 1);
			break;
		}
		case 3:
		{
			//首字符为运算符和界符
			strcpy(str, firstOpebounder(s+index));
			printf("(%s,%d)\n", str, kindofOpebounder(str));
			index += (strlen(str) - 1);
			break;
		}
		default:
		{
			//其他
			printf("(%c,error)\n", *(s+index));
		}

		}
	}
}

int main(void)
{
	char letter[MAXN] = ""; //存储要扫描的字符
	int size = 0;  //字符的个数

    //与s.txt文件连接并读取里面的内容
	FILE* fp;
	fp = fopen("s.txt", "r");
	char ch = getc(fp);
    
	while (ch != EOF)
	{
		
		if (ch != ' '&&ch !='\n')  //保存非空白字符
		{
			letter[size] = ch;
			size++;
		}
    ch = getc(fp);
	}
	fclose(fp);
    //开始扫,并将结果以二元的形式打印在屏幕上
	scan(letter, size);


	return 0;
}

三、文本内容及结果截图:

 

 

  • 19
    点赞
  • 168
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C_Newind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值