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

    实验目的

    构造LR分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子,了解LR(K)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。

    实验内容

    对下列文法,用SLR(1)分析法对任意输入的符号串进行分析:


    (1)S->E

    (2)E->E+T

    (3)E->T

    (4)T->T*F

    (5)T->F

    (6)F->(E)

    (7)F->i

    设计思想

    (1)总控程序,也可以称为驱动程序。对所有的LR分析器总控程序都是相同的。

    (2)分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。

    (3)分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。

    分析器的动作就是由栈顶状态和当前输入符号所决定。

    u  LR分析器由三个部分组成:

    u  其中:SP为栈指针,S[i]为状态栈,X[i]为文法符号栈。状态转换表用GOTO[i,X]=j表示,规定当栈顶状态为i,遇到当前文法符号为X时应转向状态j,X为终结符或非终结符。

    u  ACTION[i,a]规定了栈顶状态为i时遇到输入符号a应执行。动作有四种可能:

    (1)移进:

        action[i,a]= Sj:状态j移入到状态栈,把a移入到文法符号栈,其中i,j表示状态号。

    (2)归约:

        action[i,a]=rk:当在栈顶形成句柄时,则归约为相应的非终结符A,即文法中有A- B的产生式,若B的长度为R(即|B|=R),则从状态栈和文法符号栈中自顶向下去掉R个符号,即栈指针SP减去R,并把A移入文法符号栈内,j=GOTO[i,A]移进状态栈,其中i为修改指针后的栈顶状态。

    (3)接受acc:

        当归约到文法符号栈中只剩文法的开始符号S时,并且输入符号串已结束即当前输入符是'#',则为分析成功。

    (4)报错:

    当遇到状态栈顶为某一状态下出现不该遇到的文法符号时,则报错,说明输入端不是该文法能接受的符号串。

    【实验要求】

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

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

    3、程序输入/输出实例:

    输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串

    输出过程如下:

    步骤     状态栈     符号栈      剩余输入串            动 作 

     1          0             #          i+i*i#               移进 

    【实验结果】

    代码:

      1 Main.cpp
      2 #include<iostream>
      3 #include<stack>
      4 #include<string>
      5 #include <stdlib.h>
      6 using namespace std;
      7 string action[12][6] = { "S5", "0", "0", "S4", "0", "0",
      8 //ACTION 表
      9 "0", "S6", "0", "0", "0", "acc",
     10 "0", "r2", "S7", "0", "r2", "r2",
     11 "0", "r4", "r4", "0", "r4", "r4",
     12 "S5", "0", "0", "S4", "0", "0",
     13 "0", "r6", "r6", "0", "r6", "r6",
     14 "S5", "0", "0", "S4", "0", "0",
     15 "S5", "0", "0", "S4", "0", "0",
     16 "0", "S6", "0", "0", "S11", "0",
     17 "0", "r1", "S7", "0", "r1", "r1",
     18 "0", "r3", "r3", "0", "r3", "r3",
     19 "0", "r5", "r5", "0", "r5", "r5" };
     20 int gotoarr[12][3] = { 1, 2, 3, //GOTO 表
     21 0, 0, 0,
     22 0, 0, 0,
     23 0, 0, 0,
     24 8, 2, 3,
     25 0, 0, 0,
     26 0, 9, 3,
     27 0, 0, 10,
     28 0, 0, 0,
     29 0, 0, 0,
     30 0, 0, 0,
     31 0, 0, 0 };
     32 char vt[6] = { 'i', '+', '*', '(', ')', '#' }; //存放终结符
     33 char vn[3] = { 'E', 'T', 'F' }; //存放非终结符
     34 string Production[6] = { "E->E+T", "E->T", "T->T*F", "T->F", "F->(E)", "F->i" };//产生式集合
     35 //int com= 0;//记录当前进行处理的输入字符串字符位置
     36 int com = 0;
     37 int line = 1;//记录处理的步骤数
     38 bool flag = false;
     39 int StatusNumber = 1;//栈中状态数
     40 string stacktd = "#";//记录符号栈中内容
     41 int Status[50] = { 0 };//记录状态栈
     42 stack <char> Stack;//创建一个符号栈
     43 stack <int> status;//创建一个状态栈
     44 void Judge(int &i, int j, char arr[], char ch, string s){//判断输入串是否由文法终结符组成
     45     flag = false;
     46     for (int l = 0; l<j; l++){
     47         if (ch == arr[l]){
     48             flag = true;
     49             i = l;
     50             break;
     51         }
     52     }
     53     if (flag == false){
     54         cout << "	Error" << endl;
     55         //com = s.size();
     56         com = s.size();
     57     }
     58 }
     59 void Outputstatus(){//输出状态集
     60     for (int i = 0; i<StatusNumber; i++)
     61         cout << Status[i];
     62 }
     63 void Outputstring(string s){//输出未处理的字符串
     64     for (int i = com; i<s.size(); i++)
     65         cout << s.at(i);
     66 }
     67 void Output(string s){//输出步骤、 状态集、 符号集、 输入串
     68     cout << line << "	";
     69     Outputstatus();
     70     cout << "	" << stacktd << "	";
     71     Outputstring(s);
     72     cout << "		";
     73     line++;
     74 }
     75 void Shift(int i, string s){//移进函数 S
     76     Output(s);
     77     cout << "ACTION[" << status.top() << "," << s.at(com) << "]=S" << i << ",状态" << i << "入栈" << endl;
     78     status.push(i);//将状态 i 压进状态
     79     Status[StatusNumber] = i;//Status 记录状态栈的内容
     80     Stack.push(s.at(com));//将当前面临的输入串符号压进符号栈
     81     stacktd = stacktd + s.at(com);//stacktd 记录符号栈的内容
     82     com++;//当前面临的输入串字符往后移一位
     83     StatusNumber++;//状态数加一
     84 }
     85 void Goto(stack <int> st1, stack <char> st2, string s){//GoTo 语句
     86     int j = -1;
     87     int ch1 = st1.top();
     88     char ch2 = st2.top();
     89     Judge(j, 3, vn, ch2, s);//求得 ch2 在非终结符表中的位置
     90     if (gotoarr[ch1][j] == 0){
     91         cout << "	Error" << endl;
     92         com = s.size();
     93     }
     94     else{
     95         status.push(gotoarr[ch1][j]);//新状态进栈
     96         Status[StatusNumber] = gotoarr[ch1][j];
     97         StatusNumber++;
     98     }
     99 }
    100 void Reduction(int i, string s){//归约函数 R
    101     Output(s);
    102     cout << "r" << i << ":" << Production[i - 1] << "归约, GoTo(";
    103     int N = Production[i - 1].length() - 3;
    104     for (int j = 0; j<N; j++){//消除要归约的状态及符号
    105         status.pop();
    106         Stack.pop();
    107         StatusNumber--;
    108         stacktd.erase(stacktd.length() - 1);
    109     }
    110     cout << status.top() << "," << Production[i - 1].at(0) << ")=";
    111     Stack.push(Production[i - 1].at(0));//符号进栈
    112     stacktd = stacktd + Stack.top();
    113     Goto(status, Stack, s);
    114     cout << status.top() << "入栈" << endl;
    115     Status[StatusNumber] = status.top();
    116 }
    117 void Analyse(string s){//具体分析函数
    118     Stack.push('#');//初始化
    119     status.push(0);
    120     s = s + "#";
    121     int t = -1;//记录 ch 在数组 vt 的位置
    122     while (com<s.size()){
    123         int i = status.top();
    124         char ch = s.at(com);
    125         Judge(t, 6, vt, ch, s);
    126         if (flag == true){
    127             if (action[i][t] != "acc"&&action[i][t] != "0"){
    128                 if (action[i][t].at(0) == 'S'){
    129                     action[i][t].erase(0, 1); //删除 action[i][t]的首字母 S
    130                     Shift(atoi(action[i][t].c_str()), s);//atoi(action[i][t].c_str()), 将action[i][t]转换为整型
    131                     action[i][t].insert(0, "S");//将 S 添加回 action[i][t]
    132                 }
    133                 else if (action[i][t].at(0) == 'r'){
    134                     action[i][t].erase(0, 1);//删除 action[i][t]的首字母 r
    135                     Reduction(atoi(action[i][t].c_str()), s);//atoi(action[i][t].c_str()), 将action[i][t]转换为整型
    136                     action[i][t].insert(0, "r");//将 r 添加回 action[i][t]
    137                 }
    138             }
    139             else if (action[i][t] == "0"){
    140                 cout << "	Error" << endl;
    141                 break;
    142             }
    143             else if (action[i][t] == "acc"){
    144                 Output(s);
    145                 cout << "acc" << "	 分析成功" << endl;
    146                 break;
    147             }
    148         }
    149         else if (flag == false)
    150             break;
    151     }
    152 }
    153 int main(){
    154     string s;
    155     cout << "************************20173599周博*************************" << endl;
    156     cout << "输入的文法" << endl;
    157     for (int j = 0; j < 6; j++)
    158     {
    159         cout << Production[j] << endl;
    160     }
    161     cout << "VT:" << endl;
    162     for (int i = 0; i < 6; i++)
    163     {
    164         cout << vt[i] << "	";
    165     }
    166     cout << endl;
    167     for (int i = 0; i <3; i++)
    168     {
    169         cout << vn[i] << "	";
    170     }
    171     cout << endl;
    172     cout << "************************LR(1)分析*************************" << endl;
    173     char T;
    174         cout << "输入字符串" << endl;
    175         cin >> s;//输入要分析的字符串
    176         cout << "************************现进行如下分析*************************" << endl;
    177         cout << "步骤" << "	" << "状态栈" << "	" << "符号栈" << "	" << "剩余输入串" << "	" << "动作说明" << endl;
    178         Analyse(s);
    179         com = 0;//记录当前进行处理的输入字符串字符位置
    180         line = 1;//记录处理的步骤数
    181         stacktd = "#";
    182         StatusNumber = 1;
    183         while (!Stack.empty()){
    184             Stack.pop();
    185         }
    186         while (!status.empty()){
    187             status.pop();
    188         }
    189     
    190     return 0;
    191 }

  • 相关阅读:
    Java 8 Lambda 表达式
    OSGi 系列(十二)之 Http Service
    OSGi 系列(十三)之 Configuration Admin Service
    OSGi 系列(十四)之 Event Admin Service
    OSGi 系列(十六)之 JDBC Service
    OSGi 系列(十)之 Blueprint
    OSGi 系列(七)之服务的监听、跟踪、声明等
    OSGi 系列(六)之服务的使用
    OSGi 系列(三)之 bundle 事件监听
    OSGi 系列(三)之 bundle 详解
  • 原文地址:https://www.cnblogs.com/smartisn/p/12207421.html
Copyright © 2011-2022 走看看