Sicily1001. 自上而下语法分析(二)

Sicily1001. 输入输出LL(1)语法分析程序 **

题目

输入开始符号,非终结符,终结符,产生式,LL(1)分析表
输出LL(1)分析表

Input
输入开始符号;
非终结符个数,非终结符,空格符分隔;
终结符个数,终结符,空格符分隔;
产生式的个数,各产生式的序号,产生式的左边和右边符号,空格符分隔;
LL(1)分析表中的产生式个数,序号,行符号,列符号,产生式编号,空格符分隔;
输入一个算术式符号串,用#结束

Output
输出推导过程,每一步一行,中间“ & ”前是已经识别的子串,后是栈中信息。

样例输入
E
6 E A T B F D
9 + - * / ( ) x y z
13
1 E TA
2 A +TA
3 A -TA
4 A k
5 T FB
6 B *FB
7 B /FB
8 B k
9 F (E)
10 F D
11 D x
12 D y
13 D z
25
1 E ( 1
2 E x 1
3 E y 1
4 E z 1
5 A + 2
6 A - 3
7 A ) 4
8 A # 4
9 T ( 5
10 T x 5
11 T y 5
12 T z 5
13 B + 8
14 B - 8
15 B * 6
16 B / 7
17 B ) 8
18 B # 8
19 F ( 9
20 F x 10
21 F y 10
22 F z 10
23 D x 11
24 D y 12
25 D z 13
(x+(y-x*z)*(y+x*z))+x/z#

样例输出
. # & E#
. # & TA#
. # & FBA#
. # & (E)BA#
. #( & E)BA#
. #( & TA)BA#
. #( & FBA)BA#
. #( & DBA)BA#
. #( & xBA)BA#
. #(x & BA)BA#
. #(x & A)BA#
. #(x & +TA)BA#
. #(x+ & TA)BA#
. #(x+ & FBA)BA#
. #(x+ & (E)BA)BA#
. #(x+( & E)BA)BA#
. #(x+( & TA)BA)BA#
. #(x+( & FBA)BA)BA#
. #(x+( & DBA)BA)BA#
. #(x+( & yBA)BA)BA#
. #(x+(y & BA)BA)BA#
. #(x+(y & A)BA)BA#
. #(x+(y & -TA)BA)BA#
. #(x+(y- & TA)BA)BA#
. #(x+(y- & FBA)BA)BA#
. #(x+(y- & DBA)BA)BA#
. #(x+(y- & xBA)BA)BA#
. #(x+(y-x & BA)BA)BA#
. #(x+(y-x & *FBA)BA)BA#
. #(x+(y-x* & FBA)BA)BA#
. #(x+(y-x* & DBA)BA)BA#
. #(x+(y-x* & zBA)BA)BA#
. #(x+(y-x*z & BA)BA)BA#
. #(x+(y-x*z & A)BA)BA#
. #(x+(y-x*z & )BA)BA#
. #(x+(y-x*z) & BA)BA#
. #(x+(y-x*z) & *FBA)BA#
. #(x+(y-x*z)* & FBA)BA#
. #(x+(y-x*z)* & (E)BA)BA#
. #(x+(y-x*z)*( & E)BA)BA#
. #(x+(y-x*z)*( & TA)BA)BA#
. #(x+(y-x*z)*( & FBA)BA)BA#
. #(x+(y-x*z)*( & DBA)BA)BA#
. #(x+(y-x*z)*( & yBA)BA)BA#
. #(x+(y-x*z)*(y & BA)BA)BA#
. #(x+(y-x*z)*(y & A)BA)BA#
. #(x+(y-x*z)*(y & +TA)BA)BA#
. #(x+(y-x*z)*(y+ & TA)BA)BA#
. #(x+(y-x*z)*(y+ & FBA)BA)BA#
. #(x+(y-x*z)*(y+ & DBA)BA)BA#
. #(x+(y-x*z)*(y+ & xBA)BA)BA#
. #(x+(y-x*z)*(y+x & BA)BA)BA#
. #(x+(y-x*z)*(y+x & *FBA)BA)BA#
. #(x+(y-x*z)(y+x & FBA)BA)BA#
. #(x+(y-x*z)(y+x & DBA)BA)BA#
. #(x+(y-x*z)(y+x & zBA)BA)BA#
. #(x+(y-x*z)*(y+x*z & BA)BA)BA#
. #(x+(y-x*z)*(y+x*z & A)BA)BA#
. #(x+(y-x*z)*(y+x*z & )BA)BA#
. #(x+(y-x*z)*(y+x*z) & BA)BA#
. #(x+(y-x*z)*(y+x*z) & A)BA#
. #(x+(y-x*z)*(y+x*z) & )BA#
. #(x+(y-x*z)*(y+x*z)) & BA#
. #(x+(y-x*z)*(y+x*z)) & A#
. #(x+(y-x*z)*(y+x*z)) & +TA#
. #(x+(y-x*z)*(y+x*z))+ & TA#
. #(x+(y-x*z)*(y+x*z))+ & FBA#
. #(x+(y-x*z)*(y+x*z))+ & DBA#
. #(x+(y-x*z)*(y+x*z))+ & xBA#
. #(x+(y-x*z)*(y+x*z))+x & BA#
. #(x+(y-x*z)*(y+x*z))+x & /FBA#
. #(x+(y-x*z)*(y+x*z))+x/ & FBA#
. #(x+(y-x*z)*(y+x*z))+x/ & DBA#
. #(x+(y-x*z)*(y+x*z))+x/ & zBA#
. #(x+(y-x*z)*(y+x*z))+x/z & BA#
. #(x+(y-x*z)*(y+x*z))+x/z & A#
. #(x+(y-x*z)*(y+x*z))+x/z & #

解题分析

这道题目与上一题类似,因此存储方式是一样的,仍旧是结构体,在此不再赘述。另外根据题目的提示,我们用栈来存储推导过程中的相关信息。现在问题的关键是如何根据LL(1)分析表来进行语法推导。同样,我们先结合样例来进行分析。
根据样例,我们知道,刚开始是先将开始符号压入栈中。然后我们再来看看接下来的情况。根据语法推导的过程我们每次判断栈顶元素是否与输入串的首个字符相同。很明显此时栈顶元素为E,输入串首个字符为(,二者并不相同。所以将以E为开头的产生式压入栈中,此时栈中的元素为TA,其中T为栈顶。依此类推,可以得到栈中的元素为(E)BA。此时,栈顶元素为(,与输入串首个字符相同,此时进行归约,将其移出栈,继续进行移入归约的处理。最后当栈为空的时候,程序就结束了。
因此,根据上面的过程,我们不难写出以下程序。先往栈中移入开始符号,并输入此时栈中的情况。然后开始进行移入归约的判断,注意每次进行移入归约处理之后都要将栈中信息和已识别子串进行输出 。最后当栈为空的时候程序结束。

源代码

#include
#include
#include
using namespace std;

struct non_terminal
{
    int count;
    string sign[100];
    string LL[100][100];
};

struct terminal
{
    int count;
    string sign[100];
};

struct produce
{
    int count;
    int number[100];
    string left[100];
    string right[100];
};

struct LL1_produce
{
    int count;
    int number[100];
    string row[100];
    string col[100];
    int order[100];
};

int main() {
    non_terminal non_terminal;
    terminal terminal;
    produce produce;
    LL1_produce LL1_produce;

    string start, test;
    cin >> start;
    cin >> non_terminal.count;
    for (int i = 0; i < non_terminal.count; i++) {
        cin >> non_terminal.sign[i];
    }
    cin >> terminal.count;
    for (int i = 0; i < terminal.count; i++) {
        cin >> terminal.sign[i];
    }
    cin >> produce.count;
    for (int i = 0; i < produce.count; i++) {
        cin >> produce.number[i] >> produce.left[i] >> produce.right[i];
    }
    cin >> LL1_produce.count;
    for (int i = 0; i < LL1_produce.count; i++) {
        cin >> LL1_produce.number[i] >> LL1_produce.row[i] >> LL1_produce.col[i] >> LL1_produce.order[i];
    }
    cin >> test;

    string left = "", temp = "";
    stack<string> right;
    right.push(start);

    cout << "#" << left << " & ";
    while (!right.empty()) {
        cout << right.top();
        temp += right.top();
        right.pop();
    }
    cout << "#" << endl;
    while (temp.size() != 0) {
        string temp_top = temp.substr(temp.size() - 1, 1);
        right.push(temp_top);
        temp = temp.substr(0, temp.size() - 1);
    }

    while (!right.empty()) {
        string top = right.top();
        string first = test.substr(0, 1);
        if (top == first) {
            left += top;
            test = test.substr(1, test.size() - 1);
            right.pop();

            temp = "";
            cout << "#" << left << " & ";
            while (!right.empty()) {
                cout << right.top();
                temp += right.top();
                right.pop();
            }
            cout << "#" << endl;
            while (temp.size() != 0) {
                string temp_top = temp.substr(temp.size() - 1, 1);
                right.push(temp_top);
                temp = temp.substr(0, temp.size() - 1);
            }
        }
        else {
            for (int i = 0; i < LL1_produce.count; i++) {
                if (LL1_produce.row[i] == top && LL1_produce.col[i] == first) {
                    right.pop();
                    string expression = produce.right[LL1_produce.order[i] - 1];
                    if (expression == "k") {
                        continue;
                    }
                    while (expression.size() != 0) {
                        string temp_top = expression.substr(expression.size() - 1, 1);
                        right.push(temp_top);
                        expression = expression.substr(0, expression.size() - 1);
                    }
                    break;
                }
            }

            temp = "";
            cout << "#" << left << " & ";
            while (!right.empty()) {
                cout << right.top();
                temp += right.top();
                right.pop();
            }
            cout << "#" << endl;
            while (temp.size() != 0) {
                string temp_top = temp.substr(temp.size() - 1, 1);
                right.push(temp_top);
                temp = temp.substr(0, temp.size() - 1);
            }
        }
    }
    return 0;
} 

以上是我对这道问题的一些想法,有问题还请在评论区讨论留言~

你可能感兴趣的:(编译原理,sicily)