LL(1)语法分析器 c++实现

    • 结构
    • 记号和规定
    • 代码
      • Base.h
      • Base.cpp
      • LL1.h
      • LL1.cpp
      • main.cpp
    • 测试样例

结构

  • main.cpp包含了主函数和LL1语法分析过程的调用
  • Base.h和Base.cpp定义了类Base, 类Base用于存储产生式、符号表、FIRST集合FOLLOW集(还可应用于LR分析,故独立出来)
  • LL1.h和LL1.cpp定义了类

LL1, 类LL1继承了Base, 用于生成预测表和分析输入语句.

记号和规定

记号和规定

  • $表示空ε, #表示终止
  • 大写字母为非终结符.
  • 用单个字母表示一个符号
  • 默认第一个产生式的左边那个非终结符就是开始符号
  • 输入的产生式分开写(比如A->a|b, 要输入A->a和A->b才能处理)

代码

Base.h

#ifndef _BASE_H_
#define _BASE_H_
#include 
#include 
#include 
#include 
#include 

#define maxsize 100

using namespace std;

struct node {  // 产生式的数据结构
    char left;
    string right;
};

class Base {
protected:
    int T;
    node production[maxsize]; // 产生式集

    set<char> firstSet[maxsize];  // First集
    set<char> followSet[maxsize];  // Follow集
    vector<char> terminalNoEmpty; // 去$(空)的终结符
    vector<char> terminal;  // 终结符
    vector<char> nonterminal;  // 非终结符

    bool isNonterminal(char c);
    int getIndex(char target);  // 获得target在终结符集合中的下标
    int getNIndex(char target);  // 获得target在非终结符集合中的下标
    void getFirst(char target);  // 得到First(target)
    void getFollow(char target);  // 得到Follow(target)

public:
    Base() {};

    void inputAndSolve();  // 处理和求出First和Follow集
    void displayFirstAndFollow();  // 输出First和Follow集

};
#endif 

Base.cpp

#include "Base.h"

bool Base::isNonterminal(char c) { // 判断c是否为非终结符
    if (c >= 'A' && c <= 'Z')
        return true;
    return false;
}
int Base::getNIndex(char target) {  // 获得target在非终结符集合中的下标
    for (int i = 0; iif (target == nonterminal[i])
            return i;
    }
    return -1;
}
int Base::getIndex(char target) {  // 获得target在终结符集合中的下标
    for (int i = 0; iif (target == terminalNoEmpty[i])
            return i;
    }
    return -1;
}

void Base::getFirst(char target) {  // 求FIRST(target)
    int countEmpty = 0;  // 用于最后判断是否有空
    int isEmpty = 0;
    int targetIndex = getNIndex(target);
    for (int i = 0; i < T; i++) {
        if (production[i].left == target) {  // 匹配产生式左部
            if (!isNonterminal(production[i].right[0])) {  // 对于终结符,直接加入first
                firstSet[targetIndex].insert(production[i].right[0]);
            }
            else {
                for (int j = 0; j < production[i].right.length(); j++) { // X->Y1..Yj..Yk是一个产生式
                    char Yj = production[i].right[j];
                    if (!isNonterminal(Yj)) {  // Yj是终结符(不能产生空),FIRST(Yj)=Yj加入FIRST(X),不能继续迭代,结束
                        firstSet[targetIndex].insert(Yj);
                        break;
                    }
                    getFirst(Yj);// Yj是非终结符,递归 先求出FIRST(Yj)

                    set<char>::iterator it;
                    int YjIndex = getNIndex(Yj);
                    for (it = firstSet[YjIndex].begin(); it != firstSet[YjIndex].end(); it++) {
                        if (*it == '$')  // 遍历查看FIRST(Yj)中是否含有'$'(能产生空)
                            isEmpty = 1;
                        else
                            firstSet[targetIndex].insert(*it);//将FIRST(Yj)中的非$就加入FIRST(X)
                    }
                    if (isEmpty == 0)  // Yj不能产生空, 迭代结束
                        break;
                    else {   //  Yj能产生空
                        countEmpty += isEmpty;
                        isEmpty = 0;
                    }
                }
                if (countEmpty == production[i].right.length())//所有右部first(Y)都有$(空),将$加入FIRST(X)中
                    firstSet[getNIndex(target)].insert('$');
            }
        }
    }
}

