Compiler_词法分析_表驱动法_分析文件

本文出自:http://blog.csdn.net/svitter


一开始做这个实验真是觉得各种简单- -就是一张状态转换图不停的跳来跳去。。后来发现我太天真了。。一个搞来搞去搞不清楚的bug是因为老师给的状态转换图坑了 - - 当然这肯定不怪老师因为我一开始做的时候居然没发现= =。

状态转换图我就暂且不贴了,另外两篇文章的地址如下:

Compiler_词法分析_表驱动法

Compiler_词法分析_直接转向法

这次的是分析文件,用双缓冲。其实我也不是很清楚自己到底有没有用上双缓冲。。

下面简单介绍一下我所理解的双缓冲:

1.我理解的双缓冲区,其实就是一个缓冲区分了两部分的,前半部分用于分析,后半部分用于暂存。

2.分析部分分析完以后,下一次分析的时候,暂存部分作为新的分析部分,分析部分作为暂存部分。

3.如果整个单词超出了分析部分,暂存部分,那么就存入文件或者其他数组,再做处理。

另外,请教老师得知,一般要求缓冲长度大于单词长度。


介绍就这么多吧,下面贴一下代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

#define MIDBUFFER 1023
#define WHOLEBUFFER 2048
#define MAXWORD 10000

//Double buffer
struct bibuffer
{
	char *buffer;            		//缓冲区空间
	char *forward;     	            //后向指针
	int count;                   	//前向指针记数
	int state;						//当前的状态
};

//lexical analysis
//scheme
int State[8][5];

//set final status
const bool Acstatus[7] =
{ 0, 1, 1, 0, 0, 1, 0};

//for JudgeNum
int JudgeNum(char &ch)
{
	if (ch >= '0' && ch <= '9')
		return 0;
	else if (ch == '.')
		return 1;
	else if (ch == 'E')
		return 2;
	else if (ch == '+' || ch == '-')
		return 3;
	else
		return 4;
}

//initial the scheme
void init()
{
	//set error state
	for (int i = 0; i < 8; i++)
		for (int j = 0; j < 5; j++)
		{
			State[i][j] = 7;
		}

	//set table
	State[0][0] = 1;
	State[0][1] = 6;
	State[1][0] = 1;
	State[1][1] = 2;
	State[1][2] = 5;
	State[2][0] = 2;
	State[2][2] = 3;
	State[3][3] = 4;
	State[4][0] = 5;
	State[5][0] = 5;
	State[6][0] = 2;
}

//parse, change state due to char;
void parse(int &state, char &ch, char *cur)
{
	state = State[state][JudgeNum(ch)];
	if (state != 7)		//可以在此考虑拼接问题
		*cur = ch;
}

bool FinalState(int &state)
{
	return state == 7;

}

void InitBuff(bibuffer *bbuf, FILE *fp, char *buffer)
{

	fread(buffer, MIDBUFFER, 1, fp);					//first buffer
	buffer[MIDBUFFER] = EOF;							    //put the end
	fread(buffer + MIDBUFFER + 1, MIDBUFFER, 1, fp);	//next buffer
	buffer[WHOLEBUFFER - 1] = EOF;						    //put the end

    bbuf->buffer = buffer;
	bbuf->forward = bbuf->buffer;
	bbuf->count = 0;
	bbuf->state = 0;

}

void pause()
{}

//
void Analysis( FILE *fp)
{
    int i;
	bibuffer *bbuf;
	char *temp, *buffer;        //用于记录当前的位置
	bool init = false;


    bbuf = new bibuffer();
    temp = new char[MAXWORD];
    buffer= new char[MAXWORD];
    i = 0;

    memset(temp, '\0', MAXWORD);

	while (1)
	{
		if(!init)
        {
			InitBuff(bbuf, fp, buffer);
			init = true;
		}
		if(*(bbuf->forward) == '1')
			pause();
		//count值位于第一缓冲区或者第二缓冲区中
		if ((bbuf->count < MIDBUFFER || ((bbuf->count > MIDBUFFER) && (bbuf->count < WHOLEBUFFER)))
				&& !FinalState(bbuf->state))
		{
			//parse state, char
			bbuf->state = State[bbuf->state][JudgeNum(*(bbuf->forward))];
            if (bbuf->state != 7)		//可以在此考虑拼接问题
                temp[i] = *(bbuf->forward);
            i++;

			bbuf->forward++;
			bbuf->count++;
		}
		//count值超出第一缓冲区
		else if (bbuf->count == MIDBUFFER && !FinalState(bbuf->state))
		{
			//read next buffer
			fread((bbuf->buffer) + MIDBUFFER + 1, MIDBUFFER, 1, fp);

            bbuf->forward++;
			bbuf->count++;

            bbuf->state = State[bbuf->state][JudgeNum(*(bbuf->forward))];
            if (bbuf->state != 7)		//可以在此考虑拼接问题
                temp[i] = *(bbuf->forward);
            i++;
		}
		//count值超出第二缓冲区
		else if (bbuf->count >= WHOLEBUFFER && !FinalState(bbuf->state))
		{
			//read first buffer
			fread((bbuf->buffer) + MIDBUFFER + 1, MIDBUFFER, 1, fp);
            bbuf->forward = bbuf->buffer;
			bbuf->count = 0;

            bbuf->state = State[bbuf->state][JudgeNum(*(bbuf->forward))];
            if (bbuf->state != 7)		//可以在此考虑拼接问题
                temp[i] = *(bbuf->forward);
            i++;
		}
		//识别出一个单词
		else if (FinalState(bbuf->state))				//当一个终态出现
		{
			if (temp[0] != '\0')
				printf("%s ", temp);
			memset(temp, '\0', MAXWORD);
			i = 0;
			bbuf->state = 0;
			//count 不用改变
		}

		if (bbuf->count != MIDBUFFER && bbuf->count < WHOLEBUFFER
				&& *(bbuf->forward) == EOF)
		{
			break; 		//analysis end
		}

	}
	delete temp;
	delete bbuf;
	delete buffer;
}

