编译原理实验(二)——LL(1)文法语法分析

编译原理实验(二)——LL(1)文法语法分析

实验要求

根据LL(1)分析法编写一个语法分析程序 直接输入根据已知文法构造的分析表M;对于输入的文法和符号串,所编制的语法分析程序应能正确判断此串是否为文法的句子,并要求输出分析过程。

参考程序

#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <iomanip>
using namespace std;

const int maxSize = 10; //定义分析表的最大大小
const string errorstr = "你输入的语言该文法无法识别";
const int outWidth = 30; //设置输出字符串所占宽度

string LL1ForecastAnalysisTable[maxSize][maxSize]; //分析表的具体的内容
int terminatorNum;                                 //输入终结符的数量
int nonterminatorNum;                              //输入非终结符的数量
map<char, int> terminatorSet;                      //输入终结符的集合,用map 映射表示在分析表的第几列
map<char, int> nonterminatorSet;                   //输入非终结符的集合,用map 映射表示在分析表的第几行
vector<char> analysisStack;                        //为了更好的输出栈中的内容,用vector数组模拟栈行为

void analysisProcess(string); //对输入的语言用LL1预测分析表进行分析
char S;

int main()
{
    cout << "请输入终结符的个数:";
    cin >> terminatorNum;
    char str;
    cout << "请依次按照分析表输入终结符(包含结束符#):" << endl;
    for (int i = 1; i <= terminatorNum; ++i)
    {
        cin >> str;
        terminatorSet[str] = i;
    }
    cout << "请输入非终结符的个数:";
    cin >> nonterminatorNum;
    cout << "请依次按照分析表输入终结符:" << endl;
    for (int i = 1; i <= nonterminatorNum; ++i)
    {
        cin >> str;
        nonterminatorSet[str] = i;
    }
    cout << "请输入开始符合:";
    cin >> S;
    cout << "请依次输入分析表的内容,对于出错错误的请输入单个英文字符_:\n";
    for (int i = 1; i <= nonterminatorNum; ++i)
    {
        for (int j = 1; j <= terminatorNum; ++j)
        {
            cin >> LL1ForecastAnalysisTable[i][j];
        }
    }
    cout << "请输入要分析语言: ";
    string L;
    cin >> L;
    analysisProcess(L);
}

void analysisProcess(string str)
{
    cout << " 步骤	 分析栈	    剩余输入串	      所用产生式" << endl;
    int i = 0, ip = 0;     //i代表进行到第几步 a是分析到输入语言字符串第几个
    char X, a = str[ip];   //分析栈栈顶符号
    str += "#";            //在语言末尾加入输入结束符
    analysisStack.clear(); //使分析栈为空
    analysisStack.push_back('#');
    analysisStack.push_back(S); //初始化将’#’压入堆栈中,将开始符号S压入栈中
    string outStack, outStr;
    while (++i)
    {
        X = analysisStack.back();
        analysisStack.pop_back();
        if (X == '#')
        {
            if (X == a)
            {
                cout << setw(10) << setiosflags(ios::left) << i << setw(outWidth);
                cout << setiosflags(ios::left) << "#" << setw(outWidth) << setiosflags(ios::left) << "#"
                     << "接受\n";
            }
            else
            {
                cout << errorstr << endl;
            }
            return;
        }
        else if (terminatorSet[X])
        {
            if (X == a)
            {
                outStack = "";
                for (int i = 0; i < analysisStack.size(); ++i)
                    outStack += analysisStack[i];
                outStack += X;
                cout << setw(10) << setiosflags(ios::left) << i << setw(outWidth) << setiosflags(ios::left) << outStack;
                outStr = "";
                for (int t = ip; t < str.size(); ++t)
                    outStr += str[t];
                cout << setw(outWidth) << setiosflags(ios::left) << outStr << a << "匹配\n";
                a = str[++ip];
            }
            else
            {
                cout << errorstr << endl;
                return;
            }
        }
        else
        {
            int row = nonterminatorSet[X], col = terminatorSet[a];
            string f = LL1ForecastAnalysisTable[row][col]; //获取文法产生式
            if (f == "_")
            {
                cout << errorstr << endl;
                return;
            }
            outStack = "";
            for (int i = 0; i < analysisStack.size(); ++i)
                outStack += analysisStack[i];
            outStack += X;
            cout << setw(10) << setiosflags(ios::left) << i << setw(outWidth) << setiosflags(ios::left) << outStack;
            outStr = "";
            for (int t = ip; t < str.size(); ++t)
                outStr += str[t];
            cout << setw(outWidth) << setiosflags(ios::left) << outStr << X << "->" << f << endl;
            if (f != "@")
                for (int j = f.size() - 1; j >= 0; --j)
                    analysisStack.push_back(f[j]);
        }
    }
}
程序输入说明

输入的终结符与终结符都为单个字符
空( ε \varepsilon ε)用@表示

实验结果

对于文法
E->TA
A->+TA|@
T->FB
B->*FB|@
F->(E)|i
分析表为
在这里插入图片描述
输入数据为

6 
i + * (  ) #
5
E A T B F
E

TA _ _ TA _ _ 
_ +TA _ _ @ @
FB _ _ FB _ _
_ @ *FB _ @ @
i _ _ (E) _ _

i+i*i
截图

在这里插入图片描述

  • 17
    点赞
  • 161
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值