编译原理 词法分析 C++实现

词法分析实验

【文法定义】:

<标识符>::=<字母>{<字母>|<数字>}//标识符和关键字都不区分大小写,比如if和IF均为关键字,不允许出现与关键字相同的标识符

<字母>::=_|a|...|z|A|...|Z  

<数字>::=0|1|...|9  

<整数>::=[+|-]<无符号整数>

<无符号整数>::=<数字>{<数字>}

<字符>::='<加法运算符>'|'<乘法运算符>'|'<字母>'|'<数字>'  

<加法运算符>::=+|- 

<乘法运算符>::=*|/ 

<字符串>::="{十进制编码为32,33,35-126的ASCII字符}"  //字符串中要求至少有一个字符

【问题描述】

请根据给定的文法设计并实现词法分析程序,从源程序中识别出单词,记录其单词类别和单词值,输入输出及处理要求如下:

  1. 数据结构和与语法分析程序的接口请自行定义;类别码需按下表格式统一定义;
  2. 为了方便进行自动评测,输入的被编译源文件统一命名为testfile.txt;输出的结果文件统一命名为output.txt,输入输出文件路径为相对路径,不要写成绝对路径。
  3. 结果文件中每行按如下方式组织:

单词类别码 单词的字符/字符串形式(中间仅用一个空格间隔)

单词的类别码请统一按如下形式定义:

 

【输入形式】testfile.txt中的符合文法要求的测试程序。


【输出形式】要求将词法分析结果输出至output.txt中。

【样例输入】

const int const1 = 1, const2 = -100;

const char const3 = '_';

int change1;

char change3;

int gets1(int var1,int var2){

    change1 = var1 + var2;

    return (change1);

}

void main(){

    printf("Hello World");

    printf(gets1(10, 20));

}

【样例输出】

CONSTTK const

INTTK int

IDENFR const1

ASSIGN =

INTCON 1

COMMA ,

IDENFR const2

ASSIGN =

MINU -

INTCON 100

SEMICN ;

CONSTTK const

CHARTK char

IDENFR const3

ASSIGN =

CHARCON _

SEMICN ;

INTTK int

IDENFR change1

SEMICN ;

CHARTK char

IDENFR change3

SEMICN ;

INTTK int

IDENFR gets1

LPARENT (

INTTK int

IDENFR var1

COMMA ,

INTTK int

IDENFR var2

RPARENT )

LBRACE {

IDENFR change1

ASSIGN =

IDENFR var1

PLUS +

IDENFR var2

SEMICN ;

RETURNTK return

LPARENT (

IDENFR change1

RPARENT )

SEMICN ;

RBRACE }

VOIDTK void

MAINTK main

LPARENT (

RPARENT )

LBRACE {

PRINTFTK printf

LPARENT (

STRCON Hello World

RPARENT )

SEMICN ;

PRINTFTK printf

LPARENT (

IDENFR gets1

LPARENT (

INTCON 10

COMMA ,

INTCON 20

RPARENT )

RPARENT )

SEMICN ;

RBRACE }

代码:

#include<stdio.h>
#include<string.h>
struct Symbol
{
    char name[10];//名字
    char real[3];//真实的符号
} ;
char c;
int i;
FILE *inFile,*outFile;
int split();
char buffer[1024];
int result=0;
char CONSTTKS[][7]= {"CONST","INT","CHAR","RETURN","VOID","MAIN","PRINTF"};

struct Symbol symbols[]= {{"COMMA",","},{"SEMICN",";"},{"MINU","-"},{"PLUS","+"},{"DIV","/"},{"LSS","<"},{"GRE",">"},
    {"ASSIGN","="},{"LPARENT","("},{"RPARENT",")"},{"LBRACK","["},{"RBRACK","]"},{"LBRACE","{"},{"RBRACE","}"}
};

int comp(char* a,char* b)
{

    int i;
    for(i=0; a[i]!='\0'&&b[i]!='\0'; i++)
    {
        if(a[i]!=b[i]&&a[i]-b[i]!=32&&a[i]-b[i]!=-32)
            return 1;
    }
    if(a[i]==b[i]&&a[i]=='\0')
        return 0;
    else return 1;

}
int isConsttks(char* c)
{

    int i;
    for(i=0; i<7; i++)
    {
        if(comp(CONSTTKS[i],c)==0)
        {
            return i;
        }
    }
    return -1;
}

//判断一个字母是否是字母:a-zA-Z_,
//返回1代表是,0 代表不是
int isAlpheBelta(char c)
{

    return (c>='A'&&c<='Z')||(c>='a'&&c<='z')||c=='_';
}

int isDigit(char c)
{
    return c>='0'&&c<='9';
}




