基于C语言的PL/0词法分析器

要求:输入一段程序,分析出其中的标识符、基本字、运算符、界符、常数并输出

算法思路:先定义一个二维数组,存储读入的程序段 ,然后对二维数组进行处理

具体处理方法为:先读入一个字符,若为字母、数字,继续往后读,若为同类型,将其存入一个临时数组(若是字母,与保留字进行比较,判断是否为保留字,若为数字,则输出),否则跳出,进行判断;若是运算符,判断当前字符和后一个字符,判断是否为>=或<=等连续的两个运算符;界符直接进行判断。


上代码:


#include<stdio.h>
#include<string.h>
#include <stdbool.h>  //引入布尔类型,stdio.h文件中没有布尔类型


#define lineLength 100  //固定每行的长度
#define primLength 10   //读取的字符串的长度(标识符之类)
#define numLength 20    //读取的常量的长度


//存储基本字
char mPrimary[13][20]= {"begin","call","const","do","end","if","odd","procedure","read","then","var","while","write"};//有序,二分查找的前提是有序(按字母表顺序)


char text[lineLength][lineLength];//存储读到的内容




void  main()
{


int i=0;
bool flag=false; //判断输入是否结束,以及是否读到二维数组最后标志符(.),pl/0语言程序最后以点结束。


//将输入读入二维字符数组中
int t;
for (t = 0; t < 100; t++)
    {
        printf("%d:", t);
        gets(text[t]);
        if (!*text[t])     //当输入的该行为空时   if条件成立,执行break语句跳出循环。
        {
            break;
        }
    }


    //对二维字符数组进行处理,
     int mid;
    for(i=0; i<t; i++)
    {
        char prim[primLength];//新建一个字符数组用来存储基本字或者变量名
        char num[numLength];//新建一个字符数组用来存储常量


        for(mid=0; mid<primLength; mid++) //清空数组
            prim[mid]='\0';


        for(mid=0; mid<numLength; mid++) //清空数组
            num[mid]='\0';




        int j;
        for(j=0; text[i][j]!='\0'; j++)
        {
            if(text[i][j]=='.')
            {
                printf(".        界符/结束符\n");
                flag=true;
                break;
            }
            else if(text[i][j]==' ')
            {
                continue;
            }
            else if(text[i][j]>='a'&&text[i][j]<='z')
            {
                for(mid=0; (text[i][j]>='a'&&text[i][j]<='z')||(text[i][j]>='0'&&text[i][j]<='9'); j++,mid++) //读入字符串
                    prim[mid]=text[i][j];
                j--;//由于用j去判断循环的结束,此处需要回退一个字符


                for(mid=0; prim[mid]!='\0'; mid++) //输出字符串
                    printf("%c",prim[mid]);


                int head=0,tail=12;//二分查找,查找是否为基本字,保留字共13个
                int mid2;//中间比较变量
                while(head<=tail)
                {
                    mid2=(head+tail)/2;
                    if(strcmp(prim,mPrimary[mid2])<=0)  //字符串比较用strcpy()函数
                        tail=mid2-1;
                    if(strcmp(prim,mPrimary[mid2])>=0)
                        head=mid2+1;
                }
                if(head-1>tail)//搜索成功,确定为基本字
                    printf("         基本字/%s \n",mPrimary[mid2]);
                else
                    printf("         标识符\n");


                for(mid=0; prim[mid]!='\0'; mid++) //清空数组方便下次读入
                    prim[mid]='\0';
            }
            else if(text[i][j]>='0'&&text[i][j]<='9')
            {
                for(mid=0; text[i][j]>='0'&&text[i][j]<='9'; j++,mid++)//读入数字
                    num[mid]=text[i][j];
                j--;//由于用j去判断循环的结束,此处需要回退一个字符


                for(mid=0; num[mid]!='\0'; mid++) //输出数字,并且清空方便下次读入
                {
                    printf("%c",num[mid]);
                    num[mid]='\0';
                }
                printf("         常数\n");
            }
            else//处理“+ - * /,#()等”
            {
                switch(text[i][j])
                {
                case '<':
                {
                    if(text[i][j+1]=='=')
                    {
                        printf("%c%c       运算符/小于等于号\n",text[i][j],text[i][j+1]);
                        j++;
                    }
                    else
                    {
                        printf("%c         运算符\n",text[i][j]);
                    }
                    break;
                }
                case '>':
                {
                    if(text[i][j+1]=='=')
                    {
                        printf("%c%c         运算符/大于等于号\n",text[i][j],text[i][j+1]);
                        j++;
                    }
                    else
                    {
                        printf("%c        运算符\n",text[i][j]);
                    }
                    break;
                }
                case ':':
                {
                    if(text[i][j+1]=='=')
                    {
                        printf("%c%c        运算符\n",text[i][j],text[i][j+1]);
                        j++;
                    }
                    else
                    {
                        printf("%c        运算符\n",text[i][j]);
                    }
                    break;
                }
                case '+':
                case '-':
                case '*':
                case '/':
                {
                    printf("%c      运算符\n",text[i][j]);
                    break;
                }
                case '(':
                {
                    printf("%c      界符\n",text[i][j]);
                    break;
                }
                case ')':
                {
                    printf("%c      界符\n",text[i][j]);
                    break;
                }
                case ',':
                {
                    printf("%c      界符/逗号\n",text[i][j]);
                    break;
                }
                case ';':
                {
                    printf("%c      界符/分号\n",text[i][j]);
                    break;
                }
                default:
                    printf("%c      标识符\n",text[i][j]);
                }


            }
        }
        if(flag)
            break;
    }




}



运行截图:




  • 11
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值