C语言实现简单 词法分析程序(编译原理)

要求

代码书写(详细注释,亲自修改,测试无误)

#include <stdio.h>
#include  <string.h>
char prog[80],token[8];
char ch, en=a;
int syn,p,m,n,sum;
char *rwtab[6]={
          
   "begin","if","then","while","do","end"};
void main()
{
          
   
	void scaner();
	p=0;
	// 不以# 结尾,程序将一直等待输入:查看getchar()的用法:https://zhidao.baidu.com/question/60668767.html
	printf("
 please input string: 并以#号结尾!
");
	//printf("
a
");
	//printf("
%c
", en);
	do 
	{
          
   
		ch=getchar();
		prog[p++]=ch;
		//printf("
%c
", ch);
		//printf("
%d
", p);
	  }while(ch !=#);
	p=0;
	//printf("
%d
", p);
	do
	  {
          
   
		scaner();
		// 执行完函数后,全局变量 syn, token的值就会自动改变。
		switch(syn)
		{
          
     
			// 11数字 二元组
			case 11:printf("
(%d, %d)",syn,sum); break;
			// 不符合语法的字符,报错
			case -1:printf("
error"); break;
			// 输出关键字,或者是 标识符
			default:printf("
(%d, %s)", syn, token);
		}
	  }while(syn != 0);  // 遇# 为0,结束循环。
}

void scaner()
{
          
    
	// 前三行是初始化数据,初始化字符数组token ,元素全都是 null
	for(n=0;n<8;n++) token[n]=NULL; 
	// 先读取值,再p++,也就是从下标0开始读取
    m=0;
	ch=prog[p++];
	//printf("
%c
", ch);
	//printf("
%d
", p);
	while(ch== ) ch=prog[p++];
	// 运用 ASCLL码,对字母范围确定,下面判断数字同理
	// 判断关键字和标识符
    if((ch >= a && ch <= z)||(ch >= A && ch <= Z)) 
	{
          
    
		// 当读取到字母开头是, 就开始进入循环了,取得以该字符开头的 关键字(或者是标识符)
		while ((ch >= a && ch <= z)||(ch >= A&& ch <= Z)||(ch >= 0 && ch <= 9))
           {
          
    
			token[m++]=ch;
            ch=prog[p++];
			//printf("
m
");
           }	
        token[m++]=;  // 字符数组结尾符号
        /*回退一个字符; 此时的p代表 非字母或数字的字符的 下一个字符*/
		p--;  // 回退到 非字母或数字的那个字符
        
		// 先预先设置为 标识符的 种别码
		syn=10;
        for(n=0; n<6; n++)
        if(strcmp(token,rwtab[n])==0) // 判等函数,相等返回0, 大于返回正整数,小于返回负整数
        {
          
   
			// 进入if里说明相等是关键字,给syn 赋值标识符的种别码
			syn = n + 1;
			break;
			
		}
   }
	else if(ch >= 0 && ch <= 9) // 用来判断数字
		{
          
   	
			sum = 0; // 老师的代码忘记了初始化sum这一步, 并且绝对不能放到while循环内部初始化
			while(ch >= 0 && ch<= 9)
			{
          
    
				sum = sum * 10 + ch -0;  // 也是利用ASCLL码,将字符转化为数字,然后实现累加,计算数值(巧妙)
				ch=prog[p++];
			}
		p--; // 同样p--,因为这个p--代表的字符,还没被处理
		syn=11;
   }
	else
		switch(ch)
   {
          
   
     case<: token[m++]=ch;
			// 下面这些是用来判断是否有 <=  或者 <>的
            ch = prog[p++];
            if(ch==>) {
          
   syn=21; token[m++]=ch;}
            else if(ch===) {
          
   syn=22; token[m++]=ch;}
            else {
          
   syn=20; p--;}
            break;
     case>: token[m++]=ch;
             ch=prog[p++];
			// 同上,不过老师的 syn 值给错了,改过来就行
            if(ch===) {
          
    syn=24; token[m++]=ch;}
            else {
          
    syn=23; p--;}
            break;
     case:: token[m++]=ch;
            ch=prog[p++];
            if(ch===) {
          
   syn=18; token[m++]=ch;}
            else {
          
   syn=17; p--;}
            break;
     case+: syn=13; token[0]=ch;break;
     case-: syn=14; token[0]=ch;break;
     case*: syn=15; token[0]=ch;break;
     case/: syn=16; token[0]=ch;break;
     /*...补齐单词表中其他单个界符;*/
	 case=: syn=25; token[0]=ch;break;
     case#: syn= 0; token[0]=ch; break;
	 case;: syn=26; token[0]=ch;break;
	 case(: syn=27; token[0]=ch;break;
	 case): syn=28; token[0]=ch;break;
     default:syn=-1;  
	}
}

逻辑分析

结果展示

结束~ 感谢观看

经验分享 程序员 微信小程序 职场和发展