编译原理初级入门--自制词法分析器(二)

这篇博客介绍了如何改进自制的词法分析器,增加了带参数的main函数,将输入字串改为从文件读取,更接近实际场景。文章还提到了改进架构,用IDEN标识符状态替换alpha,并创建基本类型表和界限符表。目前分析器能处理算术运算符和基本数据类型,仅支持整数和纯字母标识符。后续计划扩展功能,如处理注释、空行以及预处理运算优先级和括号匹配等语义分析问题。
摘要由CSDN通过智能技术生成

对前面的源码进行改进,增加带参数的main函数,不直接在代码中提供需要分析字串,而是把字串添加到文件中去。
这样更贴近真实情况。


    int main(int arc,char*argv[])
{
	
	FILE *fp;
	if (arc != 2)
	{
		printf("usage: %s filename  \n", argv[0]);
		exit(1);
	}

	if ((fp = fopen(argv[1], "r")) == NULL)
	{
		printf("can't open %s\n", argv[1]);
		exit(1);
	}

对架构进行改进,把alpha状态替换成IDEN标识符状态。单独构建一个基本类型表,用来从iden中筛选出基本类型。
单独构建一个界限符表。
写进头文件。


#ifndef _basetype_H
#define _basetype_H

char *basetype[8] = { "int","long","short","unsigned","char","float","double","signed" };

char delim[8] = { '(',	')',	'{',	'}',	';',	'[',	']' ,','};

char oper[5] = { '+',	'-',	'*',	'/',	'=' };
#endif // 


完整的主程序如下:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <conio.h>
#include <stdlib.h>
#include "basetype.h"


#define STRMAX 50 

//定义状态
typedef enum {START,INT,IDEN,OPER,DELIM,END} state;
void stradd(char*, const char);
bool isbasetype(const char*);
bool isoper(char);
bool isdelim(char);


int main(int arc,char*argv[])
{
	
	FILE *fp;
	if (arc != 2)
	{
		printf("usage: %s filename  \n", argv[0]);
		exit(1);
	}

	if ((fp = fopen(argv[1], "r")) == NULL)
	{
		printf("can't open %s\n", argv[1]);
		exit(1);
	}
	
	
		
	
	//初始化状态
	state cur_state = START;

	
	char s[STRMAX];
	int i ;
	char c,token[20]="";
	//循环取字符
	while ((fgets(s, STRMAX, fp)) != NULL)
	{
		for (i = 0; s[i] != '\n'; i++)
		{
			c = s[i];


			switch (cur_state)
			{
			case START:
				if (isdigit(c))
				{
					cur_state = INT;
					i--;
					break;
				}
				else if (isalpha(c))
				{
					cur_state = IDEN;
					i--;
					break;
				}
				else if (isoper(c))
				{
					cur_state = OPER;
					i--;
					break;

				}
				else if (isdelim(c))
				{
					cur_state = DELIM;
					i--;
					break;
				}
				
			
				else if (isspace(c))
				{
					cur_state = START;

					break;
				}
				else if(c=='\0')
				{
					cur_state = END;
					i--;
					break;
				}
			case INT:
				if (isdigit(c))
				{
					stradd(token, c);
					break;
				}
				else
				{
					cur_state = START;
					printf("分解的数字是: %s\n", token);
					strcpy(token, "");
					i--;
					break;
				}

			case IDEN:
				if (isalpha(c))
				{
					stradd(token, c);
					break;
				}
				else
				{
					cur_state = START;
					if (isbasetype(token))
						printf("分解keyword是: %s\n", token);
					else
						printf("分解的变量是: %s\n", token);
					strcpy(token, "");
					i--;
					break;
				}


			case DELIM:

				printf("界限符是: %c\n", c);
				cur_state = START;
				break;
			case OPER:
				printf("分解的运算符是: %c\n", c);
				cur_state = START;
				break;

			case END:
				printf("完全分解完毕\n");
				return 0;
			}
		}
	}
	
	return 0;
}

void stradd(char*pstr, const char ch)
{
	int len;
	len=strlen(pstr);
	pstr[len] = ch;
	pstr[len + 1] = '\0';
}
bool isbasetype(const char *ptoken)
{
	
	for (int i = 0; i < 8; i++)
	{
		if (strcmp(ptoken, basetype[i]) == 0)
			return true;
		
	}
	return false;
}

bool isoper(char ch)
{
	for (int i = 0; i < 5; i++)
	{
		if (ch == oper[i])
			return true;
		
	}
	return false;
}

bool isdelim(char ch)
{
	for (int i = 0; i < 8; i++)
	{
		if (ch == delim[i])
			return true;
	}
	return false;
}

现在能进行一些简单的分解了,支持算术运算符,基本数据类型。
只能支持整数,纯字母组成的标识符。
下一步再来扩展。预备弄一个预处理掉注释和空行。

另外问题依然很多,怎么识别运算优先级?
怎么识别括号成对?大括号(不在一行内),怎么识别拼写错误?

这类问题不属于词法分析的范畴,而是语义分析的领域。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值