编译原理实验一:词法分析程序设计实验

结果(只是基础实验还没做拓展实验,我太喜欢这个风格的vscode了,多贴一次哈哈哈哈哈)

在这里插入图片描述

对实验指导书源程序进行一些补充和少量修改

程序一:

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define ID 7
#define INT 8
#define REAL 9
#define LT 10
#define LE 11
#define EQ 12
#define NE 13
#define GT 14
#define GE 15
#define IS 16
#define PL 17
#define MI 18
#define MU 19
#define DI 20

char TOKEN[20];
void report_error(char *s)
{
    printf("Having Error: %s", *s);
}
void out(int x, char *s)
{
    switch (x)
    {
    case 7:
    {
        printf("%s,%s\n", "ID", s);
        break;
    }
    case 8:
    {
        printf("%s,%s\n", "INT", s);
        break;
    }
    case 10:
    {
        printf("%s,%s\n", "LT", s);
        break;
    }
    case 11:
    {
        printf("%s,%s\n", "LE", s);
        break;
    }
    case 12:
    {
        printf("%s,%s\n", "EQ", s);
        break;
    }
    case 13:
    {
        printf("%s,%s\n", "NE", s);
        break;
    }
    case 14:
    {
        printf("%s,%s\n", "GT", s);
        break;
    }
    case 15:
    {
        printf("%s,%s\n", "GE", s);
        break;
    }
    case 16:
    {
        printf("%s,%s\n", "IS", s);
        break;
    }
    case 17:
    {
        printf("%s,%s\n", "PL", s);
        break;
    }
    case 18:
    {
        printf("%s,%s\n", "MI", s);
        break;
    }
    case 19:
    {
        printf("%s,%s\n", "MU", s);
        break;
    }
    case 20:
    {
        printf("%s,%s\n", "DI", s);
        break;
    }
    default:
    {
        printf("%s,%s\n", KeyWordTable[x], s);
        break;
    }
    }
}

/* 建立保留字表 */
#define MAX_KEY_NUMBER 20                         /*关键字的数量*/
#define KEY_WORD_END "waiting for your expanding" /*关键字结束标记*/
char *KeyWordTable[MAX_KEY_NUMBER] = {"begin", "end", "if", "then", "else", "switch", "case", KEY_WORD_END};
/* 查保留字表,判断是否为关键字 
不是关键字,返回0,是关键字,返回n+1, n为关键字数组中所找到的相同的关键字的索引位置*/
int lookup(char *token)
{
    int n = 0;
    while (strcmp(KeyWordTable[n], KEY_WORD_END)) /*如果比较到最后一位,也就是KEY_WORD_END,也就是已经确定都没有相同的,返回0*/
    {
        /*strcmp比较两串是否相同,若相同返回0*/
        /*相等:strcmp函数返回0,加上!后为:TRUE 进入if内部执行语句;
        不相等: strcmp返回其他正数或负数,这些返回值都等价于:TRUE ,加上!后,都为:FALSE 不进入if内部语句*/
        if (!strcmp(KeyWordTable[n], token))
        {
            return n + 1; /*根据单词分类码表I,设置正确的关键字类别码,并返回此类别码的值*/
            break;
        }
        n++;
    }
    return 0; /*单词不是关键字,而是标识符*/
}

