计算机科学与技术系
实 验 报 告
专业名称      计算机科学与技术 
课程名称      编译原理         
项目名称      LR(1)分析法     
      班    级           
学    号           
姓    名               
      同组人员      无               
实验日期      2016.11.4       
一、实验目的与要求:
(简述实验要求达到的目的,涉及到的相关知识点,实验的具体要求。)
目的:掌握LR(1)分析法的基本原理
      掌握LR(1)分析表的构造方法
      掌握LR(1)驱动程序的构造方法
要求:
1. 对LR(1)语法规则有明确的定义; 
2. 编写的分析程序能够对实验结果进行正确的语法分析; 
3. 对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成。
二、实验内容
(根据实验项目的具体任务和要求,完成相关内容,可包括:实验目的、算法原理、实验仪器、设备选型及连线图、算法描述或流程图、源代码、实验运行步骤、关键技术分析、测试数据与实验结果、其他)
具体任务:构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子,了解LRK)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。
对下列文法,用LR(1)分析法对任意输入的符号串进行分析:
(1)E-E+T
(2)E-E—T
(3)T-T*F
(4)T-T/F
(5)F-(E)
(6)F-i
输出的格式如下:
(1)LR(1)分析程序,编制人:姓名,学号,班级
(2)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串
(3)输出过程如下:
 
步骤
状态栈 
符号栈 
剩余输入串
动作
1
0
#
i+i*i#
移进
 
(4)输入符号串为非法符号串(或者为合法符号串)
 
备注:(1)在“所用产生式”一列中如果对应有推导则写出所用产生式;如果为匹配终结符则写
明匹配的终结符;如分析异常出错则写为“分析出错”;若成功结束则写为“分析成功”。
(2) 在此位置输入符号串为用户自行输入的符号串。
l1正则化的作用
原理:LR分析方法是已知的最一般的无回溯移进-归约方法,它能够和其他移进-归约方法一样有效地实现。同时利用数据结构中堆栈的性质,来分析一个具体的句型。
步骤:分析一个LR(1)文法的产生式。
正确无误的构造一个LR(1)的项目集。
根据LR(1)的项目集构建LR(1)分析表。
针对具体句型进行实例分析。
关键技术分析:LR(1)文法中只有三个动作:移进,规约和接受,这三个动作也是通过查表得来的额,任何时候如果都是唯一确定这三个动作中的一个,我们就可以让LR(1)文法正确的运行。首先需要构建项目集,才能根据项目集的状态转换构建分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为
动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。而分析器的动作就是由栈顶状态和当前输入符号所决定。
流程图:
代码:
#include<iostream>
#include<stack>
#include<string>
using namespace std; 
string action[12][6]={
    "S5","0","0","S4","0","0",            //ACTION表                       
        "0","S6","0","0","0","acc",       
        "0","r2","S7","0","r2","r2",     
        "0","r4","r4","0","r4","r4",       
        "S5","0","0","S4","0","0",       
        "0","r6","r6","0","r6","r6",       
        "S5","0","0","S4","0","0",       
        "S5","0","0","S4","0","0",       
        "0","S6","0","0","S11","0",       
        "0","r1","S7","0","r1","r1",                     
        "0","r3","r3","0","r3","r3",             
        "0","r5","r5","0","r5","r5"}; 
    int gotoarr[12][3]={1,2,3,                        //GOTO表                 
        0,0,0,     
        0,0,0,     
        0,0,0,     
        8,2,3,     
        0,0,0,     
        0,9,3,     
        0,0,10,     
        0,0,0,     
        0,0,0,     
        0,0,0,         
        0,0,0}; 
    char vt[6]={'i','+','*','(',')','#'};    //存放终结符                 
    char vn[3]={'E','T','F'};                //存放非终结符     
    string  Production[6]={"E->E+T","E->T","T->T*F","T->F","F->(E)","F->i"};//产生式集合 
    int count=0;//记录当前进行处理的输入字符串字符位置
    int line=1;//记录处理的步骤数
    bool flag=false; 
    int StatusNumber=1;//栈中状态数
    string stacktd="#";//记录符号栈中内容
    int Status[50]={0};//记录状态栈
    stack <char> Stack;//创建一个符号栈
    stack <int> status;//创建一个状态栈 
    void Judge(int &i,int j,char arr[],char ch,string s){//判断输入串是否由文法终结符组成 
        flag=false; 
        for(int l=0;l<j;l++)
        {   
            if(ch==arr[l])
            {   
                flag=true;   
                i=l;   
                break;   
            } 
        } 
        if(flag==false)
        { 
            cout<<"\tError"<<endl; 
            count=s.size(); 
        } 
    } 
    void Outputstatus()
    {
        //输出状态集 
        for(int i=0;i<StatusNumber;i++)   
            cout<<Status[i];
    } 
    void Outputstring(string s)
    {
        //输出未处理的字符串 
        for(int i=count;i<s.size();i++)   
            cout<<s.at(i); 
    } 
    void Output(string s)
    {
        //输出步骤、状态集、符号集、输入串
        cout<<line<<"\t"; 
        Outputstatus();   
        cout<<"\t"<<stacktd<<"\t"; 
        Outputstring(s); 
        cout<<"\t\t"; 
        line++;
    } 
    void Shift(int i,string s)
    {//移进函数S 
        Output(s);     
        cout<<"ACTION["<&p()<<","<<s.at(count)<<"]=S"<<i<<",状态"<<i<<"入栈"<<endl;     

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。