编译原理实验一 词法分析

直接上代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *KT[32]={"auto","break","case","char","const","continue","default","do",
"double","else","enum","extern","float","for","goto","if",
"int","long","register","return","short","signed","sizeof","static",
"struct","switch","typedef","union","unsigned","void","volatile","while"
};//关键字表
char PT[18]={';',',','.','{','}','[',']','+','-','*','/','%','(',')','=','>','<','#'};//单目界符
char *doublePT[11]={"++","--","<=","==",">=","+=","-=","*=","/=","<<",">>"};//双目界符
char IT[10][10],CT[10][10],ST[10][10];//分别储存标识符 常数 字符串
char cT[10];//储存字符
struct point
{
    char*kind;//种类
    char value[33];//名字
    int num;//token值
};//用以储存词法分析的结果
int isLetter(char ch)//判断字符是否为字母
{
    if((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'))
        return 1;
    else return 0;
}
int isDigit(char ch)//判断字符是否为数字
{
    if(ch>='0'&&ch<='9')return 1;
    else return 0;
}
int Reserve(char strToken[33])//寻找关键字表
{
    int i;
    for(i=0;i<32;i++){
        if(strcmp(KT[i],strToken)==0)return i+1;
    }
    return 0;
}
void Retract(FILE *fp)//缩进,当识别大于1个字符的单词时应用到
{
    fseek(fp,-1L,1);
}
void Print(struct point a)//输出结果
{
    printf("%s   <%s,%d>\n",a.value,a.kind,a.num);
}
int isPartition(char ch)//判断是否是界符并返回序号
{
    int i;
    for(i=0;i<18;i++)if(PT[i]==ch)return i+1;
    return 0;
}
int isSpecial(char ch)//判断是否为特殊符号
{
    if(ch=='+'||ch=='-'||ch=='/'||ch=='<'||ch=='>'||ch=='*'||ch=='=')return 1;
    else return 0;
}
void operate(struct point a)//将词法分析的结果输出到文件中
{
    FILE *fp;
    fp=fopen("result.txt","a+");
    fprintf(fp,"%s  <%s,%d>\n",a.value,a.kind,a.num);
    fclose(fp);
}
int main()
{

    int code,count1=0,count2=0,count3=0,count4=0,f=0,E=0;//辅助变量
    struct point result;//保存结果
    char strToken[33];//暂存每次识别的字符
    char ch;
    char *p;
    FILE *fp;
    fp=fopen("examplecode.txt","r");//打开示例代码的文本文件
    if(fp==NULL)//当文件打开失败时
    {
        printf("file does not exist!");
        return -1;
    }
    while(1)
    {
        p=strToken;
        ch=fgetc(fp);//逐个读取字符
        if(feof(fp))//当读到文件末尾
            break;
        if(ch==' '||ch=='\n')//遇到空格则跳过
            continue;
        if(isLetter(ch)){//判断是否是标识符或是关键字
            while(isLetter(ch)||isDigit(ch))
            {
                *p=ch;
                p++;
                *p='\0';
                ch=fgetc(fp);
                if(feof(fp))return -1;
            }
            Retract(fp);
            code=Reserve(strToken);
            if(code!=0)
            {
                result.kind="KT";
                 strcpy(result.value,strToken);
                result.num=code;
                operate(result);
                Print(result);
            }
            else
            {
             for(int i=0;i<20;i++)
            if(strcmp(IT[i],strToken)==0){code=21;result.num=i+1;break;}
              if(code!=21){strcpy(IT[count1],strToken);count1++; result.num=count1;}


                result.kind="IT";
                 strcpy(result.value,strToken);
                 operate(result);
                Print(result);
            }
        }
    else if(isDigit(ch))//常数
    {
        while((isDigit(ch)||ch=='.'||ch=='e')&&(f==0||f==1)&&(E==0||E==1)){
                if(ch=='.')f++;
                if(ch=='e'){E++;*p=ch;
            p++;
            *p='\0';
            ch=fgetc(fp);}
        if(f>1||E>1)printf("Error occurs!at%c\n",ch);
            *p=ch;
            p++;
            *p='\0';
            ch=fgetc(fp);
            if(feof(fp))return -1;
        }
        Retract(fp);

 for(int i=0;i<20;i++)
       if(strcmp(CT[i],strToken)==0){code=22;result.num=i+1;break;}
              if(code!=22){strcpy(CT[count2],strToken);count2++;result.num=count2;}

 strcpy(result.value,strToken);
        result.kind="CT";//常数
        operate(result);
        Print(result);
    }
     else if(isPartition(ch))//界符
    {
            result.kind="PT";
            result.num=isPartition(ch);
           char ch2;
            ch2=fgetc(fp);

            *p=ch;
            p++;
            *p='\0';
            if(isSpecial(ch2)&&isPartition(ch2))Retract(fp);
            else if(!isSpecial(ch2))Retract(fp);
            if(isSpecial(ch)&&ch2=='=')
            {
                code=1;
                *p=ch2;
                p++;
                *p='\0';
                ch=fgetc(fp);
            }
            if((ch=='>'||ch=='<'||ch=='+'||ch=='-')&&ch2==ch)
            {
                code=1;
                *p=ch2;
                p++;
                *p='\0';
                ch=fgetc(fp);
            }
            strcpy(result.value,strToken);
          if(code==1)for(int i=0;i<11;i++)
        if(strcmp(doublePT[i],strToken)==0){result.num=i+21;break;}
operate(result);
            Print(result);

    }
     else if (ch=='\''){//字符
            char ch2;
             result.kind="cT";
             printf("'   <PT,19>\n");//前引号
            ch2=fgetc(fp);
            *p=ch2;
            p++;
            *p='\0';
            for(int i=0;i<20;i++)
            if(cT[i]==ch2){code=23;result.num=i+1;break;}
              if(code!=23){cT[count3]=ch2;count3++;result.num=count3;}


            strcpy(result.value,strToken);
operate(result);
            Print(result);
            printf("'   <PT,19>\n");
            ch2=fgetc(fp);
            }

    else if(ch=='"'){//字符串
         result.kind="sT";
         printf("\"   <PT,20>\n");
         ch=getc(fp);
         while(isLetter(ch)||isDigit(ch)){
            *p=ch;
            p++;
            *p='\0';
            ch=fgetc(fp);
            if(feof(fp))return -1;
        }
         Retract(fp);
         for(int i=0;i<10;i++)
        if(strcmp(IT[i],strToken)==0){code=24;result.num=i+1;break;}
              if(code!=24){strcpy(ST[count4],strToken);count4++; result.num=count4;}

         strcpy(result.value,strToken);
operate(result);
            Print(result);
            ch=getc(fp);
             printf("\"   <PT,20>\n");
    }
    else//其余情况为错误情况
    {
        if(ch=='\n')continue;
        result.kind="Error!";
        operate(result);
        printf("Error occurs!at%c\n",ch);
    }
    }
    return 1;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值