词法分析器的设计与实现

词法分析器的设计与实现


词法分析器介绍

词法分析是从左到右扫描每行源程序的符号,拼成单词,换成统一的机内表示形式——TOKEN字,送给语法分析程序。

TOKEN字是一个二元式:(单词种别码,自身值)。单词自身值按如下规则给出:

​ 1.标识符的自身值是他在符号表的入口位置。

​ 2.常数的自身值是常数本身(或者其他二进制数值)。

​ 3.关键字和界限符的自身值为本身。

词法分析器功能

1.输入:字符串(带进行词法分析的源程序),可从键盘直接输入或从文件读入。

输出:由(种别码,自身值)所组成的二元组序列。

单词的种别码是语法分析需要的信息,可用整数编码表示,例如:标识符的种别码为1,常数为2,保留字为3,运算符为4,界符为5。

单词的自身值是编译其他阶段需要的信息,标识符的自身是标识符在符号表入口,其他类型单词的自身值是其本身。

例如:输入:if i >= 15 then x := y ;

​ 输出:

​ (3,if)

​ (1,0)//i符号的入口为0

​ (4,>=)

​ (2,15)

​ (3,then)

​ (1,1)//x符号的入口为1

​ (4,:=)

​ (1,2)//y符号的入口为2

​ (5,;)

2.功能:

a.滤过空格。

b.识别保留字:if then else while do 等。

c.识别标识符:<字母>(<字母>|<数字>)。

d.识别整数:0|(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)。

e.识别典型的运算符和分隔符,例如:+ - * / > >= <= ( ) ;

3.具有一定的错误处理功能,例如:能检查出程序语言的字符集以外的非法字符。

源码附带注释

#include<string>
#include<stdlib.h>
#include<stdio.h>
using namespace std;

bool isLetter(char ch){//isLetter 标识符
    if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) return true;
    else return false;
}

bool isDigit(char ch){//isDigit 常数
    if (ch >= '0' && ch <= '9') return true;
    else return false;
}

bool isOperators(char ch){// isOperators 运算符
    if (ch == '+' || ch == '*' || ch == '-' || ch == '/' || ch == '=' || ch == ':' || ch == '<' || ch == '>') return true;
    else return false;
}
bool isDelimiter(char ch){// isDelimiter 界符
    if (ch == ',' || ch == ';' || ch == '.' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}' || ch == '#') return true;
    else return false;
}
bool isBlank(char ch){
    if (ch == ' ' || ch == '\t') return true;
    else return false;
}
char  key[34][10] = { "main",
"auto", "short", "int", "long", "float", "double", "char", "struct"
, "union", "enum", "typedef", "const", "unsigned", "signed", "extern", "register"
, "static", "volatile", "void", "if", "else", "switch", "case", "for"
, "do", "while", "goto", "continue", "break", "default", "sizeof", "return","then"};


void main()
{
back:
    char Sourcecode[100] = "";
    int number=0;
    int h=0;
    char hh[100][10]={'\0'};
    //声明变量
    printf("请输入程序段,标识符为1,常数为2,关键字为3,运算符4,界符5\n");
    gets(Sourcecode);
    //读入程序段放入firstcode
    
    for (int i = 0; i < 100; i){
        //char delimiter[2] = "";
        int j = 0;  //letter  标识符
        int l = 0;   //digit  常数
        int k = 0;   //operators  运算符

        int b = 0;   //类型编号
        char num[10] = "";
        char word[10] = "";  
        if (isBlank(Sourcecode[i]) == 1){
            i += 1;
        }//去空格
        else{
            if (isLetter(Sourcecode[i]) == 1)         //是否为字母
            {                                             //是
                
                do
                {
                    if (j < 10){
                        word[j] = Sourcecode[i];
                        j++;
                    }
                } while (isDigit(Sourcecode[++i]) == 1|| isLetter(Sourcecode[i]) == 1);//常数||标识符

                //*~~~*
                int a = 0;
                while (a < 34){
                    if (strcmp(key[a], word) == 0){
                        b = 3;
                        a++;
                        break;
                    }
                    else {
                        b = 1;
                        a++;
                        //否
                    }
                }
                if (b == 3){
                    printf("(3,%s)\n", word);
                }//~~~~~~~~~~~~~~~~~~~~~~~~~~~
                if (b == 1){
                    int q=0;
                    for(int qq=0;strcmp(hh[qq],"")!=0;qq++){
                        if(strcmp(word,hh[qq])==0){
                            q=1;break;
                        }
                    }
                    if(q==1){
                        printf("(1,%d)\n",qq);
                        q=0;
                    }else{
                        for(qq=0;qq<j;qq++){
                            hh[h][qq]=word[qq];
                        }
                        printf("(1,%d)\n",h);
                        h++;
                    }
                /*  int qq,yy=0;
                    if(h==0){
                        for(qq=0;qq<j;qq++){
                            hh[0][qq]=word[qq];
                        }
                        printf("(1,%d)\n",h);
                        h++;
                    }else{
                        for(qq=0;qq<h;qq++){
                            if(strcmp(hh[qq], word)==0){
                                yy=1;
                                break;
                            }
                        }
                        if(yy==0){
                            for(qq=0;qq<j;qq++){
                                hh[h][qq]=word[qq];

                            }
                            printf("(1,%d)\n",h);
                            h++;
                            yy=0;
                        }
                        else{
                            for(qq=0;qq<h;qq++){
                                if(strcmp(hh[qq], word)==0)
                                    printf("(1,%d)\n",qq);
                                yy=0;
                            }
                        }
                    }*/
                    //
                }
                //~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            }
            else if (isDigit(Sourcecode[i]) == 1)//常数
            {int c = 0;
                while (isDigit(Sourcecode[i])){
                    
                    num[c] = Sourcecode[i];
                    i += 1;
                    c++;
                }
                printf("(2,%s)\n", num);
            }
            else if (isDelimiter(Sourcecode[i]) == 1){//界符
                
                printf("(5,%c)\n", Sourcecode[i]);
                i++;
            }
            else if (isOperators(Sourcecode[i]) == 1){//运算符

                if (Sourcecode[i] == ':' || Sourcecode[i] == '>' || Sourcecode[i] == '<'&&Sourcecode[i + 1] == '='){
                    printf("(4,%c%c)\n", Sourcecode[i], Sourcecode[i + 1]);
                    i += 2;
                }
                else{
                    printf("(4,%c)\n", Sourcecode[i]);
                    i+= 1;
                }
            }
            else{
                if(Sourcecode[i]!='\0')
                    printf("(error,%c)\n",Sourcecode[i]);
                if(Sourcecode[i+1]!='\0'){
                    
                    i+=1;}
                else
                    i=100;
            }
        }

    
    }

    goto back;

}

编程感悟

1.需要对是否为标识符、常数、保留字、运算符、界符进行判断,应用布尔类型完美的解决这个问题。

2.++i与i++都是i=i+1的含义,但是++i表示执行前i=i+1,而i++表示执行后i=i+1。

3.用一维数组来表示字符串,二维数组用来表示字符串的集合,并且用strcmp(string_1,string_2)来进行字符串内容的比较,相同返回0。

4.对于相同的标识符来说,入口应该相同,所以在对这里进行处理的时候,声明一个二维数组用来存放各个标识符(字符或者字符串),根据二维数组中的行下标进行入口标记。

5.好好学习一维数组、二维数组的应用场景以及应用原理。

猜你喜欢

转载自blog.csdn.net/qq_40265501/article/details/80001409