编译原理实验一:简单PL/0词法分析器C语言代码

思路分析:我的个人思路比较简单,首先定义几个二维数组,分别保存PL语言关键字,界符,或者运算符,然后在主函数中,读入字符串,或者从文件中读入,然后对字符串进行分割,进行一些过滤空格(ASCII码为10,换行的ASCII码为13),之后将分割后的字符串与我们定义的数组进行比较(这相当于一个词库),假如匹配,就与之对应对它进行标记,如果既不是关键字,也不是界符.运算符,那么就是用户自定义的标识符.然后分别输出就OK.


code类别表:

1 : 关键字
2 : 标识符
3 : 常量
4 : 运算符
5 : 对应的是界符中元素的位置


关键字只有如下几个:

Const——用来声明常量;

Var——用来声明变量;

Procedure——用来声明过程;

Begin——声明过程的开始;

End——声明过程的结束;

Ood——单目运算符,声明为关键字;

If——条件语句;

Then——条件语句;

Call——声明调用函数;

While——循环语句;

Read——读文件语句;

Write——写文件语句;

对于用户自定义标识符应该满足:以字母开头,其后是字母和数字的组合,即:字母(字母|数字)*

数字则是数字字符(0——9)组成的数字串;

特殊符号有如下几个:
+,-,*,/,=<>,<,>=,<=,:=

把关键字、算符和界符称为语言固有的单词,标识符、常量称为用户自定义的单词。

实验指导书上说啥用SYM,ID,NUM,我个人觉得没必要,这是为了后面的自动转换机准备的,什么枚举类型啊,实验一应该用不到,况且第一节上机课代码给老师验收的时候,老师说差不多就可以了.那就差不多,没必要那么复杂,个人觉得对编译原理这门课没必要太重视,毕竟太冷门了,以后谁吃多了做编译器设计语言呢?不实用..

下面上代码:

/*************************************************************************
	> File Name: pl0.c
	> Author:chendiyang
      > School:WUST_CST_1501班    
     >  Myblog: www.chendsir.com
	> Mail:1441353519@qq.com 
	> Created Time: 2017年04月06日 星期四 20时27分34秒
 ************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*
  code类别表: 
         1 : 关键字 
         2 : 标识符
	 3 : 常量
	 4 : 运算符 
         5 : 对应的是界符中元素的位置
 */
 
typedef struct Word
{
	int num;//词所属类型 SYM
	char w[20];//词的标识识别符的值  ID 
}Word;
 
int main()
{
	char ch,word_temp[20]="";  //缓存区 
	int i=0,j=0,k=0,key=0,chioce;
	char ktt[42][20]={"begin","call","const","do","end","if","odd","procedure","read","then","var","while","write",",",";",":","(",")","[","]","{","}","+","-","*","/","=","<",">","<=",">=",":=","0","1","2","3","4","5","6","7","8","9"};  //SYM用户关键字,运算符,界符 
	FILE *fp;
	Word word[100];
	printf("1:输入源程序保存成文件\n");
	printf("2:打开文件进行词法分析\n");
	printf("请输入你的选择:");
	scanf("%d",&chioce);
	switch(chioce)
	{
	case 1:
		fp=fopen("nasm.txt","wt");
		if(!fp)
		{
			printf("can't open file C_program.txt\n");
			exit(1);
		}
		printf("请输入一段程序(以#结束):\n");
		ch=getchar();
		while(ch!='#')
		{
			fputc(ch,fp);
			ch=getchar();
		}
		fclose(fp);break;
	case 2:
		fp=fopen("nasm.txt","r");
		if(!fp)
		{
			printf("can't open file C_program.txt\n");
			exit(1);
		}
		printf("源程序如下:");
		while((ch=fgetc(fp))!=EOF)
		{
			putchar(ch);
		}
		fclose(fp);
		printf("\n词法分析结果如下:\n");
		fp=fopen("nasm.txt","r");
		if(!fp)
		{
			printf("can't open file C_program.txt\n");
			exit(1);
		}
		while((ch=fgetc(fp))!=EOF)
		{   
			if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9'))
			{
				
				word_temp[key++]=ch;//连续几个字母的连成单词
				word_temp[key]='\0';
				continue;
			}
			else
			{   if(strcmp(word_temp,"")!=0)
				{
					strcpy(word[i].w,word_temp);//将单词拷贝到结构数组中
					strcpy(word_temp,"");
					key=0;//回到临时数组的开始位置
					i++;//结构数组的下标加1
					
				}
				if(ch==' '||ch==10||ch==13||ch=='	')//去掉空格、回车和tab键
				{	
					continue;
				}			
				else
				{
					word_temp[0]=ch;
                                        if(word_temp[0]==':'||word_temp[0]=='>'||word_temp[0]=='<')
                                        ch=fgetc(fp);
                                        if(ch=='=')
                                        word_temp[1]=ch;
					word_temp[2]='\0';//字符串结束符
					strcpy(word[i].w,word_temp);//将非字母数字符号拷贝到结构数组中
					strcpy(word_temp,"");
					key=0;//回到临时数组的开始位置
					i++;
				}
			}
		}break;
	default: printf(" 输入错误!");
	}
	
	for(j=0;j<i;j++)
	{
		for(k=0;k<43;k++)
		{
			if((strcmp(word[j].w,ktt[k]))==0)
			{
				if(k>=0&&k<13)
					word[j].num=1;//保留字
				else if(k>=13&&k<21)
					word[j].num=5;//分隔符
				else if(k>=21&&k<32)
					word[j].num=4;//运算符
				else if(k>=32&&k<43)
					word[j].num=3;//数字
				break;
			}
			else 
				word[j].num=2;//变量
		}
	}
printf("code类别表:\n");printf("1 : 关键字 \n");
printf("2 : 标识符\n");
printf("3 : 常量\n");
printf("4 : 运算符 \n");
 printf("5 : 对应的是界符中元素的位置\n");
for(j=0;j<i;j++)//按格式要求打印输出
	{
		printf("(%d,'%s')\n",word[j].num,word[j].w);
	}
	//输出保留字
printf("\n保留字表:\n\n");
	for(j=0;j<i;j++)
	{	
		if(word[j].num==1)
	     {
printf("%s ",word[j].w);
	     }
 
	}
	//分隔符表
printf("\n分隔符表:\n\n");
	for(j=0;j<i;j++)
	{
	 if(word[j].num==5)
	     {
printf("%s ",word[j].w);
	     }
 
	}
//运算符表
printf("\n运算符表:\n\n");
	for(j=0;j<i;j++)
	{	
		if(word[j].num==4)
	     {
printf("%s ",word[j].w);
	     }
 
	}
//数字表
printf("\n数字表:\n\n");
	for(j=0;j<i;j++)
	{
		if(word[j].num==3)
	     {
printf("%s  ",word[j].w);
	     }
}
//变量表
printf("\n变量表:\n");
	for(j=0;j<i;j++)
	{
	  if(word[j].num==2&strcmp(word[j].w," ")!=0)
	     {
printf("%s ",word[j].w);
 
	     }
     
 
	}
printf("\n");
 
 
	fclose(fp);
	return 0;
}
运行结果如图:

注意,敲黑板了,注意符号的拼数问题:比如":"和":=",">="之类....

以上.......


  • 8
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值