/**
* 分割单词的时候,通过;空格 ,‘’“”(){}进行分割
*/
int main()
{
    int toFile=1;

    int kind;
    int temp2;
    inFile=fopen("testfile.txt","r");
    outFile=fopen("output.txt","w");
    if(inFile==NULL)
    {
        printf("打开文件失败!程序退出!");
        return -1;
    }
    if(outFile==NULL)
    {
        printf("创建输出文件失败!程序退出!");
        return -1;
    }
    else
    {


        while((kind=split())!=-1)
        {


            if(buffer[0]!='\0')
            {
                if(kind==15)//如果是char类型
                {
                    if(toFile)
                        fprintf(outFile,"CHARCON %c\n",buffer[0]);
                    else
                        printf("CHARCON %c\n",buffer[0]);
                    buffer[0]='\0';
                    result=0;
                }
                else if(kind==16)
                {
                    if(toFile)
                        fprintf(outFile,"STRCON %s\n",buffer);
                    else printf("STRCON %s\n",buffer);
                    buffer[0]='\0';
                    result=0;
                }

                else
                {
                    temp2=isConsttks(buffer);
                    if(temp2>=0)
                    {
                        if(toFile)
                            fprintf(outFile,"%sTK %s\n",CONSTTKS[temp2],buffer);
                        else printf("%sTK %s\n",CONSTTKS[temp2],buffer);
                    }
                    else if(toFile)
                        fprintf(outFile,"IDENFR %s\n",buffer);
                    else printf("IDENFR %s\n",buffer);

                    if(kind==111)
                    {
                        if(toFile)
                            fprintf(outFile,"LEQ <=\n");
                        else printf("LEQ <=\n");
                    }
                    else if(kind==112)
                    {
                        if(toFile)
                            fprintf(outFile,"GEQ >=\n");
                        else printf("GEQ >=\n");
                    }
                    else if(kind==113)
                    {
                        if(toFile)
                            fprintf(outFile,"EQL ==\n");
                        else printf("EQL ==\n");
                    }
                    else if(kind==114)
                    {
                        if(toFile)
                        {
                            fprintf(outFile,"NEQ !=\n");
                        }

                        else printf("NEQ !=\n");
                    }
                }

            }

            if(kind>0&&kind<=14)
            {
                if(toFile)
                    fprintf(outFile,"%s %s\n",symbols[kind-1].name,symbols[kind-1].real);
                else  printf("%s %s\n",symbols[kind-1].name,symbols[kind-1].real);
            }

        }

    }

    printf("分析完成!");
    return 0;
}

//分词程序,返回值用来控制下一个输出
int split()
{

    int count=0;

    int flag=0;
    while(!feof(inFile)&&!flag)
    {

        i=fgetc(inFile);
        c=(char)i;
        if(result==16)
        {
            if(i==32||i==33||(i>=35&&i<=126))
                buffer[count++]=c;
            else if(i==34)
            {
                buffer[count]='\0';
                flag=1;
            }
        }
        else if(result==15)
        {
            if(i==32||i==33||(i>=35&&i<=126))
            {
                buffer[count++]=c;
                buffer[count]='\0';
                flag=1;
            }

        }
        else
        {
            if(isAlpheBelta(i)) //如果是字母
            {


                result=0;

                buffer[count++]=c;


            }
            else if(isDigit(c))
            {


                result=0;
                //如果是数字

                buffer[count++]=c;


            }
            else
            {
                flag=1;

                buffer[count]='\0';
                switch(c)
                {

                case ' ':
                case '\t':
                case '\n':

                    if(result==16)
                    {
                        result=16;
                        flag=0;
                        buffer[count++]=c;
                    }
                    else if(result==15)
                    {
                        result=15;
                        buffer[count++]=c;
                        buffer[count]='\0';
                    }
                    else result=0;
                    break;
                case ',':
                    result=1;//
                    break;
                case ';':
                    result=2;
                    break;
                case '-':
                    result=3;
                    break;
                case '+':
                    result=4;
                    break;
                case '/':
                    result=5;
                    break;
                case '<':
                    result=6;
                    if((char)fgetc(inFile)=='=')
                    {
                        result=111;

                    }
                    else
                    {
                        fseek(inFile,-1,SEEK_CUR);
                    }

                    break;
                case '>':
                    result=7;
                    if((char)fgetc(inFile)=='=')
                    {
                        result=112;

                    }
                    else
                    {
                        fseek(inFile,-1,SEEK_CUR);
                    }

                    break;
                case '=':
                    result=8;
                    if((char)fgetc(inFile)=='=')
                    {
                        result=113;
                    }
                    else
                    {
                        fseek(inFile,-1,SEEK_CUR);
                    }
                    break;
                case '(':
                    result=9;
                    break;
                case ')':
                    result=10;
                    break;
                case '[':
                    result=11;
                    break;
                case ']':
                    result=12;
                    break;
                case '{':
                    result=13;
                    break;
                case '}':
                    result=14;
                    break;
                case '\'':
                    result=15;
                    break;
                case '\"':
                    result=16;
                    break;
                case '!':

                    c=(char)fgetc(inFile);
                    if(c=='=')
                    {

                        result=114;

                    }
                    else
                    {
                        fseek(inFile,-1,SEEK_CUR);
                    }


                    break;
                }


            }
        }
    }

    if(feof(inFile))
        return -1;
    if (flag==1)
    {
        return result;
    }

    return -1;



}

运行效果:

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值