编译原理实验二(只能逐行识别,一个正确的语法如果跨行存在则默认为是两行语法则这两行可能出现语法错误)

编译原理实验二(只能逐行识别,一个正确的语法如果跨行存在则默认为是两行语法则这两行可能出现语法错误)

以前的思路是用二维数组整个把文件的内容全读下来,然后对这个二维数组逐行分析,但是问题在于如果需要分析的文件内容特别多,这个二维数组会无限大,然后这里改用一维数组,读一行就往一维数组里存进去一次,然后进行语法分析,然后清空这个一维数组的全部内容,再读入下一行如此循环

局限性:1、如果一行特别长,超过一维数组的给定长度,那用一位数组读入则可能无法实现(不过也许可以考虑使用容器,但是应该也是会可能存在问题 2、按行识别,则如果一个正确的语法如果跨行存在则默认为是两行语法则这两行可能出现语法错误

实验结果

在这里插入图片描述

       (       )       +       -       *       /       I       #       E       T       F
0       S4                                              S5              1       2       3
1                       S6      S7                              Acc
2               R3      R3      R3      S8      S9              R3
3               R6      R6      R6      R6      R6              R6
4       S4      R3                                      S5              10      2       3
5               R8      R8      R8      R8      R8              R8
6       S4                                              S5                      11      3
7       S4                                              S5                      12      3
8       S4                                              S5                              13
9       S4                                              S5                              14
10              S15     S6      S7                                      1       11      3
11              R1      R1      R1      S8      S9              R1
12              R2      R2      R2      S8      S9              R2
13              R4      R4      R4      R4      R4              R4
14              R5      R5      R5      R5      R5              R5
15              R7      R7      R7      R7      R7              R7
第  0  行词法分析结果:
第0行为空行

第  1  行词法分析结果:
INT,12
PL,
LP,
INT,25
MU,
INT,66
DI,
INT,35
MI,
LP,
INT,66
PL,
INT,9
DI,
INT,2
MU,
INT,5
CP,
DI,
REAL, 22.600
MU,
REAL, 0.235
CP,

INT PL LP INT MU INT DI INT MI LP INT PL INT DI INT MU INT CP DI REAL MU REAL CP
# I + ( I * I / I - ( I + I / I * I ) / I * I ) #1  行语法分析结果(基础运算):

状态栈最后结果(从栈顶到栈底)1 0
符号栈最后结果(从栈顶到栈底):
E #
第1个语法正确

第  2  行词法分析结果:
REAL, 0.568
PL,
REAL, 15.888
DI,
INT,25
MI,
LP,
INT,56
PL,
INT,9999
MU,
REAL, 0.250
CP,
if,

Error: 第2行,第13位非基本运算符号,而是if

第  3  行词法分析结果:
INT,15
PL,
ID,kkkk25
PL,
INT,56
DI,
INT,65
MU,
INT,89
PL,
INT,89
MU,
INT,90

Error: 第3行,第2位非基本运算符号,而是ID

第  4  行词法分析结果:
第4行为空行

第  5  行词法分析结果:
LP,
INT,12
PL,
INT,56
DI,
INT,65
MU,
INT,20
MI,
INT,800
CP,

LP INT PL INT DI INT MU INT MI INT CP
# ( I + I / I * I - I ) #5  行语法分析结果(基础运算):

状态栈最后结果(从栈顶到栈底)1 0
符号栈最后结果(从栈顶到栈底):
E #
第5个语法正确

第  6  行词法分析结果:
第6行为空行

第  7  行词法分析结果:
INT,15
PL,
INT,25
PL,
INT,69
MU,
REAL, 7.630

INT PL INT PL INT MU REAL
# I + I + I * I #7  行语法分析结果(基础运算):

状态栈最后结果(从栈顶到栈底)1 0
符号栈最后结果(从栈顶到栈底):
E #
第7个语法正确

第  8  行词法分析结果:
第8行为空行

第  9  行词法分析结果:
PL,
REAL, 88.560

PL REAL
# + I #9  行语法分析结果(基础运算):
Error state and charset: 0,#
Error_message:Action[state.top()][ReturnAction_fromArray(charArray,*new_status[j])] == NULL
第x行: 9        第j位: 0
new_status[j]: #
状态栈最后结果(从栈顶到栈底)0
符号栈最后结果(从栈顶到栈底)#
第9个语法存在错误

第  10  行词法分析结果:
第10行为空行

第  11  行词法分析结果:
MU,
INT,9999

MU INT
# * I #11  行语法分析结果(基础运算):
Error state and charset: 0,#
Error_message:Action[state.top()][ReturnAction_fromArray(charArray,*new_status[j])] == NULL
第x行: 11       第j位: 0
new_status[j]: #
状态栈最后结果(从栈顶到栈底)0
符号栈最后结果(从栈顶到栈底)#
第11个语法存在错误

第  12  行词法分析结果:
第12行为空行

第  13  行词法分析结果:
INT,55
PL,
PL,
REAL, 65.560

INT PL PL REAL
# I + + I #13  行语法分析结果(基础运算):
Error state and charset: 6,+
Error_message:Action[state.top()][ReturnAction_fromArray(charArray,*new_status[j])] == NULL
第x行: 13       第j位: 2
new_status[j]: +
状态栈最后结果(从栈顶到栈底)6 1 0
符号栈最后结果(从栈顶到栈底):
+ E #
第13个语法存在错误

第  14  行词法分析结果:
第14行为空行

第  15  行词法分析结果:
REAL, 0.236
MU,
MU,
MU,
MU,
INT,56789

REAL MU MU MU MU INT
# I * * * * I #15  行语法分析结果(基础运算):
Error state and charset: 8,*
Error_message:Action[state.top()][ReturnAction_fromArray(charArray,*new_status[j])] == NULL
第x行: 15       第j位: 2
new_status[j]: *
状态栈最后结果(从栈顶到栈底)8 2 0
符号栈最后结果(从栈顶到栈底):
* T #
第15个语法存在错误

第  16  行词法分析结果:
第16行为空行

第  17  行词法分析结果:
REAL, 0.560
LP,
PL,
REAL, 23689.119

REAL LP PL REAL
# I ( + I #17  行语法分析结果(基础运算):
Error state and charset: 5,I
Error_message:Action[state.top()][ReturnAction_fromArray(charArray,*new_status[j])] == NULL
第x行: 17       第j位: 1
new_status[j]: I
状态栈最后结果(从栈顶到栈底)5 0
符号栈最后结果(从栈顶到栈底):
I #
第17个语法存在错误

第  18  行词法分析结果:
第18行为空行

第  19  行词法分析结果:
LP,
INT,56
PL,
INT,88
PL,
INT,65

LP INT PL INT PL INT
# ( I + I + I #19  行语法分析结果(基础运算):
Error state and charset: 10,E
Error_message:Action[state.top()][ReturnAction_fromArray(charArray,*new_status[j])] == NULL
第x行: 19       第j位: 6
new_status[j]: I
状态栈最后结果(从栈顶到栈底)10 4 0
符号栈最后结果(从栈顶到栈底):
E ( #
第19个语法存在错误

第  20  行词法分析结果:
第20行为空行

第  21  行词法分析结果:
REAL, 22.500
CP,

REAL CP
# I ) #21  行语法分析结果(基础运算):
Error state and charset: 1,E
Error_message:Action[state.top()][ReturnAction_fromArray(charArray,*new_status[j])] == NULL
第x行: 21       第j位: 1
new_status[j]: I
状态栈最后结果(从栈顶到栈底)1 0
符号栈最后结果(从栈顶到栈底):
E #
第21个语法存在错误

第  22  行词法分析结果:
第22行为空行

第  23  行词法分析结果:
else,

Error: 第23行,第0位非基本运算符号,而是else

第  24  行词法分析结果:
第 24行不存在,文件已经结尾

请按任意键继续. . .

源代码

#include <iostream>
#include <cstring>
#include <math.h>
#include <stdlib.h>
#include <string>
#include <stack>
#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 LP 21  /*(*/
#define CP 22  /*)*/

/****************************判断实数**************************************/
#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;
int out_symbol = 0;
int out_symbol_big = 0;
int word_error = 0;
/***********保存所有的状态在一个二维字符串数组里(文件有几行,状态有几行)(为实验二做准备)*************/
char *status[100];
int status_count_row = 0;
int status_usable_count_row = 0;
/**********保存所有的状态在一个二维字符串数组里(文件有几行,状态有几行)(为实验二做准备)**************/

/*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);

    status[status_count_row] = "REAL";
    status_count_row++;
}

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

/************************************判断是否是保留字********************************/
/* 建立保留字表 */
#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);
    status[status_count_row] = "Having Error in word";
    status_count_row++;
    word_error = 1;
}
void out(int x, char *s)
{
    switch (x)
    {
    case 7:
    {
        printf("%s,%s\n", "ID", s);

        status[status_count_row] = "ID";
        status_count_row++;

        break;
    }
    case 8:
    {
        printf("%s,%s\n", "INT", s);

        status[status_count_row] = "INT";
        status_count_row++;

        break;
    }
    case 10:
    {
        printf("%s,%s\n", "LT", s);

        status[status_count_row] = "LT";
        status_count_row++;

        break;
    }
    case 11:
    {
        printf("%s,%s\n", "LE", s);

        status[status_count_row] = "LE";
        status_count_row++;

        break;
    }
    case 12:
    {
        printf("%s,%s\n", "EQ", s);

        status[status_count_row] = "EQ";
        status_count_row++;

        break;
    }
    case 13:
    {
        printf("%s,%s\n", "NE", s);

        status[status_count_row] = "NE";
        status_count_row++;

        break;
    }
    case 14:
    {
        printf("%s,%s\n", "GT", s);

        status[status_count_row] = "GT";
        status_count_row++;

        break;
    }
    case 15:
    {
        printf("%s,%s\n", "GE", s);

        status[status_count_row] = "GE";
        status_count_row++;

        break;
    }
    case 16:
    {
        printf("%s,%s\n", "IS", s);

        status[status_count_row] = "IS";
        status_count_row++;

        break;
    }
    case 17:
    {
        printf("%s,%s\n", "PL", s);

        status[status_count_row] = "PL";
        status_count_row++;

        break;
    }
    case 18:
    {
        printf("%s,%s\n", "MI", s);

        status[status_count_row] = "MI";
        status_count_row++;

        break;
    }
    case 19:
    {
        printf("%s,%s\n", "MU", s);

        status[status_count_row] = "MU";
        status_count_row++;

        break;
    }
    case 20:
    {
        printf("%s,%s\n", "DI", s);

        status[status_count_row] = "DI";
        status_count_row++;

        break;
    }
    case 21:
    {
        printf("%s,%s\n", "LP", s);

        status[status_count_row] = "LP";
        status_count_row++;

        break;
    }
    case 22:
    {
        printf("%s,%s\n", "CP", s);

        status[status_count_row] = "CP";
        status_count_row++;

        break;
    }
    default:
    {
        printf("%s,%s\n", KeyWordTable[x], s);

        status[status_count_row] = KeyWordTable[x];
        status_count_row++;

        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':
        {
            out_symbol = 1;
            break;
        }
        case '(':
        {
            out(LP, " ");
            break;
        }
        case ')':
        {
            out(CP, " ");
            break;
        }
        default:
        {
            report_error(&ch);
            break;
        }
        }
    }

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

/*****************************实验二***************************************************/

/****************************建表*********************/
using namespace std;
int Goto[16][3] = {0};
std::string Action[16][8];
char charArray[50];
void show_status(char *status[][100])
{
    int j = 0;
    for (int i = 0; i <= status_count_row; i++)
    {
        while (status[i][j] != nullptr)
        {
            cout << status[i][j] << " ";
            j++;
        }
        if (j != 0)
        {
            cout << endl;
            j = 0;
            if (status[i][0] != "#")
            {
                status_usable_count_row++;
                /*计算非空行行数*/
            }
        }
    }
    cout << "在show函数中,在用它展示任意一个status的时候,排出空行(二维数组里面一行都是null的为空行)计算了非空行数" << endl;
    cout << "此非空行数为:status_usable_count_row :" << status_usable_count_row << endl;
}
void Create_tableofAction(string Action[][8])
{
    Action[0][0] = "S4";
    Action[0][6] = "S5";
    Action[1][2] = "S6";
    Action[1][3] = "S7";
    Action[1][7] = "Acc";
    Action[2][1] = "R3";
    Action[2][2] = "R3";
    Action[2][3] = "R3";
    Action[2][4] = "S8";
    Action[2][5] = "S9";
    Action[2][7] = "R3";
    Action[3][1] = "R6";
    Action[3][2] = "R6";
    Action[3][3] = "R6";
    Action[3][4] = "R6";
    Action[3][5] = "R6";
    Action[3][7] = "R6";
    Action[4][0] = "S4";
    Action[4][1] = "R3";
    Action[4][6] = "S5";
    Action[5][1] = "R8";
    Action[5][2] = "R8";
    Action[5][3] = "R8";
    Action[5][4] = "R8";
    Action[5][5] = "R8";
    Action[5][7] = "R8";
    Action[6][0] = "S4";
    Action[6][6] = "S5";
    Action[7][0] = "S4";
    Action[7][6] = "S5";
    Action[8][0] = "S4";
    Action[8][6] = "S5";
    Action[9][0] = "S4";
    Action[9][6] = "S5";
    Action[10][1] = "S15";
    Action[10][2] = "S6";
    Action[10][3] = "S7";
    Action[11][1] = "R1";
    Action[11][2] = "R1";
    Action[11][3] = "R1";
    Action[11][4] = "S8";
    Action[11][5] = "S9";
    Action[11][7] = "R1";
    Action[12][1] = "R2";
    Action[12][2] = "R2";
    Action[12][3] = "R2";
    Action[12][4] = "S8";
    Action[12][5] = "S9";
    Action[12][7] = "R2";
    Action[13][1] = "R4";
    Action[13][2] = "R4";
    Action[13][3] = "R4";
    Action[13][4] = "R4";
    Action[13][5] = "R4";
    Action[13][7] = "R4";
    Action[14][1] = "R5";
    Action[14][2] = "R5";
    Action[14][3] = "R5";
    Action[14][4] = "R5";
    Action[14][5] = "R5";
    Action[14][7] = "R5";
    Action[15][1] = "R7";
    Action[15][2] = "R7";
    Action[15][3] = "R7";
    Action[15][4] = "R7";
    Action[15][5] = "R7";
    Action[15][7] = "R7";
}
void Create_tableofGoto(int Goto[][3])
{
    Goto[0][0] = 1;
    Goto[0][1] = 2;
    Goto[0][2] = 3;
    Goto[4][0] = 10;
    Goto[4][1] = 2;
    Goto[4][2] = 3;
    Goto[6][1] = 11;
    Goto[6][2] = 3;
    Goto[7][1] = 12;
    Goto[7][2] = 3;
    Goto[8][2] = 13;
    Goto[9][2] = 14;
    Goto[10][2] = 3;
    Goto[10][1] = 11;
    Goto[10][0] = 1;
}
void Create_charArrray(char charArray[])
{
    charArray[0] = '(';
    charArray[1] = ')';
    charArray[2] = '+';
    charArray[3] = '-';
    charArray[4] = '*';
    charArray[5] = '/';
    charArray[6] = 'I';
    charArray[7] = '#';
    charArray[8] = 'E';
    charArray[9] = 'T';
    charArray[10] = 'F';
}
int ReturnAction_fromArray(char charArray[], char ch)
{
    for (int i = 0; i <= 7; i++)
    {
        if (ch == charArray[i])
        {
            return i;
        }
    }
}
int ReturnGoto_fromArray(char charArray[], char ch)
{
    for (int i = 8; i < 11; i++)
    {
        if (ch == charArray[i])
        {
            return i;
        }
    }
}
void show_tables(string Action[][8], int Goto[][3])
{
    cout << "\t";
    for (int i = 0; i < 11; i++)
    {
        cout << charArray[i] << '\t';
    }
    cout << endl;
    for (int i = 0; i < 16; i++)
    {
        cout << i << "\t";
        for (int j = 0; j < 8; j++)
        {
            cout << Action[i][j] << "\t";
        }
        for (int j = 0; j < 3; j++)
        {
            if (Goto[i][j] != 0)
            {
                cout << Goto[i][j] << "\t";
            }
            else
            {
                cout << "\t";
            }
        }
        cout << endl;
    }
}
/****************************建表*********************/
stack<int> state;
stack<char *> charset;
int status_error = 0;
char *new_status[100];
void Create_new_status(char *status[], char *new_status[],int x)
{
    for (int i = 0; i < status_count_row; i++)
    {
        if (status[i] != nullptr)
        {
            new_status[0] = "#";
            if (status[i] == "REAL" || status[i] == "INT")
            {
                new_status[i + 1] = "I";
            }
            else
            {
                if (status[i] == "PL")
                {
                    new_status[i + 1] = "+";
                }
                else
                {
                    if (status[i] == "MI")
                    {
                        new_status[i + 1] = "-";
                    }
                    else
                    {
                        if (status[i] == "MU")
                        {
                            new_status[i + 1] = "*";
                        }
                        else
                        {
                            if (status[i] == "DI")
                            {
                                new_status[i + 1] = "/";
                            }
                            else
                            {
                                if (status[i] == "LP")
                                {
                                    new_status[i + 1] = "(";
                                }
                                else
                                {
                                    if(status[i] == "CP")
                                    {
                                        new_status[i + 1] = ")";
                                    }
                                    else
                                    {
                                        cout << "Error: " << "第" << x <<"行,第"<< i << "位非基本运算符号,而是" << status[i] << endl << endl;
                                        status_error = 1;
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    new_status[status_count_row + 1] = "#";
    status_usable_count_row = status_count_row + 2; /*new_status的数据范围 : 0 到 status_usable_count_row - 1*/
    for (int i = 0; i < status_count_row; i++)
    {
        cout << status[i] << " ";
    }
    cout << endl;
    for (int i = 0; i < status_count_row + 2; i++)
    {
        if (new_status[i] != nullptr)
        {
            cout << new_status[i] << " ";
        }
    }
    cout << endl << endl;
}

/*R1-8:右部文法用string字符串存储,左部文法用char单个字符存储、右部文法字符串长度int
从符号栈中取出字符组成临时string字符串与右部文法的string字符串比较*/
void Return_error(int state, char charset, string Error_message, int x, int j)
{
    cout << "Error state and charset: " << state << "," << charset;
    cout << endl << "Error_message:" << Error_message << endl;
    cout << "第x行: " << x << '\t' << "第j位: " << j << endl;
    cout << "new_status[j]: " << new_status[j];
    status_error = 1;
}
struct Left
{
    char Left_ch;
    string Right;
};
Left wenfa[8] =
    {
        {'E', "E+T"},
        {'E', "E-T"},
        {'E', "T"},
        {'T', "T*F"},
        {'T', "T/F"},
        {'T', "F"},
        {'F', "(E)"},
        {'F', "I"}};
void Second_operate(char *new_status[], stack<int> state, stack<char *> charset, Left left_wenfa[],int x)
{
    int j = 0;
    charset.push(new_status[j]); /*符号栈压入#*/
    state.push(j);               /*状态栈压入0*/
    j++;/*j==1*/
    while (!state.empty() && !charset.empty() && j < status_usable_count_row && Action[state.top()][ReturnAction_fromArray(charArray, *new_status[j])] != "Acc" )
    {
        if (Action[state.top()][ReturnAction_fromArray(charArray, *new_status[j])] == "")
        {
            Return_error(state.top(), *charset.top(), "Action[state.top()][ReturnAction_fromArray(charArray,*new_status[j])] == NULL", x, j-1);
            break;
        }
        else if (Action[state.top()][ReturnAction_fromArray(charArray, *new_status[j])].at(0) == 'S')
        {
            int next_state;
            if (Action[state.top()][ReturnAction_fromArray(charArray, *new_status[j])].length() == 2)
            {
                next_state = Action[state.top()][ReturnAction_fromArray(charArray, *new_status[j])].at(1) - '0';
            }
            if (Action[state.top()][ReturnAction_fromArray(charArray, *new_status[j])].length() == 3)
            {
                next_state = 10 * (Action[state.top()][ReturnAction_fromArray(charArray, *new_status[j])].at(1) - '0') + (Action[state.top()][ReturnAction_fromArray(charArray, *new_status[j])].at(2) - '0');
            }

            state.push(next_state);
            if (new_status[j] != nullptr)
            {
                charset.push(new_status[j]);
            }
            j++;
        }
        else if (Action[state.top()][ReturnAction_fromArray(charArray, *new_status[j])].at(0) == 'R')
        {
            int i_fromNew = ReturnAction_fromArray(charArray, *(new_status[j]));

            int instruction;
            if (Action[state.top()][i_fromNew].length() == 2)
            {
                instruction = Action[state.top()][i_fromNew].at(1) - '0';
            }
            if (Action[state.top()][i_fromNew].length() == 3)
            {
                instruction = 10 * (Action[state.top()][i_fromNew].at(1) - '0') + (Action[state.top()][i_fromNew].at(2) - '0');
            }

            string right = left_wenfa[instruction - 1].Right;
            string compare;
            if (charset.size() >= right.length())
            {
                char *fan_compare[3];
                for (int length = 0; length < right.length(); length++)
                {
                    fan_compare[length] = charset.top();
                    charset.pop();
                }
                for (int length = right.length() - 1; length >= 0; length--)
                {
                    compare.append(fan_compare[length]);
                }
                if (compare == right && state.size() >= right.length())
                {
                    for (int length = 0; length < right.length(); length++)
                    {
                        state.pop();
                    }
                    if (!state.empty())
                    {
                        char *leftx = &left_wenfa[instruction - 1].Left_ch;
                        int i_leftx = ReturnGoto_fromArray(charArray, *leftx) - 8;
                        state.push(Goto[state.top()][i_leftx]);
                        charset.push(leftx);
                    }
                    else
                    {
                        Return_error(state.top(), *charset.top(), "state.empty()", x, j-1);
                        break;
                    }
                }
                else
                {
                    Return_error(state.top(), *charset.top(), "!(compare == right && state.size() >= right.length())", x, j-1);
                    break;
                }
            }
            else
            {
                Return_error(state.top(), *charset.top(), "!(charset.size() >= right.length())", x, j-1);
                break;
            }
        }
        
        if(j>=status_usable_count_row)
        {
            break;
        }
    }
    
    j = 0;
    cout << endl;
    cout << "状态栈最后结果(从栈顶到栈底):" << endl;
    while (!state.empty())
    {
        cout << state.top() << " ";
        state.pop();
    }
    cout << endl;
    int length_end = charset.size();
    string string_end;
    cout << "符号栈最后结果(从栈顶到栈底):" << endl;
    while (!charset.empty())
    {
        cout << charset.top() << " ";
        if (charset.size() == 2)
        {
            string_end.append(charset.top());
            charset.pop();
            string_end.append(charset.top());
            cout << charset.top() << " ";
        }
        charset.pop();
    }
    cout << endl;
    if (string_end == "E#" && length_end == 2 && status_error == 0)
    {
        cout << "第" << x << "个语法正确\n\n";
    }
    else
    {
        cout << "第" << x << "个语法存在错误\n\n";
        status_error = 0;
    }
}

/*****************************实验二***************************************************/

void getstring(FILE *fp,int x)
{
    cout << "第  "<< x <<"  行词法分析结果:\n";
    while (1)
    {
        char ch = fgetc(fp);
        if (ch != EOF)
        {
            fseek(fp, -1, 1);
        }
        else
        {
            cout << "第 " << x << "行不存在,文件已经结尾\n";
            out_symbol_big = 1;
            break;
        }
        scanner_example(fp);
        if(word_error == 1)
        {
            break;
        }
        if (out_symbol == 1 && out_symbol_big == 0)
        {
            if(status_count_row == 0)
            {
                cout << "第" << x << "行为空行" << endl;
                status_error = 1;
            }
            out_symbol = 0;
            break;
        }
    }
    cout << endl;
}
void empty_status(char *status[],int status_count_row)
{
    for (int i = 0; i < status_count_row; i++)
    {
        if (status[i] != nullptr)
        {
            status[i] = nullptr;
        }
    }
    status_count_row = 0;
}

int main()
{
    FILE *fp = NULL;
    fp = fopen("Text_4.txt", "r");
    int x = 0;
    Create_charArrray(charArray);
    Create_tableofAction(Action);
    Create_tableofGoto(Goto);
    show_tables(Action, Goto);
    while (1)
    {
        /*词法分析调用,逐行调用*/
        getstring(fp,x);
        if(out_symbol_big == 1)
        {
            break;
        }

        /*非空行或者错行的建数组*/
        if(status_count_row !=0 && word_error == 0)
        {
            Create_new_status(status, new_status,x);
        }

        /*存在别的关键字,不再判断运算公式*/
        if(status_error == 0)
        {
            cout << "第  "<< x <<"  行语法分析结果(基础运算):\n";
            Second_operate(new_status, state, charset, wenfa,x);
        }
        else
        {
            status_error = 0;
        }

        x++;

        empty_status(status,status_count_row);
        empty_status(new_status, status_usable_count_row);
        status_count_row = 0;
        status_usable_count_row = 0;
        status_error = 0;
        word_error = 0;
    }
    fclose(fp);
    system("pause");
}

posted @ 2021-11-19 19:02  在天边偷看小天使  阅读(21)  评论(0)    收藏  举报  来源