int main()
{
	//Declare the variables
	FILE *fp;
	fp = fopen("test.txt", "rt");
	//initial
	init();
	Analysis(fp);

	return 0;
}

本来想要做成每次调用返回一个单词的。但是发现我去每次调用返回一个单词怎么做到最长匹配等等诸多问题。

肯定能实验但肯定不是老师所要求的,被虐了这么多天也就没有心思再继续写下去了。

心得:

中间出现了很多问题。比如中间识别后的重置,判断顺序的先后,一点一点DEBUG出来的。pause()函数是为了调试特意添加的,对于程序效率肯定有影响,但是觉得还是不错的一个调试方法,就暂且保留了。用于测试的test:

1.255dsfasfsafsafdasfdsafasdfdsfas
dsfasfsaf554.54fdsafasdfdsfas
erqewrewqr1.2E+2sdgfdsakfshak2313dslkhalfkakjrege1d

略微有些随意,也算是够用了吧。。对于“1.”这样的数字也是可以识别的。

之前先写好了跳转的状态转换表用处是很大的。。但是难免也会出现小BUG慢慢的找上去调好了。也考虑如果有时间可以做一下语法分析那些部分。有BUG慢慢调,慢慢整理思路思密达。。。

还有WEB作业和JSP作业。大二下学期真是人间小炼狱啊。。。。


By Svitter。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include<iostream> #include<cctype> #include<cstring> #include<cmath> using namespace std; int w=0; //尾数累加器 int p=0; //指数累加器 int j=0; //十进制小数位数计数器 int e=1; //用来记录十进制数的符号,当指数为正时为1,为负时为-1 int i=0; //用来标志元素位置 int d=0; //用来示每个数值型元素对应的数值 const int N=40;//用来确定输入识别符的最大长度 char data[N];//存放输入的识别符 bool is_digit; //标志是否是数字 string CJ1;//确定是整形还是实型 double CJ2;//记数值 //函数声明 void check(char c);//检查首字母是否是数字的函数 void deal_integer(char c);//处理识别符的整数部分 void deal_point(char c);//用来处理小数部分 void deal_index(char c);//用来处理指数部分 void s_next();// 确定实型 void z_next();//确定整型 void last();// 计算 CJ2 void error();//程序中错误处理程序 void deal();//处理函数主体 int main(){ //主函数 cout<<"please input your data,and its maximum length is "<<N<<":"<<endl;//等待用户输入识别符 cin>>data; deal();//处理函数主体 last();// 计算 CJ2 system("pause"); return 0; } void check(char c) //判断输入的首字母是否是数字 { is_digit=isdigit(c); while(is_digit!=true){//输入的首字母不是数字时 cout<<"\nError! Try again.."<<endl;//要求重新输入 cin>>data; check(data[0]); } } void deal_integer(char c){//处理识别符的整数部分 d=(int)c-48; w=w*10+d; i++; if(isdigit(data[i])!=0)//下一个仍是数值时,调用程序本身 deal_integer(data[i]); } void deal_point(char c){//用来处理小数部分 int temp=i; if(isdigit(c)!=0)//是数值字符时 deal_integer(c); else { error(); //错误处理程序 deal();//处理函数主体 } j=i-temp;//记录十进制小数位数 } void deal_index(char c){//用来处理指数部分 if(c=='-') {e=-1;i++;}//是'-'号时 else {if(c=='+') i++;//是'+' 号时 else { if(isdigit(c)==false) //非数值字符时 { error();//错误处理程序 deal();//处理函数主体 } else { d=(int)c-48;//把输入字符转换为整型 goto pro2;} } } if(isdigit(data[i])!=0) pro1: d=(int)(data[i])-48; pro2: p=p*10+d; i++; if(isdigit(data[i])!=0)//是数值字符时 goto pro1; else if(data[i]!='\0'){//非结束标志 error();//错误处理程序 deal();//处理函数主体 } else s_next(); // 确定实型 } void s_next(){// 确定实型 i--;//退一个字符 CJ1="实型"; } void z_next(){//确定整型 i--;//退一个字符 CJ1="整型"; } void last(){// 计算 CJ2 CJ2=w*pow((double)10,e*p-j); cout<<CJ1<<": "<<CJ2<<endl;//输出 } void error(){//程序中错误处理程序 cout<<"\nError! Try again.."<<endl;//重新输入数据 cin>>data; p=0;w=0;j=0; //所有全局变量重新初始化 e=1;i=0;d=0; //exit(0); } void deal(){ check(data[0]);//判断输入的首字母是否是数字 deal_integer(data[i]);//处理识别符的整数部分 if(data[i]=='.') { deal_point(data[++i]);//用来处理小数部分 if(data[i]=='e'||data[i]=='E')//如果是e或E时 deal_index(data[++i]);//用来处理指数部分 else if(data[i]!='\0') { error();//错误处理程序 deal();//处理函数主体 } else s_next();// 确定实型 } else { if(data[i]=='e'||data[i]=='E')//如果是e或E时 { deal_index(data[++i]);//用来处理指数部分 //CJ1="整型"; } else if(data[i]!='\0'){ //非结束标志 error();//错误处理程序 deal();//处理函数主体 } else z_next();//确定整型 } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值