void Base::getFollow(char target) {  // 求FOLLOW(target)
    int targetIndex = getNIndex(target);
    for (int i = 0; iint index = -1;
        int len = production[i].right.length();
        for (int j = 0; j < len; j++) {  // 寻找target在产生式中的位置index
            if (production[i].right[j] == target) {
                index = j;
                break;
            }
        }
        if (index != -1 && index < len - 1) {  // 找到target在产生式中的位置index
                                               // 存在A->αBβ, 将FIRST(β)中除了空$之外的所有放入FOLLOW(B)中
                                               // 这里B对应target, β对应nxt
            char nxt = production[i].right[index + 1];
            if (!isNonterminal(nxt)) {  // β是终结符 FIRST(β)=β,直接插入β
                followSet[targetIndex].insert(nxt);
            }
            else {  // β是非终结符
                int hasEmpty = 0;
                set<char>::iterator it;
                int nxtIndex = getNIndex(nxt);  // 插入FIRST(β)中除了空$之外的所有
                for (it = firstSet[nxtIndex].begin(); it != firstSet[nxtIndex].end(); it++) {
                    if (*it == '$')
                        hasEmpty = 1;
                    else
                        followSet[targetIndex].insert(*it);
                }

                if (hasEmpty && production[i].left != target) { // 存在A->αBβ且FIRST(β)->$
                                                             // FOLLOW(A)放在FOLLOW(B)中
                    getFollow(production[i].left);
                    set<char>::iterator it;
                    char tmp = production[i].left;
                    int tmpIndex = getNIndex(tmp);
                    for (it = followSet[tmpIndex].begin(); it != followSet[tmpIndex].end(); it++)
                        followSet[targetIndex].insert(*it);
                }
            }
        }
        else if (index != -1 && index == len - 1 && target != production[i].left) {  // 存在A->αB ,FOLLOW(A)放在FOLLOW(B)中
            getFollow(production[i].left);
            set<char>::iterator it;
            char tmp = production[i].left;
            int tmpIndex = getNIndex(tmp);
            for (it = followSet[tmpIndex].begin(); it != followSet[tmpIndex].end(); it++)
                followSet[targetIndex].insert(*it);
        }
    }
}

void Base::inputAndSolve() {  // 处理和求出First和Follow集
    string s;
    cout << "输入的产生式的个数:" << endl;
    cin >> T;
    cout << "输入的产生式:" << endl;
    for (int index = 0; index < T; index++) {  // 处理每一个产生式
        cin >> s;
        string temp = "";  // 存储去掉空格的产生式
        for (int i = 0; i < s.length(); i++) {  // 去掉产生式中的' '
            if (s[i] != ' ')
                temp += s[i];
        }
        production[index].left = temp[0];  // 产生式的左部
        for (int i = 3; i// 产生式的右部
            production[index].right += temp[i];

        for (int i = 0; i < temp.length(); i++) {  // 存储所有终结符和非终结符
            if (i == 1 || i == 2) continue;  // 跳过产生符号->
            if (isNonterminal(temp[i])) {  //插入一个非终结符
                int flag = 0;
                for (int j = 0; j < nonterminal.size(); j++) {
                    if (nonterminal[j] == temp[i]) {
                        flag = 1;
                        break;
                    }
                }
                if (!flag) nonterminal.push_back(temp[i]);
            }
            else {                       //插入一个终结符
                int flag = 0;
                for (int j = 0; j < terminal.size(); j++) {
                    if (terminal[j] == temp[i]) {
                        flag = 1;
                        break;
                    }
                }
                if (!flag) terminal.push_back(temp[i]);
            }
        }
    }
    terminal.push_back('#');

    for (int i = 0; i < terminal.size(); i++) { // 存储没有$符号的终结符
        if (terminal[i] != '$')
            terminalNoEmpty.push_back(terminal[i]);
    }

    // 获得first集
    for (int i = 0; i < nonterminal.size(); i++) {
        getFirst(nonterminal[i]);
    }

    // 获得follow集
    for (int i = 0; i < nonterminal.size(); i++) {
        if (i == 0)  // 开始符号, 先加入结束符号
            followSet[0].insert('#');
        getFollow(nonterminal[i]);
    }
}

void Base::displayFirstAndFollow() {  // 输出First和Follow集
    cout << "FIRST集合" << endl;
    for (int i = 0; icout << nonterminal[i] << ": ";
        set<char>::iterator it;
        for (it = firstSet[i].begin(); it != firstSet[i].end(); it++)
            cout << *it << "  ";
        cout << endl;
    }
    cout << endl;

    cout << "FOLLOW集合" << endl;
    for (int i = 0; icout << nonterminal[i] << ": ";
        set<char>::iterator it;
        for (it = followSet[i].begin(); it != followSet[i].end(); it++)
            cout << *it << "  ";
        cout << endl;
    }
    cout << endl;
}

LL1.h

#ifndef _LL1_H_
#define _LL1_H_

#include"Base.h"

class LL1 : public Base {
private:
    vector<char> analyStack; // 分析栈
    vector<char> leftExpr;  // 剩余输入串
    int tableMap[100][100];  // 预测表

public:
    LL1();

    void getTable(); // 生成预测表
    void analyExpression(string s);  // 分析输入语句s
    void printPredictTable();  // 输出预测表
    void getResult(); // 综合处理
};
#endif
}

