吉首大学_编译原理实验题_基于预測方法的语法分析程序的设计【通过代码】

一、实验要求

实验二  基于预測方法的语法分析程序的设计

一、实验目的

了解预測分析器的基本构成及用自顶向下的预測法对表达式进行语法分析的方法,掌握预測语法分析程序的手工构造方法。

二、实验内容

1、了解编译程序的基于预測方法的语法分析过程。

2、依据预測分析原理设计一个基于预測方法的语法分析程序。

三、实验要求

对给定文法G[S]:

S->AT       A->BU     T->+AT|$      U->*BU|$    B->(S)|m

当中,$表示空串。

1、推断上述文法G[S]是否LL(1)文法,若不是,将其转变为LL(1)文法;

2、对转变后的LL(1)文法建立预測分析表;

3、依据清华大学出版编译原理教材教材第五章P94的图5.11手工构造预測分析程序;

4、用预測分析程序对随意给定的键盘输入串m+m*m#进行语法分析,并依据栈的变化状态输出给定串的详细分析过程。

四、执行结果

从随意给定的键盘输入串:

m+m*m#;

输出:

用预測分析法分析符号串m+m*m#的过程


Step


Stack


String


Rule


Step


Stack


String


Rule


1


#S


m+m*m#


S->AT


10


#TUm


m*m#


M匹配


2


#TA


m+m*m#


A->BU


11


#TU


*m#


U->*BU


3


#TUB


m+m*m#


B->m


12


#TUB*


*m#


*匹配


4


#TUm


m+m*m#


M匹配


13


#TUB


m#


B->m


5


#TU


+m*m#


U->$


14


#TUm


m#


M匹配


6


#T


+m*m#


T->+AT


15


#TU


#


U->$


7


#TA+


+m*m#


+匹配


16


#T


#


T->$


8


#TA


m*m#


A->BU


17


#


#


接受


9


#TUB


m*m#


B->m

五、提示

本实验重点有两个:一是怎样用适当的数据结构实现预測分析表存储和使用;二是怎样实现各规则右部串的逆序入栈处理。

建议:使用结构体数组。

六、分析与讨论

1、若输入串不是指定文法的句子,会出现什么情况?

2、总结预測语法分析程序的设计和实现的一般方法。

二、通过代码

#include<stdio.h>
#include<iostream>
#include<cstring>
#include<string>
#include<stack>
#include<map>
#include<vector>
using namespace std;
string fir[5][6]={"","","AT","","AT","",
                  "","","BU","","BU","",
                  "+AT","","","$","","$",
                  "$","*BU","","$","","$",
                  "","","(S)","","m",""};  //first值表
