编译原理表驱动的语法分析程序

代码按照教材上的说明编写。不明白可以参考教材相应内容。由于本人是自学的,不是软件相关专业的学生,所以不排除代码有错误。以下代码中的quDongTable中的数值表示的是语法表达式的序号,顺序按照前三行注释中的顺序来。\x00表示E=TG;\x01表示G=+TG……;\xff表示出错。本代码测试环境是VS2015和Qt5.9,经过简单的测试可以正确检测表达式是否有误。

#include "qstring.h"
#include "qstack.h"

// E = TG
// G = +TG | -TG | 空
// T = (E) | id

//---------------------------------------------------------------------------------------
//        +        -        (        )        id        #
// E                        TG                TG        
// G      +TG      -TG               空                 空
// T                        (E)               id        
//---------------------------------------------------------------------------------------

const static char* quDongTable[] =
{
    "\xff\xff\x00\xff\x00\xff",
    "\x01\x02\xff\x03\xff\x03",
    "\xff\xff\x04\xff\x05\xff",
};

enum TokenType
{
    TOKEN_NONE,
    STRING_NUMBER,
    STRING_PLUS,
    STRING_MINUS,
    STRING_L, /* 左括号 */
    STRING_R, /* 右括号 */
    STRING_END_TAG,
};

struct Token
{
    TokenType type;
    float value;
    QString str;
};

#define NT_E 0
#define NT_T 1
#define NT_G 2
#define NT_NUMBER 3
#define NT_PLUS 4
#define NT_MINUS 5
#define NT_L 6
#define NT_R 7
#define NT_END_TAG 8

int indexOfNonterminator(int nt)
{
    switch (nt)
    {
    case NT_E:
        return 0;
    case NT_G:
        return 1;
    case NT_T:
        return 2;
    default:
        Q_ASSERT(0);
        break;
    }
    return -1;
}

int indexOfToken(const Token& token)
{
    switch (token.type)
    {
    case STRING_PLUS:
        return 0;
    case STRING_MINUS:
        return 1;
    case STRING_L:
        return 2;
    case STRING_R:
        return 3;
    case STRING_NUMBER:
        return 4;
    case STRING_END_TAG:
        return 5;
    default:
        Q_ASSERT(0);
        break;
    }
    return -1;
}

bool checkSyntax(const QVector<Token>& tokens)
{
    QStack<int> nonterminators;
    nonterminators.push(NT_END_TAG);
    nonterminators.push(NT_E);
    int i = 0;
    while (i < tokens.size())
    {
        int stop = nonterminators.pop();
        Token peek = tokens[i];
        if ((stop == NT_PLUS && peek.type == STRING_PLUS) ||
            (stop == NT_MINUS && peek.type == STRING_MINUS) ||
            (stop == NT_L && peek.type == STRING_L) ||
            (stop == NT_R && peek.type == STRING_R) ||
            (stop == NT_NUMBER && peek.type == STRING_NUMBER) ||
            (stop == NT_END_TAG && peek.type == STRING_END_TAG))
        {
            i++;
            continue;
        }
        else if (stop == NT_E || stop == NT_G || stop == NT_T)
        {
            int row = indexOfNonterminator(stop);
            int col = indexOfToken(peek);
            int index = quDongTable[row][col];
            if (index >= 0) /* != 0xff */
            {
                switch (index)
                {
                case 0:
                    nonterminators.push(NT_G);
                    nonterminators.push(NT_T);
                    break;
                case 1:
                    nonterminators.push(NT_G);
                    nonterminators.push(NT_T);
                    nonterminators.push(NT_PLUS);
                    break;
                case 2:
                    nonterminators.push(NT_G);
                    nonterminators.push(NT_T);
                    nonterminators.push(NT_MINUS);
                    break;
                case 3:
                    break;
                case 4:
                    nonterminators.push(NT_R);
                    nonterminators.push(NT_E);
                    nonterminators.push(NT_L);
                    break;
                case 5:
                    nonterminators.push(NT_NUMBER);
                    break;
                }
                continue;
            }
        }
        break; /* error. */
    }
    bool good = (nonterminators.empty() && i == tokens.size());
    return good;
}

bool test()
{
    QVector<Token> tokens;
    tokens.push_back({ STRING_NUMBER, 32.5f, "32.5" });
    tokens.push_back({ STRING_PLUS, 0, "+" });
    tokens.push_back({ STRING_L, 0, "(" });
    tokens.push_back({ STRING_L, 0, "(" });
    tokens.push_back({ STRING_NUMBER, 0.32f, "0.32" });
    tokens.push_back({ STRING_R, 0, ")" });
    tokens.push_back({ STRING_MINUS, 0, "-" });
    tokens.push_back({ STRING_NUMBER, 33.5f, "33.5" });
    tokens.push_back({ STRING_R, 0, ")" });
    tokens.push_back({ STRING_END_TAG, 0, "#" });
    bool good = checkSyntax(tokens);
    return good;
}

附教材相关内容的图片:

 

posted @ 2022-11-06 14:25  兜尼完  阅读(53)  评论(0编辑  收藏  举报