LL1.cpp

#include"LL1.h"

LL1::LL1() {
    memset(tableMap, -1, sizeof(tableMap));
}

void LL1::getTable() {
    for (int index = 0; index < T; index++) {                          // 对于每个产生式(编号index):A->α
        int row = getNIndex(production[index].left);
        int emptyCount = 0;
        for (int i = 0; i < production[index].right.size(); i++) { // 1) 对FIRST(α)中的每个终结符号a,将index加入(A, a)中
            char tmp = production[index].right[i];
            if (!isNonterminal(tmp)) { // tmp是终结符          
                if (tmp != '$')
                    tableMap[row][getIndex(tmp)] = index;
                if (tmp == '$') {                              
                    emptyCount++;
                }
                break;
            }
            else {  // tmp是非终结符
                set<char>::iterator it;
                int tmpIndex = getNIndex(tmp);
                // 对FIRST(tmp)中的每个终结符号a,将i加入(A, a)中
                for (it = firstSet[tmpIndex].begin(); it != firstSet[tmpIndex].end(); it++) {
                    tableMap[row][getIndex(*it)] = index;
                }
                if (firstSet[tmpIndex].count('$') != 0) {      // 2) 如果空$在FIRST(tmp)中,继续看α中的下一个符号
                    emptyCount++;
                }
                else {
                    break;
                }
            }
        }

        // 2) 如果空$在FIRST(α)中,对FOLLOW(A)中的每个终结符或结束符b,将i加入(A,b)中
        if (emptyCount == production[index].right.size()) {
            set<char>::iterator  it;
            for (it = followSet[row].begin(); it != followSet[row].end(); it++) {
                tableMap[row][getIndex(*it)] = index;
            }
        }
    }
}

void LL1::analyExpression(string s) {
    for (int i = 0; i < s.size(); i++)
        leftExpr.push_back(s[i]);
    leftExpr.push_back('#');

    analyStack.push_back('#');
    analyStack.push_back(nonterminal[0]);  // 加入开始符号

    while (analyStack.size() > 0) {
        //cout<<"分析栈:";
        string outs = "";
        for (int i = 0; i < analyStack.size(); i++)
            outs += analyStack[i];
        cout << setw(15) << outs;

        //cout<<"剩余输入串:";
        outs = "";
        for (int i = 0; i < leftExpr.size(); i++)
            outs += leftExpr[i];
        cout << setw(15) << outs;

        // 匹配
        char char1 = analyStack.back();
        char char2 = leftExpr.front();
        if (char1 == char2 && char1 == '#') {
            cout << setw(15) << "Accepted!" << endl;
            return;
        }
        if (char1 == char2) {
            analyStack.pop_back();
            leftExpr.erase(leftExpr.begin());
            cout << setw(15) << "匹配:" << char1 << endl;
        }
        else if (tableMap[getNIndex(char1)][getIndex(char2)] != -1) {  // 预测表中有推倒项,可进行推导
            int tg = tableMap[getNIndex(char1)][getIndex(char2)];
            analyStack.pop_back();

            if (production[tg].right != "$") {
                for (int i = production[tg].right.length() - 1; i >= 0; i--) // 注意这里是反向的
                    analyStack.push_back(production[tg].right[i]);
            }

            cout << setw(15) << "推导:" << production[tg].left << "->" << production[tg].right << endl;
        }
        else {  // 错误
            cout << setw(15) << "error!" << endl;
            return;
        }
    }
}

void LL1::printPredictTable() {
    // 表头
    for (int i = 0; i < terminalNoEmpty.size(); i++) {
        cout << setw(10) << terminalNoEmpty[i];
    }
    cout << endl;
    for (int i = 0; i < nonterminal.size(); i++) {
        cout << nonterminal[i] << ": ";
        for (int j = 0; j < terminalNoEmpty.size(); j++) {
            if (tableMap[i][j] == -1)
                cout << setw(10) << "   ";
            else
                cout << setw(10) << production[tableMap[i][j]].right;
        }
        cout << endl;
    }
    cout << endl;
}

void LL1::getResult() {
    inputAndSolve();
    displayFirstAndFollow();
    getTable();
    printPredictTable();
    //栈匹配
    string ss;
    cout << "请输入符号串:" << endl;
    cin >> ss;
    cout << setw(15) << "分析栈" << setw(15) << "剩余输入串" << setw(15) << "推导式" << endl;
    analyExpression(ss);

}

}

main.cpp

#include "LL1.h"
#include

int main() {
    // $表示空, #表示终止
    LL1 res;
    res.getResult();
    system("pause");
    return 0;
}

测试样例

8
E->TA
A->+TA
A->$
T->FB
B->*FB
B->$
F->(E)
F->i


i+i*i

你可能感兴趣的:(编译原理,语法分析器,c++)