map<char,int> vn;  //first表索引[非终结符]
map<char,int> vt;  //first表索引[终结符]
stack<char> Stack;  //分析栈
stack<char> String;  //剩余输入串栈
string s;   //语句存放
void inital(){
    vn[‘S‘]=1;//初始化first变索引
    vn[‘A‘]=2;
    vn[‘T‘]=3;
    vn[‘U‘]=4;
    vn[‘B‘]=5;
    vt[‘+‘]=1;
    vt[‘*‘]=2;
    vt[‘(‘]=3;
    vt[‘)‘]=4;
    vt[‘m‘]=5;
    vt[‘#‘]=6;
}
void output_stackt(){//每一步分析都得输出stack和String的值
    int n;

    s.clear();
    while(!Stack.empty()){
        s+=Stack.top();
        Stack.pop();
    }
    n=0;
    for(n=s.length()-1;n>=0;n--){
         Stack.push(s[n]);
         cout<<s[n];
    }
     cout<<"\t\t";
    s.clear();
    while(!String.empty()){
        s+=String.top();
        String.pop();
    }
    cout<<s<<"\t\t";
    n=0;
    for(n=s.length()-1;n>=0;n--)
        String.push(s[n]);
}
void ann()//程序核心程序,语法分析函数
{
    int len=0,count=0;
    char Stack_top,String_top;   //分析栈与余串栈栈顶元素
    Stack.push(‘#‘);    //#s进分析栈
    Stack.push(‘S‘);
    for(len =s.length()-1;len>=0;len--) //输入串进剩余输出栈
        String.push(s[len]);
    while(++count){    //ann 一直分析,直到接受或报错
        cout<<count<<"\t";
        output_stackt();
        if(Stack.empty()){//缺“#”【基本不会出现】
            cout<<"报错\nerror---the stack is empty\n";
            break;
        }
        if(String.empty()){//输入的串中没有“#”
            cout<<"报错\nerror---the sting is empty\n";
            break;
        }

        Stack_top=Stack.top();//取分析栈栈顶元素
        Stack.pop();    //栈顶已经要处理了,如今弹出
        String_top=String.top();//取待分析串栈顶元素
        if(vt[Stack_top]!=0&&Stack_top!=‘#‘)//没有分析道栈底
        {
            if(Stack_top==String_top){//能匹配字符
                cout<<"‘"<<Stack_top<<"‘匹配\n";
                String.pop();
                continue;
            }
            else{
                cout<<"报错\nerror---Stack_top!=String_top\n";
                break;
            }
        }
        if(Stack_top==‘#‘)//分析到栈底了
        {
            if(Stack_top==String_top)   //栈底是#,接受
            {
                cout<<"接受\n";
                break;
            }
            else{
                 cout<<"报错\nerror---Stack_top==‘#‘,but Stack_top!=String_top\n";
                break;
            }
        }
        else
        {
           if(vn[Stack_top]!=0&&vt[String_top]!=0){
                s=fir[vn[Stack_top]-1][vt[String_top]-1];
                if(s!="")
                {
                    if(s!="$")
                        for(len =s.length()-1;len>=0;len--) //公式进分析栈
                            Stack.push(s[len]);
                    cout<<Stack_top<<"->"<<s<<endl;
                }
                else
                {
                    cout<<"报错\nerror---fir[vn[Stack_top]-1][vt[String_top]-1] is null!\n";
                    break;
                }
           }
           else
           {
               cout<<"报错\nerror---vn[Stack_top]==0||vt[String_top]==0\n";
               break;
           }
        }
    }
}
void start()
{
    while(!Stack.empty())Stack.pop();
    while(!String.empty())String.pop();
    cout<<"please input the annli string:";
    cin>>s;
    cout<<"step\tstack\t\tstring\t\trule\n";
    ann();
    cout<<"\n\nthe annli is finish!\n";
}
int main(){//主函数,执行入口
    while(true){
        inital();   //初始化变量
        start();    //開始分析,而且输出分析情况
    }
    return 0;
}

三、执行结果

时间: 2024-12-19 00:38:12

吉首大学_编译原理实验题_基于预測方法的语法分析程序的设计【通过代码】的相关文章

哈工大软件学院编译原理实验1——词法分析

这次实验被"过来人"们定位非常easy,实验内容例如以下: ----------------------------------------------------------------------------------- 对例如以下工作进行展开描写叙述 (1) 给出语言的词法规则描写叙述 · 标识符.keyword.整常数.字符常数.浮点常数 · 单界符:+,-,×,;,- · 双界符:/*,:=,>=,<=,!=,- · 凝视 (2) 针对这样的单词的状态转换图和程

编译原理实验代码(词法分析,语法分析,中间代码生成)

花了一天写出的程序没有顾及很多层面,但对于理解基本的实验道理和交上实验还是有点帮助的.代码实现了基于有限自动机的词法分析,采用递归下降分析法和EBNF文法实现语法分析并生成中间代码. lexAnalysis.h /* * lexAnalysis.h * * Created on: 2014-12-2 * Author: liuqiushan */ #ifndef LEXANALYSIS_H_ #define LEXANALYSIS_H_ #include <stdio.h> #include

编译原理实验二:LL(1)语法分析器

一.实验要求 不得不想吐槽一下编译原理的实验代码量实在是太大了,是编译原理撑起了我大学四年的代码量... 这次实验比上次要复杂得多,涵盖的功能也更多了,我觉得这次实验主要的难点有两个(其实都是难点...): 1. 提取左公因子或消除左递归(实现了消除左递归) 2. 递归求First集和Follow集 其它的只要按照课本上的步骤顺序写下来就好(但是代码量超多...),下面我贴出实验的一些关键代码和算法思想. 二.基于预测分析表法的语法分析 2.1 代码结构 2.1.1  Grammar类    功

编译原理 实验3 语法分析

语法分析 一. 实验目的 算术表达式的文法可以是(你可以根据需要适当改变): E→E+E|E-E|E*E|E/E|(E)|i 根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确. 二. 实验环境 操作系统:window xp 编写环境:visual c++ 编写语言:c语言 三. 实验内容 程序输入/输出示例: 如参考C语言的运算符.输入如下表达式(以分号为结束)和输出结果: (1)10; 输出:正确 (2)1+2; 输出:正确 (3)(1+2)/3+4-(5+6/7); 输出:正

编译原理 - 实验三 - 递归下降语法分析器的调试及扩展

一. 语法分析介绍 语法分析是编译过程的核心部分,它的主要任务是按照程序语言的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行语法检查,为语义分析和代码生成做准备.执行语法分析任务的程序叫语法分析程序或语法分析器. 二. 所实现的语义分析和代码生成程序能处理什么语句 (1)简单变量的声明语句 (2)表达式语句 (3)if语句. (4)while语句 (5)for语句 (6)write语句 (7)read语句 (8)do语句. (9)处理过程调用和返回 三.实验过程 ①用VC

编译原理实验之词法分析

能识别小数,科学记数法表示的数. 不多解释,代码先上: #include <cstdio> #include <iostream> #include <string> #include <cstring> #include <algorithm> #include <cctype> #include <fstream> #include <map> #include <cstdlib> #inclu

编译原理 实验2 DFA的运行

DFA的运行 一. 实验目的 1.理解有穷自动机的作用: 2.利用状态图和状态表表示有穷自动机: 3.以程序实现有穷自动机的运行过程; 4.利用状态表和有穷自动机的运行原理编制程序,使得程序能够识别一个输入串是否为一个有效的符号串.具体可以选择下面之一:无符号定点实数,无符号正偶数,自然数,整数,十六进制数,或其他自己定义的符号串. 二. 实验环境 操作系统:window xp 编写环境:visual c++ 编写语言:c语言 三. 实验内容 1.简单介绍你所设计的有穷自动机.(要求必须完成无符

编译原理 实验1 PL/0语言词法分析

PL/0语言词法分析 一. 实验目的 通过完成词法分析程序,了解词法分析的过程.编制一个读单词程序,对PL/0语言进行词法分析,把输入的字符串形式的源程序分割成一个个单词符号,即基本保留字.标识符.常数.运算符.界符五大类. 二. 实验环境 操作系统:window xp 编写环境:visual c++ .c-free.turbo c 编写语言:c语言 分析语言:PL/0 三. 实验内容 对PL/0语言进行词法分析,把输入的字符串形式的源程序分割成一个个单词符号,其词法描述如下: (1) 关键字:

编译原理 - 实验四 - yacc基本使用(bison)

一.介绍 只要在Unix环境中写过程序,必定会邂逅神秘的Lex&YACC,就如GNU/Linux用户所熟知的Flex&Bison,这里的Flex就是由Vern Paxon实现的一个Lex,Bison则是GNU版本的YACC,在此我们将统一称呼这些程序为Lex和YACC,所以我们将用Flex和Bison来尝试下我们的实例. 二.准备工作(win7) ①  下载flex和bison并安装到D:\GnuWin32(尽量是根目录) ②    由于我们使用的flex和bison都是GNU的工具,所以