void scanner_example(FILE *fp)
{
    char ch;
    int i = 0;
    int c = 0;
    ch = fgetc(fp); /*取出一个字符*/

    /*首字符为字母,字母数字混杂*/
    if (isalpha(ch)) /*是否是字母*/
    {
        TOKEN[0] = ch;
        ch = fgetc(fp); /*取出下一个字符*/
        i = 1;
        while (isalnum(ch)) /*是否是字母或者数字*/
        {
            TOKEN[i] = ch;
            i++;
            ch = fgetc(fp); /*取出一个字符*/
        }
        /*跳出循环之后,fp指针指向的字符,不再是数字或者字母*/
        TOKEN[i] = '\0';
        fseek(fp, -1, 1);  /*fp指针从当前位置往前挪一位*/
        c = lookup(TOKEN); /*判断是否是关键字,不是的话返回0*/
        if (c == 0)
            out(ID, TOKEN);
        else
            out(c - 1, " "); /*因为lookup函数返回值为n+1*/
    }
    /*首字符是数字,整型数字*/
    else if (isdigit(ch)) /*是否是数字*/
    {
        TOKEN[0] = ch;
        ch = fgetc(fp); /*取出第二个字符*/
        i = 1;
        while (isdigit(ch)) /*后面取出的字符都依然是数字*/
        {
            TOKEN[i] = ch;
            i++;
            ch = fgetc(fp);
        }
        /*跳出循环之后,fp指针指向的字符,不再是数字*/
            TOKEN[i] = '\0';
            fseek(fp, -1, 1); /*fp指针从当前位置往前挪一位*/
            out(INT, TOKEN);
    }
    else
    {
        switch (ch)
        {
        case '<':
        {
            ch = fgetc(fp);
            if (ch == '=')
                out(LE, " ");
            else if (ch == '>')
                out(NE, " ");
            else
            {                     /*下一位不是=或者> :当做只有< */
                fseek(fp, -1, 1); /*fp指针从当前位置往前挪一位*/
                out(LT, " ");
            }
            break;
        }
        case '=':
        {
            out(EQ, " ");
            break;
        }
        case '>':
        {
            ch = fgetc(fp);
            if (ch == '=')
                out(GE, " ");
            else
            {                     /*下一位不是= :当做只有> */
                fseek(fp, -1, 1); /*fp指针从当前位置往前挪一位*/
                out(GT, " ");
            }
            break;
        }
        case ':':
        {
            ch = fgetc(fp);
            if (ch == '=')
            {
                out(IS, " ");
            }
            else
            { /*冒号后面跟着的不是等号的话*/
                report_error(":");
                fseek(fp, -1, 1);
            }
        }
        case '+':
        {
            out(PL, " ");
        }
        case '-':
        {
            out(MI, " ");
        }
        case '*':
        {
            out(MU, " ");
        }
        case '/':
        {
            out(DI, " ");
        }
        default:
        {
            report_error(&ch);
            break;
        }
        }
    }

    return;
}

程序二

#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include<stdlib.h>

#define DIGIT 1
#define POINT 2
#define OTHER 3
#define POWER 4
#define PLUS  5
#define MINUS 6
#define UCON  7 
/*Suppose the class number of unsigned constant is 7
假设无符号常量的类数为7*/
#define ClassOther 200
#define EndState -1
int w, n, p, e, d;
int Class; 
/*Used to indicate class of the word
用来表示单词的类别*/
int ICON;
float FCON;
static int CurrentState; 
/*Used to present current state, the initial value:0
用于表示当前状态,初始值:0*/

int GetChar(void);
int EXCUTE(int, int);
int HandleOtherWord(void)
{
    return ClassOther;
}
int HandleError(void)
{
    printf("Error!\n");
    return 0;
}

