zoukankan      html  css  js  c++  java
  • 软件构造——LL(1)语法分析

    实验目的

    通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。使了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练掌握开发应用程序的基本方法。

    实验内容

    u  根据某一文法编制调试 LL ( 1 )分析程序,以便对任意输入的符号串进行分析。

    u  构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。

    u  分析法的功能是利用LL(1)控制程序根据显示栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。

    设计思想

    (1)定义部分:定义常量、变量、数据结构。

    (2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);

    (3)控制部分:从键盘输入一个表达式符号串;

    (4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。

     

    【实验要求】

    (1)编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。

    (2)如果遇到错误的表达式,应输出错误提示信息。

    (3)画出流程图

     

    实验截图:

     

     

    代码:

      1 Base.sh
      2 #ifndef _BASE_H_
      3 #define _BASE_H_
      4 #include <iostream>
      5 #include <iomanip>
      6 #include <string>
      7 #include <vector>
      8 #include <set>
      9 
     10 #define maxsize 100
     11 
     12 using namespace std;
     13 
     14 struct node {  // 产生式的数据结构
     15     char left;
     16     string right;
     17 };
     18 
     19 class Base {
     20 protected:
     21     int T;
     22     node production[maxsize]; // 产生式集
     23 
     24     set<char> firstSet[maxsize];  // First集
     25     set<char> followSet[maxsize];  // Follow集
     26     vector<char> terminalNoEmpty; // 去$(空)的终结符
     27     vector<char> terminal;  // 终结符
     28     vector<char> nonterminal;  // 非终结符
     29 
     30     bool isNonterminal(char c);
     31     int getIndex(char target);  // 获得target在终结符集合中的下标
     32     int getNIndex(char target);  // 获得target在非终结符集合中的下标
     33     void getFirst(char target);  // 得到First(target)
     34     void getFollow(char target);  // 得到Follow(target)
     35 
     36 public:
     37     Base() {};
     38 
     39     void inputAndSolve();  // 处理和求出First和Follow集
     40     void displayFirstAndFollow();  // 输出First和Follow集
     41 
     42 };
     43 #endif 
     44 
     45 Base.cpp
     46 #include "Base.h"
     47 
     48 bool Base::isNonterminal(char c) { // 判断c是否为非终结符
     49     if (c >= 'A' && c <= 'Z')
     50         return true;
     51     return false;
     52 }
     53 int Base::getNIndex(char target) {  // 获得target在非终结符集合中的下标
     54     for (int i = 0; i<nonterminal.size(); i++) {
     55         if (target == nonterminal[i])
     56             return i;
     57     }
     58     return -1;
     59 }
     60 int Base::getIndex(char target) {  // 获得target在终结符集合中的下标
     61     for (int i = 0; i<terminalNoEmpty.size(); i++) {
     62         if (target == terminalNoEmpty[i])
     63             return i;
     64     }
     65     return -1;
     66 }
     67 
     68 void Base::getFirst(char target) {  // 求FIRST(target)
     69     int countEmpty = 0;  // 用于最后判断是否有空
     70     int isEmpty = 0;
     71     int targetIndex = getNIndex(target);
     72     for (int i = 0; i < T; i++) {
     73         if (production[i].left == target) {  // 匹配产生式左部
     74             if (!isNonterminal(production[i].right[0])) {  // 对于终结符,直接加入first
     75                 firstSet[targetIndex].insert(production[i].right[0]);
     76             }
     77             else {
     78                 for (int j = 0; j < production[i].right.length(); j++) { // X->Y1..Yj..Yk是一个产生式
     79                     char Yj = production[i].right[j];
     80                     if (!isNonterminal(Yj)) {  // Yj是终结符(不能产生空),FIRST(Yj)=Yj加入FIRST(X),不能继续迭代,结束
     81                         firstSet[targetIndex].insert(Yj);
     82                         break;
     83                     }
     84                     getFirst(Yj);// Yj是非终结符,递归 先求出FIRST(Yj)
     85 
     86                     set<char>::iterator it;
     87                     int YjIndex = getNIndex(Yj);
     88                     for (it = firstSet[YjIndex].begin(); it != firstSet[YjIndex].end(); it++) {
     89                         if (*it == '$')  // 遍历查看FIRST(Yj)中是否含有'$'(能产生空)
     90                             isEmpty = 1;
     91                         else
     92                             firstSet[targetIndex].insert(*it);//将FIRST(Yj)中的非$就加入FIRST(X)
     93                     }
     94                     if (isEmpty == 0)  // Yj不能产生空, 迭代结束
     95                         break;
     96                     else {   //  Yj能产生空
     97                         countEmpty += isEmpty;
     98                         isEmpty = 0;
     99                     }
    100                 }
    101                 if (countEmpty == production[i].right.length())//所有右部first(Y)都有$(空),将$加入FIRST(X)中
    102                     firstSet[getNIndex(target)].insert('$');
    103             }
    104         }
    105     }
    106 }
    107 
    108 void Base::getFollow(char target) {  // 求FOLLOW(target)
    109     int targetIndex = getNIndex(target);
    110     for (int i = 0; i<T; i++) {
    111         int index = -1;
    112         int len = production[i].right.length();
    113         for (int j = 0; j < len; j++) {  // 寻找target在产生式中的位置index
    114             if (production[i].right[j] == target) {
    115                 index = j;
    116                 break;
    117             }
    118         }
    119         if (index != -1 && index < len - 1) {  // 找到target在产生式中的位置index
    120             // 存在A->αBβ, 将FIRST(β)中除了空$之外的所有放入FOLLOW(B)中
    121             // 这里B对应target, β对应nxt
    122             char nxt = production[i].right[index + 1];
    123             if (!isNonterminal(nxt)) {  // β是终结符 FIRST(β)=β,直接插入β
    124                 followSet[targetIndex].insert(nxt);
    125             }
    126             else {  // β是非终结符
    127                 int hasEmpty = 0;
    128                 set<char>::iterator it;
    129                 int nxtIndex = getNIndex(nxt);  // 插入FIRST(β)中除了空$之外的所有
    130                 for (it = firstSet[nxtIndex].begin(); it != firstSet[nxtIndex].end(); it++) {
    131                     if (*it == '$')
    132                         hasEmpty = 1;
    133                     else
    134                         followSet[targetIndex].insert(*it);
    135                 }
    136 
    137                 if (hasEmpty && production[i].left != target) { // 存在A->αBβ且FIRST(β)->$
    138                     // FOLLOW(A)放在FOLLOW(B)中
    139                     getFollow(production[i].left);
    140                     set<char>::iterator it;
    141                     char tmp = production[i].left;
    142                     int tmpIndex = getNIndex(tmp);
    143                     for (it = followSet[tmpIndex].begin(); it != followSet[tmpIndex].end(); it++)
    144                         followSet[targetIndex].insert(*it);
    145                 }
    146             }
    147         }
    148         else if (index != -1 && index == len - 1 && target != production[i].left) {  // 存在A->αB ,FOLLOW(A)放在FOLLOW(B)中
    149             getFollow(production[i].left);
    150             set<char>::iterator it;
    151             char tmp = production[i].left;
    152             int tmpIndex = getNIndex(tmp);
    153             for (it = followSet[tmpIndex].begin(); it != followSet[tmpIndex].end(); it++)
    154                 followSet[targetIndex].insert(*it);
    155         }
    156     }
    157 }
    158 
    159 void Base::inputAndSolve() {  // 处理和求出First和Follow集
    160     string s;
    161     cout << "输入的产生式的个数:" << endl;
    162     cin >> T;
    163     cout << "输入的产生式:" << endl;
    164     for (int index = 0; index < T; index++) {  // 处理每一个产生式
    165         cin >> s;
    166         string temp = "";  // 存储去掉空格的产生式
    167         for (int i = 0; i < s.length(); i++) {  // 去掉产生式中的' '
    168             if (s[i] != ' ')
    169                 temp += s[i];
    170         }
    171         production[index].left = temp[0];  // 产生式的左部
    172         for (int i = 3; i<temp.length(); i++) // 产生式的右部
    173             production[index].right += temp[i];
    174 
    175         for (int i = 0; i < temp.length(); i++) {  // 存储所有终结符和非终结符
    176             if (i == 1 || i == 2) continue;  // 跳过产生符号->
    177             if (isNonterminal(temp[i])) {  //插入一个非终结符
    178                 int flag = 0;
    179                 for (int j = 0; j < nonterminal.size(); j++) {
    180                     if (nonterminal[j] == temp[i]) {
    181                         flag = 1;
    182                         break;
    183                     }
    184                 }
    185                 if (!flag) nonterminal.push_back(temp[i]);
    186             }
    187             else {                       //插入一个终结符
    188                 int flag = 0;
    189                 for (int j = 0; j < terminal.size(); j++) {
    190                     if (terminal[j] == temp[i]) {
    191                         flag = 1;
    192                         break;
    193                     }
    194                 }
    195                 if (!flag) terminal.push_back(temp[i]);
    196             }
    197         }
    198     }
    199     terminal.push_back('#');
    200 
    201     for (int i = 0; i < terminal.size(); i++) { // 存储没有$符号的终结符
    202         if (terminal[i] != '$')
    203             terminalNoEmpty.push_back(terminal[i]);
    204     }
    205 
    206     // 获得first集
    207     for (int i = 0; i < nonterminal.size(); i++) {
    208         getFirst(nonterminal[i]);
    209     }
    210 
    211     // 获得follow集
    212     for (int i = 0; i < nonterminal.size(); i++) {
    213         if (i == 0)  // 开始符号, 先加入结束符号
    214             followSet[0].insert('#');
    215         getFollow(nonterminal[i]);
    216     }
    217 }
    218 
    219 void Base::displayFirstAndFollow() {  // 输出First和Follow集
    220     for (int aa = 0; aa < 10; aa++)
    221     {
    222         cout << "*********";
    223     }
    224     cout << "
    欢迎使用周博 20173599 LL1语法分析器(以下是First集合和Follow集合)" << endl;
    225     cout << "FIRST集合" << endl;
    226     for (int i = 0; i<nonterminal.size(); i++) {
    227         cout << nonterminal[i] << ": ";
    228         set<char>::iterator it;
    229         for (it = firstSet[i].begin(); it != firstSet[i].end(); it++)
    230             cout << *it << "  ";
    231         cout << endl;
    232     }
    233     cout << endl;
    234 
    235     cout << "FOLLOW集合" << endl;
    236     for (int i = 0; i<nonterminal.size(); i++) {
    237         cout << nonterminal[i] << ": ";
    238         set<char>::iterator it;
    239         for (it = followSet[i].begin(); it != followSet[i].end(); it++)
    240             cout << *it << "  ";
    241         cout << endl;
    242     }
    243     cout << endl;
    244 }
    245 LL1.h
    246 
    247 #include"Base.h"
    248 
    249 #define maxsize 100
    250 #ifndef _LL1_H_
    251 #define _LL1_H_
    252 using namespace std;
    253 
    254 class LL1 : public Base {
    255 private:
    256     vector<char> analyStack; // 分析栈
    257     vector<char> leftExpr;  // 剩余输入串
    258     int tableMap[100][100];  // 预测表
    259 
    260 public:
    261     LL1();
    262 
    263     void getTable(); // 生成预测表
    264     void analyExpression(string s);  // 分析输入语句s
    265     void printPredictTable();  // 输出预测表
    266     void getResult(); // 综合处理
    267 };
    268 #endif
    269 LL1.cpp
    270 #include"LL1.h"
    271 
    272 LL1::LL1() {
    273     memset(tableMap, -1, sizeof(tableMap));
    274 }
    275 
    276 void LL1::getTable() {
    277     for (int index = 0; index < T; index++) {                          // 对于每个产生式(编号index):A->α
    278         int row = getNIndex(production[index].left);
    279         int emptyCount = 0;
    280         for (int i = 0; i < production[index].right.size(); i++) { // 1) 对FIRST(α)中的每个终结符号a,将index加入(A, a)中
    281             char tmp = production[index].right[i];
    282             if (!isNonterminal(tmp)) { // tmp是终结符          
    283                 if (tmp != '$')
    284                     tableMap[row][getIndex(tmp)] = index;
    285                 if (tmp == '$') {
    286                     emptyCount++;
    287                 }
    288                 break;
    289             }
    290             else {  // tmp是非终结符
    291                 set<char>::iterator it;
    292                 int tmpIndex = getNIndex(tmp);
    293                 // 对FIRST(tmp)中的每个终结符号a,将i加入(A, a)中
    294                 for (it = firstSet[tmpIndex].begin(); it != firstSet[tmpIndex].end(); it++) {
    295                     tableMap[row][getIndex(*it)] = index;
    296                 }
    297                 if (firstSet[tmpIndex].count('$') != 0) {      // 2) 如果空$在FIRST(tmp)中,继续看α中的下一个符号
    298                     emptyCount++;
    299                 }
    300                 else {
    301                     break;
    302                 }
    303             }
    304         }
    305 
    306         // 2) 如果空$在FIRST(α)中,对FOLLOW(A)中的每个终结符或结束符b,将i加入(A,b)中
    307         if (emptyCount == production[index].right.size()) {
    308             set<char>::iterator  it;
    309             for (it = followSet[row].begin(); it != followSet[row].end(); it++) {
    310                 tableMap[row][getIndex(*it)] = index;
    311             }
    312         }
    313     }
    314 }
    315 
    316 void LL1::analyExpression(string s) {
    317 
    318     for (int i = 0; i < s.size(); i++)
    319         leftExpr.push_back(s[i]);
    320     leftExpr.push_back('#');
    321 
    322     analyStack.push_back('#');
    323     analyStack.push_back(nonterminal[0]);  // 加入开始符号
    324 
    325     while (analyStack.size() > 0) {
    326         //cout<<"分析栈:";
    327         string outs = "";
    328         for (int i = 0; i < analyStack.size(); i++)
    329             outs += analyStack[i];
    330         cout << setw(15) << outs;
    331 
    332         //cout<<"剩余输入串:";
    333         outs = "";
    334         for (int i = 0; i < leftExpr.size(); i++)
    335             outs += leftExpr[i];
    336         cout << setw(15) << outs;
    337 
    338         // 匹配
    339         char char1 = analyStack.back();
    340         char char2 = leftExpr.front();
    341         if (char1 == char2 && char1 == '#') {
    342             cout << setw(15) << "Accepted!" << endl;
    343             return;
    344         }
    345         if (char1 == char2) {
    346             analyStack.pop_back();
    347             leftExpr.erase(leftExpr.begin());
    348             cout << setw(15) << "匹配:" << char1 << endl;
    349         }
    350         else if (tableMap[getNIndex(char1)][getIndex(char2)] != -1) {  // 预测表中有推倒项,可进行推导
    351             int tg = tableMap[getNIndex(char1)][getIndex(char2)];
    352             analyStack.pop_back();
    353 
    354             if (production[tg].right != "$") {
    355                 for (int i = production[tg].right.length() - 1; i >= 0; i--) // 注意这里是反向的
    356                     analyStack.push_back(production[tg].right[i]);
    357             }
    358 
    359             cout << setw(15) << "推导:" << production[tg].left << "->" << production[tg].right << endl;
    360         }
    361         else {  // 错误
    362             cout << setw(15) << "error!" << endl;
    363             return;
    364         }
    365     }
    366 }
    367 
    368 void LL1::printPredictTable() {
    369     // 表头
    370     for (int aa = 0; aa < 10; aa++)
    371     {
    372         cout << "*********";
    373     }
    374     cout << "
    以下是预测分析表" << endl;
    375     for (int i = 0; i < terminalNoEmpty.size(); i++) {
    376         cout << setw(10) << terminalNoEmpty[i];
    377     }
    378     cout << endl;
    379     for (int i = 0; i < nonterminal.size(); i++) {
    380         cout << nonterminal[i] << ": ";
    381         for (int j = 0; j < terminalNoEmpty.size(); j++) {
    382             if (tableMap[i][j] == -1)
    383                 cout << setw(10) << "   ";
    384             else
    385                 cout << setw(10) << production[tableMap[i][j]].right;
    386         }
    387         cout << endl;
    388     }
    389     cout << endl;
    390 }
    391 
    392 void LL1::getResult() {
    393     inputAndSolve();
    394     displayFirstAndFollow();
    395     getTable();
    396     printPredictTable();
    397     //栈匹配
    398     string ss;
    399     cout << "请输入符号串:" << endl;
    400     cin >> ss;
    401     for (int aa = 0; aa < 10; aa++)
    402     {
    403         cout << "*********";
    404     }
    405     cout << "
    句子" << ss << "分析过程" << endl;
    406     cout << setw(15) << "分析栈" << setw(15) << "剩余输入串" << setw(15) << "推导式" << endl;
    407     analyExpression(ss);
    408 
    409 }
    410 
    411 
    412 Main.cpp
    413 #include "LL1.h"
    414 #include<stdlib.h>
    415 
    416 int main() {
    417     // $表示空, #表示终止
    418     LL1 res;
    419     res.getResult();
    420     system("pause");
    421     return 0;
    422 }
  • 相关阅读:
    python反爬之js混淆-字符串映射
    How to Provide a Default Trace for a Cloud Application
    Reset Peak Used Memory
    SAP 课程
    note 1639578 and 1622837
    SAP License error
    SAP BASIS-System Move
    初识Agile(敏捷项目管理)
    SAP HANA升级
    SAP FIORI 部署
  • 原文地址:https://www.cnblogs.com/smartisn/p/12207404.html
Copyright © 2011-2022 走看看