能识别浮点数的简单词法分析程序(C语言实现)

此词法分析程序能够识别基本字、标识符、有符号整数、有符号浮点数、运算符和界符)。

仅作交流,希望能抛砖引玉,获得更为简洁有效的词法分析程序。

 

输入:所给文法的源程序字符串。(字符串以“#”号结束)

输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串; sum为整型常数。

例如:控制台输入beginx:=9: if x>9 then x:=2*x+1/3;end #,经过词法分析后输出如下序列: (1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……

例如:控制台输入zzz123+-1234.56e-123+1+-2#,经过词法分析后输出:

(10,zzz123)(13,+)(11,-1.23456e-120)(11,1)(13,+)(11,-2)(0,#)

 

实现截图:


 

 

 

源代码:

 

#include<stdio.h>
#include<string.h>
#include<math.h>

char prog[80]; //存放所有输入字符
char token[8]; //存放词组
char ch; //单个字符

int syn,p,m,n;  //syn:种别编码
double sum;     
int count;

int isSignal; //是否带正负号(0不带,1负号,2正号)

int isDecimal; //是否是小数
double decimal;  //小数
int isExp;  //是否是指数
int index;  //指数幂
int isNegative; //是否带负号
double temp;
int temp2;

int repeat;

void scanner();

char *rwtab[6]={"begin","if","then","while","do","end"};

void main()
{
	p=0;
	count=0;
	isDecimal=0;
	index=0;
	repeat=0;
	printf("\n Please input string:\n");
	do{
		ch=getchar();
		prog[p++]=ch;
	}while(ch!='#');  //输入以#号键结束

	p=0;
	do{
		scanner(); //扫描,单词
		switch(syn)
		{
		case 11:
			if(isDecimal==0)
			{
				//加了1个强制类型转换
				printf("(%2d,%8d)\n",syn,(int)sum);
				break;
			}
			else if(isExp==1)
			{
				printf("(%2d,%10.5e)\n",syn,sum);
				isExp=0;
				isDecimal=0;
				break;
			}
			else if(isDecimal==1)
			{
				printf("(%2d,%8.4f)\n",syn,sum);
				isDecimal=0;
				break;
			}
		case -1:
			printf("input error\n");
			break;
		default:
			printf("(%2d,%8s)\n",syn,token);
		}
	}while(syn!=0);
	getch();
}

void scanner()
{
	sum=0;
	decimal=0;
	m=0;

	for(n=0;n<8;n++)
		token[n]=NULL;
	ch=prog[p++]; //从prog中读出一个字符到ch中
	while(ch==' ')  //跳过空字符(无效输入)
		ch=prog[p++];

	if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))) //ch是字母字符
	{
		while(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||((ch>='0')&&(ch<='9')))
		{
			token[m++]=ch; //ch=>token
			ch=prog[p++]; //读下一个字符
		}
		token[m++]='\0';
		p--; //回退一格
		syn=10; //标识符

		//如果是"begin","if","then","while","do","end"标识符中的一个
		for(n=0;n<6;n++)
			if(strcmp(token,rwtab[n])==0)
			{
				syn=n+1;
				break;
			}
	}

   else	if((ch>='0')&&(ch<='9'))
	{
IsNum:
   if(isSignal==1)
   {
	   //token[m++]='-';
   }
		while((ch>='0')&&(ch<='9'))
		{
			sum=sum*10+ch-'0'; //ch中数字本身是当做字符存放的
			ch=prog[p++];
		}
		if(ch=='.')
		{
			isDecimal=1;
			ch=prog[p++];
			count=0; //之前忘了清零,123.123+123.123#两个浮点数就无法识别
			while((ch>='0')&&(ch<='9'))
			{
				//pow(x,y)计算x的y次幂
				temp=(ch-'0')*pow(0.1,++count);
				decimal=decimal+temp;
				//AddToDec();
				ch=prog[p++];
			}
			sum=sum+decimal;
		}
		if(ch=='e'||ch=='E')
		{
			isExp=1;
			ch=prog[p++];
			if(ch=='-')
			{
				isNegative=1;
				ch=prog[p++];
			}
			while((ch>='0')&&(ch<='9'))
			{
				//指数
				index=index*10+ch-'0';
				ch=prog[p++];
			}
			//10的幂
			//123e3代表123*10(3)
			//sum=sum*pow(10,index);是错误的
			if(isNegative)
				sum=sum*pow(0.1,index);
			else
				sum=sum*pow(10,index);

		}
		if(isSignal==1)
		{
			sum=-sum;
			isSignal=0;
		}
		p--;
		syn=11;
	}

	else switch(ch)
	{
		case '<':
			m=0;
			token[m++]=ch;
			ch=prog[p++];
			if(ch=='>')
			{
				syn=21; //<>对应21
				token[m++]=ch;
			}
			else if(ch=='=')
			{
				syn=22;
				token[m++]=ch;
			}
			else
			{
				syn=20;
				p--;
			}
			break;

		case '>':
			m=0;
			token[m++]=ch;
			ch=prog[p++];
			if(ch=='=')
			{
				syn=24;
				token[m++]=ch;
			}
			else
			{
				syn=23;
				p--;
			}
			break;

		case ':':
			m=0;
			token[m++]=ch;
			ch=prog[p++];
			if(ch=='=')
			{
				syn=18;
				token[m++]=ch;
			}
			else
			{
				syn=17;
				p--;
			}
			break;

		case '+':
			temp2=prog[p];

			token[m++]=ch;

			if((temp2>='0')&&(temp2<='9')&&(repeat==1))
			{
				isSignal=2; //isSignal正数
				ch=prog[p++];
				repeat=0;
				goto IsNum;
			}

			if(((temp2=='+')||(temp2=='-'))&&(repeat==0))  //如果重复出现符号,才将后边的+,-视为正负号
			{
				repeat=1;
				//ch=prog[p++];
			}


			syn=13;

			break;
		case '-':
			temp2=prog[p];
			token[m++]=ch;

			if((temp2>='0')&&(temp2<='9')&&(repeat==1))
			{
				isSignal=1;

				ch=prog[p++]; //读“-”下一个字符
				repeat=0;
				goto IsNum;  //转到数字的识别
			}

			if(((temp2=='+')||(temp2=='-'))&&(repeat==0))  //如果重复出现符号,才将后边的+,-视为正负号
			{
				repeat=1;  //预言会重复
				//ch=prog[p++];  //读下一个字符
			}

			syn=14;

			break;

		case '*':
			temp2=prog[p];
			token[m++]=ch;

			if(temp2=='+')
			{
				isSignal=2;
				repeat=1;
			}
			else if(temp2=='-')
			{
				isSignal=1;
				repeat=1;
			}
			syn=24;
			break;

		case '/':
			syn=16;
			token[m++]=ch;
			break;
		case '=':
			syn=25;
			token[m++]=ch;
			break;
		case ';':
			syn=26;
			token[m++]=ch;
			break;
		case '(':
			temp2=prog[p];
			token[m++]=ch;
		
			if(temp2=='+')
			{
				isSignal=2;
				repeat=1;
			}
			else if(temp2=='-')
			{
				isSignal=1;
				repeat=1;
			}

			syn=27;
			break;
		case ')':
			syn=28;
			token[m++]=ch;
			break;
		case'#':
			syn=0;
			token[m++]=ch;
			break;
		default:
			syn=-1;
	}
}
 
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值