int GetChar(void)
{
    int c;
    c = getchar();
    if (isdigit(c))
    {
        d = c -'0';
        return DIGIT;
    }
    if (c =='.')
        return POINT;
    if (c =='E'|| c =='e')
        return POWER;
    if (c =='+')
        return PLUS;
    if (c =='-')
        return MINUS;
    return OTHER;
}
int EXCUTE(int state, int symbol)
{
    switch (state)
    {
    case 0:
        switch (symbol)
        {
        case DIGIT:
            n = 0;
            p = 0;
            e = 1;
            w = d;
            CurrentState = 1;
            Class = UCON;
            break;
        case POINT:
            w = 0;
            n = 0;
            p = 0;
            e = 1;
            CurrentState = 3;
            Class = UCON;
            break;
        default:
            HandleOtherWord();
            Class = ClassOther;
            CurrentState = EndState;
        }
        break;
    case 1:
        switch (symbol)
        {
        case DIGIT:
            w = w * 10 + d;
            break; //CurrentState=1
        case POINT:
            CurrentState = 2;
            break;
        case POWER:
            CurrentState = 4;
            break;
        default:
            ICON = w;
            CurrentState = EndState;
        }
        break;
    case 2:
        switch (symbol)
        {
        case DIGIT:
            n++;
            w = w * 10 + d;
            break;
        case POWER:
            CurrentState = 4;
            break;
        default:
            FCON = w * pow(10, e * p - n);
            CurrentState = EndState;
        }
        break;
    case 3:
        switch (symbol)
        {
        case DIGIT:
            n++;
            w = w * 10 + d;
            CurrentState = 2;
            break;
        default:
            HandleError();
            CurrentState = EndState;
        }
        break;
    case 4:
        switch (symbol)
        {
        case DIGIT:
            p = p * 10 + d;
            CurrentState = 6;
            break;
        case MINUS:
            e = -1;
            CurrentState = 5;
            break;
        case PLUS:
            CurrentState = 5;
            break;
        default:
            HandleError();
            CurrentState = EndState;
        }
        break;
    case 5:
        switch (symbol)
        {
        case DIGIT:
            p = p * 10 + d;
            CurrentState = 6;
            break;
        default:
            HandleError();
            CurrentState = EndState;
        }
        break;
    case 6:
        switch (symbol)
        {
        case DIGIT:
             p = p * 10 + d;
            break;
        default:
            FCON = w * pow(10, e * p - n);
            CurrentState = EndState;
        }
        break;
    }
    return CurrentState;
}
int LEX(void)
{
    int ch;
    CurrentState = 0;
    while (CurrentState != EndState)
    {
        ch = GetChar();
        EXCUTE(CurrentState, ch);
    }
    fseek(fp,-1,1);
    //return Class;
    printf("w: %d  n: %d  p: %d  e: %d  d: %d", w, n, p, e, d);
    printf("\n ICON: %.3f, FCON: %.3f CLASS: %d", ICON, FCON, Class);
}
int main(){
    LEX();
    system("pause");
}

写实验二的时候找到的实验一的一个逻辑错误

在这里插入图片描述

一开始没有写这句回退fp指针,结果就是: “字符c实数字符a字符b”这样的字符串在判断的时候,会在识别出实数之后把fp指针向后多走一位,这样字符A就根本没有被识别的机会,这个事情是在实验二识别基础算术表达式的时候发现的

但是程序二是建立在手动输入上的,需要将程序一二做一个合体,读取同一个文件

所以最终程序 :

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define ID 7
#define INT 8
#define REAL 9
#define LT 10
#define LE 11
#define EQ 12
#define NE 13
#define GT 14
#define GE 15
#define IS 16
#define PL 17
#define MI 18
#define MU 19
#define DI 20

/****************************判断实数**************************************/
#define DIGIT 1
#define POINT 2
#define OTHER 3
#define POWER 4
#define PLUS 5
#define MINUS 6
#define UCON 7
/*Suppose the class number of unsigned constant is 7
假设无符号常量的类数为7*/
#define ClassOther 200
#define EndState -1
int w, n, p, e, d;
int Class;
/*Used to indicate class of the word
用来表示单词的类别*/
int ICON;
float FCON;
static int CurrentState;
/*Used to present current state, the initial value:0
用于表示当前状态,初始值:0*/
int GetChar(void);
int EXCUTE(int, int);
int HandleOtherWord(void)
{
    return ClassOther;
}
int HandleError(void)
{
    printf("Error!\n");
    return 0;
}

