作业五——词法分析程序的设计与实现

实验报告

实验名称:词法分析程序的设计与实现  日期:2019年10月11日

一、实验内容

词法分析程序(Lexical Analyzer)要求:

- 从左至右扫描构成源程序的字符流

-  识别出有词法意义的单词(Lexemes

-  返回单词记录(单词类别,单词本身)

-  滤掉空格

-  跳过注释

-  发现词法错误

程序结构:

输入:字符流(什么输入方式,什么数据结构保存)

处理:

–遍历(什么遍历方式)

–词法规则

输出:单词流(什么输出形式)

–二元组

单词类别:

1.标识符(10)

2.无符号数(11)

3.保留字(一词一码)

4.运算符(一词一码)

5.界符(一词一码)

单词符号

种别码

单词符号

种别码

begin

1

:

17

if

2

:=

18

then

3

<

20

while

4

<=

21

do

5

<>

22

end

6

>

23

l(l|d)*

10

>=

24

dd*

11

=

25

+

13

;

26

-

14

(

27

*

15

)

28

/

16

#

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

二、程序代码

 

#include <stdio.h>
#include <string.h>
#define norw 13         /*关键字个数*/
#define nmax 14         //number的最大位数
#define al 10           //符号的最大长度 符号就是+
#define cxmax 200       //最多的虚拟机代码数
FILE* fa1;              //输出分析的文件和首地址 首地址是虚拟机指针
char ch;                //getch读取的字符
char id[al+1];          //存放标识符和保留字
int num;
int cc, ll;             //cc表示当前字符的位置
int cx;                 //虚拟机代码指针,取值范围0-cxmax-1
char line[81];           //读取行缓冲区
char a[al+1];           //读取一个符号 暂时存在这里
//char words[6][6]={'begin','if','then','while','do','end'};
char word[norw][al];    //保留字13个 就是begin end if 什么的
FILE* fin;
FILE* fout;
char fname[al];         //输入的文件名
int err;

#define getchdo         if(-1==getch()) return -1;
//如果能在缓冲区读入一个单词,那么返回值不为-1,如果失败,则返回-1.取下一个字符到ch
void error(int n);

void error(int n) {
    char space[81];
    memset(space, 32, 81);
    space[cc-1] = 0;
    printf("****出现错误\n");
    fprintf(fa1, "****出现错误\n");
    err++;
}
int getch() {
    if(cc == ll) {
        if(feof(fin)) {
            printf("\n读完了!\n");
            return -1;
        }
        ll = 0;
        cc = 0;
        ch = ' ';
        while(ch != 10) {
            if(fscanf(fin, "%c", &ch) == EOF) {
                line[ll] = 0;
                break;
            }
            printf("%c", ch);
            line[ll] = ch;
            ll++;
        }
        printf("\n");
    }
    ch = line[cc];
    cc++;
    return 0;
}

int getsym() {
    int i, j, k;
    while(ch == ' ' || ch == 10 || ch == 9||ch== 13) { //忽略空格换行回车和tab
        getchdo;
    }//当时空格,换行,回车,tab时忽略掉,取下一个字符
    if(ch >= 'a' && ch <= 'z') {
        k = 0;
        do {
            if(k < al) {
                a[k] = ch;//标识符或者保留字放在数组a中
                k++;
            }
            getchdo;
        } while(ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9');
        a[k] = '\0';
        strcpy(id, a);
        i = 0;
        j = norw-1;
        do {
            k = (i+j)/2;
            if(strcmp(id, word[k]) <= 0)
                j = k-1;
            if(strcmp(id, word[k]) >= 0)
                i = k+1;
        } while(i <= j);

        if(i-1 > j) {
            printf("保留字 (1,'%s')\n", id);
        } else {
            printf("标识符 (10,'%s')\n", id);
        }

    } else {
        if(ch >= '0' && ch <= '9') {
            k = 0;
            num = 0;
            do {
                num = num * 10 + ch - '0';
                k++;
                getchdo;
            } while(ch >= '0' && ch <= '9');
            k--;
            if(k > nmax) {
                error(30);
            }
            printf("数  字 (11,'%d')\n",num);
        } else { //假如不是数字
            if(ch == ':') {
                getchdo;//取下一个字符
                if(ch == '=') {
                    //sym = becomes;
                    printf("运算符 (12,':=')\n");
                    getchdo;
                } else {
                    printf("error!不允许单独使用‘:’\n");
                }
            } else { // 检测赋值符号
                if(ch == '<') {
                    getchdo;
                    if(ch == '=') {
                        printf("运算符 (13,'<=')\n");
                        getchdo;
                    } else {
                        printf("运算符 (14,'<')\n");
                    }
                }//如果运算符取到前一个是<,后面跟=就是≤,后面不跟就是<
                else { //检测大于小于等于
                    if(ch == '>') {
                        getchdo;
                        if(ch == '=') {
                            printf("运算符 (24,'>=')\n");
                            getchdo;
                        } else {
                            printf("运算符 (19,'>')\n");
                        }
                    } else {
                        if(ch=='+') {
                            printf("运算符 (14,'+')\n");
                            getchdo;
                        } else if(ch=='-') {
                            printf("运算符 (15,'-')\n");
                            getchdo;
                        } else if(ch=='*') {
                            printf("运算符 (16,'*')\n");
                            getchdo;
                        } else if(ch=='/') {
                            printf("运算符 (17,'/')\n");
                            getchdo;
                        }

                        else if(ch=='(') {
                            printf("分界符 (26,'(')\n");
                            getchdo;
                        } else if(ch==')') {
                            printf("分界符 (27,')')\n");
                            getchdo;
                        } else if(ch==',') {
                            printf("分界符 (28,'{')\n");
                            getchdo;
                        } else if(ch==';') {
                            printf("分界符 (29,'}'\n");
                            getchdo;
                        } else {
                            printf("error!请检查代码是否拼写正确!\n");
                            return -1;
                        }
                    }
                }
            }
        }
    }
    return 0;
}
void init() {
    strcpy(&(word[0][0]), "begin");
    strcpy(&(word[1][0]), "call");
    strcpy(&(word[2][0]), "const");
    strcpy(&(word[3][0]), "do");
    strcpy(&(word[4][0]), "end");
    strcpy(&(word[5][0]), "if");
    strcpy(&(word[6][0]), "odd");
    strcpy(&(word[7][0]), "procedure");
    strcpy(&(word[8][0]), "read");
    strcpy(&(word[9][0]), "then");
    strcpy(&(word[10][0]), "var");
    strcpy(&(word[11][0]), "while");
    strcpy(&(word[12][0]), "write");
}
int main() {
    printf("请输入要分析的文件名:\n");
    scanf("%s", fname);
    fin = fopen(fname, "r");
    if(fin) {
        init();
        printf("\n分析完毕!\n\n");
        err = 0;
        cc = cx = ll = 0;
        ch = ' ';
        while(getsym() != -1) {
        }
    } else {
        printf("找不到文件\n");
    }
    printf("\n");
    return 0;
}

 

三、问题与解决办法

1、此次实验是看书上代码和在网上查找了相关代码写了一部分内容,实在是不会写。

2、看了很多遍代码,弄清楚了其中的逻辑,但是在修改成自己的代码时,出现了很多错误。

3、保留字的分析还是没有写出来。

4、运行结果还是有问题。

四、运行结果与分

五、心得与体会

C语言有很多都不太记得了,是自己也没好好学习,借鉴书本和网上代码后,改成自己的东西也还是有很多不足的地方,之后有时间了一定要重新学习并且将词法分析的程序写出来给自己一个交代。

 

参考链接:https://blog.csdn.net/sinat_37341950/article/details/79565485

 

猜你喜欢

转载自www.cnblogs.com/cyxxixi/p/11656428.html