int GetChar(FILE *fp)
{
    int c;
    c = fgetc(fp);
    if (isdigit(c))
    {
        d = c - '0';
        return DIGIT;
    }
    if (c == '.')
        return POINT;
    if (c == 'E' || c == 'e')
        return POWER;
    if (c == '+')
        return PLUS;
    if (c == '-')
        return MINUS;
    return OTHER;
}
int EXCUTE(int state, int symbol)
{
    switch (state)
    {
    case 0:
        switch (symbol)
        {
        case DIGIT:
            n = 0;
            p = 0;
            e = 1;
            w = d;
            CurrentState = 1;
            Class = UCON;
            break;
        case POINT:
            w = 0;
            n = 0;
            p = 0;
            e = 1;
            CurrentState = 3;
            Class = UCON;
            break;
        default:
            HandleOtherWord();
            Class = ClassOther;
            CurrentState = EndState;
        }
        break;
    case 1:
        switch (symbol)
        {
        case DIGIT:
            w = w * 10 + d;
            break; //CurrentState=1
        case POINT:
            CurrentState = 2;
            break;
        case POWER:
            CurrentState = 4;
            break;
        default:
            ICON = w;
            CurrentState = EndState;
        }
        break;
    case 2:
        switch (symbol)
        {
        case DIGIT:
            n++;
            w = w * 10 + d;
            break;
        case POWER:
            CurrentState = 4;
            break;
        default:
            FCON = w * pow(10, e * p - n);
            CurrentState = EndState;
        }
        break;
    case 3:
        switch (symbol)
        {
        case DIGIT:
            n++;
            w = w * 10 + d;
            CurrentState = 2;
            break;
        default:
            HandleError();
            CurrentState = EndState;
        }
        break;
    case 4:
        switch (symbol)
        {
        case DIGIT:
            p = p * 10 + d;
            CurrentState = 6;
            break;
        case MINUS:
            e = -1;
            CurrentState = 5;
            break;
        case PLUS:
            CurrentState = 5;
            break;
        default:
            HandleError();
            CurrentState = EndState;
        }
        break;
    case 5:
        switch (symbol)
        {
        case DIGIT:
            p = p * 10 + d;
            CurrentState = 6;
            break;
        default:
            HandleError();
            CurrentState = EndState;
        }
        break;
    case 6:
        switch (symbol)
        {
        case DIGIT:
            p = p * 10 + d;
            break;
        default:
            FCON = w * pow(10, e * p - n);
            CurrentState = EndState;
        }
        break;
    }
    return CurrentState;
}
int LEX(FILE *fp)
{
    int ch;
    CurrentState = 0;
    while (CurrentState != EndState)
    {
        ch = GetChar(fp);
        EXCUTE(CurrentState, ch);
    }
    fseek(fp,-1,1);
    /*printf("\nw: %d  n: %d  p: %d  e: %d  d: %d", w, n, p, e, d);*/
    /*printf("\n ICON: %.3f, FCON: %.3f CLASS: %d\n\n", ICON, FCON, Class);*/
    printf("REAL, %.3f\n", FCON);
}

/***********************************判断实数***********************************/



/************************************判断是否是保留字********************************/
/* 建立保留字表 */
#define MAX_KEY_NUMBER 20                         /*关键字的数量*/
#define KEY_WORD_END "waiting for your expanding" /*关键字结束标记*/
char *KeyWordTable[MAX_KEY_NUMBER] = {"begin", "end", "if", "then", "else", "switch", "case", KEY_WORD_END};
/* 查保留字表,判断是否为关键字 
不是关键字,返回0,是关键字,返回n+1, n为关键字数组中所找到的相同的关键字的索引位置*/
int lookup(char *token)
{
    int n = 0;
    while (strcmp(KeyWordTable[n], KEY_WORD_END)) /*如果比较到最后一位,也就是KEY_WORD_END,也就是已经确定都没有相同的,返回0*/
    {
        /*strcmp比较两串是否相同,若相同返回0*/
        /*相等:strcmp函数返回0,加上!后为:TRUE 进入if内部执行语句;
        不相等: strcmp返回其他正数或负数,这些返回值都等价于:TRUE ,加上!后,都为:FALSE 不进入if内部语句*/
        if (!strcmp(KeyWordTable[n], token))
        {
            return n + 1; /*根据单词分类码表I,设置正确的关键字类别码,并返回此类别码的值*/
            break;
        }
        n++;
    }
    return 0; /*单词不是关键字,而是标识符*/
}
/************************************判断是否是保留字***************************************/




/**********************************非实数的所有显示与报错*********************************************/
void report_error(char *s)
{
    printf("Having Error:%s\n",s);
}
void out(int x, char *s)
{
    switch (x)
    {
    case 7:
    {
        printf("%s,%s\n", "ID", s);
        break;
    }
    case 8:
    {
        printf("%s,%s\n", "INT", s);
        break;
    }
    case 10:
    {
        printf("%s,%s\n", "LT", s);
        break;
    }
    case 11:
    {
        printf("%s,%s\n", "LE", s);
        break;
    }
    case 12:
    {
        printf("%s,%s\n", "EQ", s);
        break;
    }
    case 13:
    {
        printf("%s,%s\n", "NE", s);
        break;
    }
    case 14:
    {
        printf("%s,%s\n", "GT", s);
        break;
    }
    case 15:
    {
        printf("%s,%s\n", "GE", s);
        break;
    }
    case 16:
    {
        printf("%s,%s\n", "IS", s);
        break;
    }
    case 17:
    {
        printf("%s,%s\n", "PL", s);
        break;
    }
    case 18:
    {
        printf("%s,%s\n", "MI", s);
        break;
    }
    case 19:
    {
        printf("%s,%s\n", "MU", s);
        break;
    }
    case 20:
    {
        printf("%s,%s\n", "DI", s);
        break;
    }
    default:
    {
        printf("%s,%s\n", KeyWordTable[x], s);
        break;
    }
    }
}
/**********************************非实数的所有显示与报错*********************************************/



/**********************************扫描一次*********************************************/
void scanner_example(FILE *fp)
{
    char TOKEN[20] = {};
    char ch;
    int i = 0;
    int c = 0;
    ch = fgetc(fp); /*取出一个字符*/

    /*首字符为字母,字母数字混杂*/
    if (isalpha(ch)) /*是否是字母*/
    {
        TOKEN[0] = ch;
        ch = fgetc(fp); /*取出下一个字符*/
        i = 1;
        while (isalnum(ch)) /*是否是字母或者数字*/
        {
            TOKEN[i] = ch;
            i++;
            ch = fgetc(fp); /*取出一个字符*/
        }
        /*跳出循环之后,fp指针指向的字符,不再是数字或者字母*/
        fseek(fp, -1, 1);  /*fp指针从当前位置往前挪一位*/
        c = lookup(TOKEN); /*判断是否是关键字,不是的话返回0*/
        if (c == 0)
            out(ID, TOKEN);
        else
            out(c - 1, " "); /*因为lookup函数返回值为n+1*/
    }
    /*首字符是数字,整型数字*/
    else if (isdigit(ch)) /*是否是数字*/
    {
        TOKEN[0] = ch;
        ch = fgetc(fp); /*取出第二个字符*/
        i = 1;
        while (isdigit(ch)) /*后面取出的字符都依然是数字*/
        {
            TOKEN[i] = ch;
            i++;
            ch = fgetc(fp);
        }
        /*跳出循环之后,fp指针指向的字符,不再是数字*/
        if (ch != 'E' && ch != 'e' && ch != '.')
        {
            fseek(fp, -1, 1); /*fp指针从当前位置往前挪一位*/
            out(INT, TOKEN);
        }
        else /*考虑实型常数*/
        {
            fseek(fp, -(i + 1), 1);
            LEX(fp);
        }
    }
    else
    {
        switch (ch)
        {
        case '<':
        {
            ch = fgetc(fp);
            if (ch == '=')
                out(LE, " ");
            else if (ch == '>')
                out(NE, " ");
            else
            {                     /*下一位不是=或者> :当做只有< */
                fseek(fp, -1, 1); /*fp指针从当前位置往前挪一位*/
                out(LT, " ");
            }
            break;
        }
        case '=':
        {
            out(EQ, " ");
            break;
        }
        case '>':
        {
            ch = fgetc(fp);
            if (ch == '=')
                out(GE, " ");
            else
            {                     /*下一位不是= :当做只有> */
                fseek(fp, -1, 1); /*fp指针从当前位置往前挪一位*/
                out(GT, " ");
            }
            break;
        }
        case ':':
        {
            ch = fgetc(fp);
            if (ch == '=')
            {
                out(IS, " ");
            }
            else
            { /*冒号后面跟着的不是等号的话*/
                report_error(":");
                fseek(fp, -1, 1);
            }
            break;
        }
        case '+':
        {
            out(PL, " ");
            break;
        }
        case '-':
        {
            out(MI, " ");
            break;
        }
        case '*':
        {
            out(MU, " ");
            break;
        }
        case '/':
        {
            out(DI, " ");
            break;
        }
        case ' ':
        {
            break;
        }
        case '\n':
        { 
            break;
        } 
        default:
        {
            report_error(&ch);
            break;
        }
        }
    }

    return;
}
/**********************************扫描一次*********************************************/




int main()
{
    FILE *fp = NULL;
    fp = fopen("Test.txt", "r");
    char ch;
    while (1)
    {
        ch = fgetc(fp);
        if (ch != EOF)
        {
            fseek(fp, -1, 1);
        }
        else
        {
            break;
        }
        scanner_example(fp);
    }
    fclose(fp);
    system("pause");
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值