LL(1)文法系列(三)预测分析程序

编译原理——第四章-LL(1)文法的判别条件、构造文法的预测分析表 LL(1)文法的判别条件 若一个文法满足以下条件,则称该文法G为LL(1)文法: 阅读详情

Problem Description

已知文法G[S]的表达式,通过预测分析表,对输入串进行分析。在文法G[S]中使用’@’代表空。

现在我们规定文法G[S]中每个表达式只包含一个语句,也就是说不会含有S -> A|B这样的表达式。

Input

 第一行输入一个n(n < 10),表示表达式的个数,接下来n行,每行一个表达式。终结符和非终结符的个数都小于10

最后一行输入字符串,长度小于20,输入串以#结尾

Output

 按照示例进行输出,使用\t进行格式控制,保证输入串合法。

为方便表示,将输入串翻转,在当前串中输出。

Sample Input

4
S->ABC
A->a
B->@
C->c
ac

Sample Output

#S	#ca	S->ABC	
#CBA	#ca	A->a
#CBa	#ca	a
#CB	#c	B->@
#C	#c	C->c
#c	#c	c
#	#	#
acc

code:

#include <cstdio>
#include <cstring>
#include <map>
#include <stack>
#include <algorithm>
using namespace std;
struct node
{
    char s1[10], s2[20] ;
} g[100];

char s[100] ;
int num ;
map<char,int> Map1;//对终结符映射
map<char,int> Map2;//对非终结符映射
int Map1_num, Map2_num;//记录终结符个数,非终结符个数
char s1[100] , s2[100] ;//存储终结符和非终结符
int first[20][20] ;
int follow[20][20] ;
int vis[100];//禁止重复递归
int acc[20] ;//使用以求得的集合
int select1[100][20] ;
int c[20][20] ;
char sta[100] ;
int cnt ;
void dfs1(char ch,int dis[])
{
    if( acc[ Map1[ch] ] )
    {
        for(int i = 1 ; i <= Map2_num; i++)
            dis[i] = first[ Map1[ch] ][i] ;
        return ;
    }
    int value[20] ;
    memset(value,0,sizeof(value));
    for(int i = 1 ; i <= num ; i++)
    {
        if( vis[i] ) continue ;
        if( g[i].s1[0] != ch ) continue ;
        int j , k , len = strlen(g[i].s2) ;
        for(j = 0 ; j < len ; j++)
        {
            if( Map1[ g[i].s2[j] ] )
            {
                vis[i] = 1 ;
                dfs1(g[i].s2[j],value);
                for(k = 2 ; k <= Map2_num ; k++)
                    if( value[k] ) dis[k] = 1 ;
                if( value[1] == 0 ) return ;
            }
            else
            {
                dis[ Map2[ g[i].s2[j] ] ] = 1 ;
                break;
            }
        }
        if( j == len )
            dis[1] = 1 ;
    }
    return ;
}
void dfs2(char ch,int dis[])
{
    int i , j , k , len , flag = 0 ;
    if( acc[ Map1[ch] ] )
    {
        for(int i = 1 ; i <= Map2_num; i++)
            dis[i] = follow[ Map1[ch] ][i] ;
        return ;
    }
    for(i = 1 ; i <= num ; i++)
    {
        len = strlen(g[i].s2) ;
        for(j = 0 ; j < len ; j++)
        {
            if( g[i].s2[j] == ch )
            {
                flag = 1 ;
                continue ;
            }
            if( !flag ) continue ;
            if( Map1[ g[i].s2[j] ] )
            {
                for(k = 2 ; k <= Map2_num ; k++)
                    if( first[ Map1[ g[i].s2[j] ] ][k] ) dis[k] = 1 ;
                if( !first[ Map1[ g[i].s2[j] ] ][1] )
                    flag = 0 ;
            }
            else
            {
                dis[ Map2[ g[i].s2[j] ] ] = 1 ;
                flag = 0 ;
            }
        }
        if( !flag || vis[i] ) continue ;
        int value[20] ;
        memset(value,0,sizeof(value));
        vis[i] = 1 ;
        dfs2(g[i].s1[0],value);
        for(i = 1 ; i <= Map2_num; i++)
            if( value[i] ) dis[i] = 1 ;

    }
}
int main()
{
    int i , j , k , len ;
    //freopen("data2.in", "r", stdin);
    //freopen("data2.out", "w", stdout);
    //输入
    num = Map1_num = Map2_num = 0 ;
    Map1.clear();
    Map2.clear();
    Map2[ '@' ] = ++Map2_num;
    s2[ Map2_num ] = '@';
    int m;
    scanf("%d", &m);
    while( m-- )
    {
        scanf("%s", s);
        len = strlen(s) ;
        num++ ;
        for(i = 0 ; i < 1 ; i++)
        {
            g[num].s1[i] = s[i] ;
            if( !Map1[ s[i] ] )
            {
                Map1[ s[i] ] = ++Map1_num ;
                s1[Map1_num] = s[i];
            }
        }
        g[num].s1[i] = '\0' ;
        for(i = 3 ; i < len ; i++)
        {
            g[num].s2[i-3] = s[i] ;
            if( s[i] >= 'A' && s[i] <= 'Z' )
            {
                if( !Map1[ s[i] ] )
                {
                    Map1[ s[i] ] = ++Map1_num ;
                    s1[Map1_num] = s[i];
                }
            }
            else
            {
                if( !Map2[ s[i] ] )
                {
                    Map2[ s[i] ] = ++Map2_num;
                    s2[Map2_num] = s[i];
                }
            }
        }
        g[num].s2[i-3] = '\0';
    }
    //求first
    memset(first,0,sizeof(first));
    memset(acc,0,sizeof(acc));
    for(i = 1 ; i <= Map1_num ; i++)
    {
        int value[20];
        memset(vis,0,sizeof(vis));
        memset(value,0,sizeof(value));
        dfs1(s1[i],value);
        for(j = 1 ; j <= Map2_num; j++)
            first[i][j] = value[j] ;
        acc[i] = 1 ;
    }
    //求follow
    Map2['#'] = ++Map2_num ;
    s2[ Map2_num ] = '#' ;
    memset(follow,0,sizeof(follow));
    memset(acc,0,sizeof(acc));
    for(i = 1 ; i <= Map1_num ; i++)
    {
        int value[20] ;
        memset(vis,0,sizeof(vis)) ;
        memset(value,0,sizeof(value));
        if( s1[i] == 'S' ) value[ Map2['#'] ] = 1 ;
        dfs2(s1[i],value);
        for(j = 1 ; j <= Map2_num; j++)
            follow[i][j] = value[j] ;
        acc[i] = 1 ;
    }
    //求select1
    memset(select1,0,sizeof(select1));
    for(i = 1 ; i <= num ; i++)
    {
        for(j = 0 ; j < strlen(g[i].s2) ; j++)
        {
            if( Map2[ g[i].s2[j] ] && g[i].s2[j] != '@' )
            {
                select1[i][ Map2[ g[i].s2[j] ] ] = 1 ;
                break ;
            }
            for(k = 2 ; k <= Map2_num ; k++)
            {
                if( first[ Map1[ g[i].s2[j] ] ][k] ) select1[i][k] = 1 ;
            }
            if( first[ Map1[ g[i].s1[j] ] ][1] == 0 ) break ;
        }
        if( j == strlen( g[i].s2 ) )
        {
            for(k = 2 ;  k <= Map2_num ; k++)
                if( follow[ Map1[ g[i].s1[0] ] ][k] ) select1[i][k] = 1 ;
        }
    }
    //预测分析表
    memset(c,0,sizeof(c)) ;
    for(i = 1 ; i <= num ; i++)
    {
        for(j = 1 ; j <= Map2_num ; j++)
        {
            if( select1[i][j] )
                c[ Map1[ g[i].s1[0] ] ][j] = i ;
        }
    }
    scanf("%s", s);
    len = strlen(s) ;
    for(i = 0 ; i < len/2 ; i++)
    {
        swap( s[i], s[len-1-i] );
    }
    cnt = 0 ;
    i = len-1 ;
    char ch;
    sta[cnt++] = '#';
    sta[cnt++] = 'S';
    while( i >= 0 )
    {
        if( cnt == 0 )
        {
            printf("@\n");
            break ;
        }
        ch = sta[cnt-1] ;
        if( Map1[ch] )
        {
            j = c[ Map1[ch] ][ Map2[ s[i] ] ] ;
            if( j )
            {
                sta[cnt] = '\0' ;
                s[i+1] = '\0' ;
                printf("%s\t%s\t%s->%s\n", sta, s, g[j].s1, g[j].s2);
                cnt-- ;
                for(k = strlen( g[j].s2 ) - 1 ; k >= 0 ; k-- )
                {
                    if( g[j].s2[k] != '@' )
                        sta[cnt++] = g[j].s2[k] ;
                }
            }
            else
            {
                printf("@\n") ;
                break ;
            }
        }
        else
        {
            if( ch == s[i] )
            {
                sta[cnt] = '\0' ;
                s[i+1] = '\0' ;
                printf("%s\t%s\t%c\n", sta, s, ch);
                cnt-- ;
                i--;
            }
            else
            {
                printf("@\n") ;
                break;
            }
        }
    }
    if( i < 0 )
        printf("acc\n");
    return 0;
}

 

【编译原理】典型题型:判断一个文法是否为LL(1)文法并构造预测分析表(First集和Follow集的求解方法&LL(1)文法的判断条件&预测分析表的构造&消除左递归的方法) 判断一个文法是否为LL(1)文法并构造预测分析表(First集和Follow集的求解方法&LL(1)文法的判断条件&预测分析表的构造) 目录判断一个文法是否为LL(1)文法并构造预测分析表(First集和Follow集的求解方法&LL(1)文法的判断条件&预测分析表的构造)题目预览LL(1)文法的判断条件First集和Follow集的求解方法预测分析表的构造方法题目解答!!!看这里 题目预览 G[S]: S->MH|a H->LSo|ε K->dML|ε 阅读详情

相关推荐

表驱动LL(1)分析程序过程详解

表驱动LL(1)分析程序由预测分析程序、先进后出栈和预测程序表3个部分组成,其中只有预测分析表与文法有关,而分析表又可用一个矩阵M表示。矩阵的元素M[A,a]中的下标A表示非终结符,a为终结符或句子括号#,矩阵元素M[A,a]中的内容是一条关于A的产生式,表明当用非终结字符A向下推导时,面令输入符a时所采取的候选产生式。当元素内容无产生式时,则表明A为左部向下推导时遇到了不该出现的符号,因此元...

W.J.Z 7352

编译原理:LL(1)文法 语法分析器(预测分析表法)

设计要求:对于任意输入的一个LL(1)文法,构造其预测分析表,并对指定输入串分析其是否为该文法的句子。 思路:首先实现集合FIRST(X)构造算法和集合FOLLOW(A)构造算法,再根据FIRST和FOLLOW集合构造出预测分析表,并对指定的句子打印出分析栈的分析过程,判断是否为该文法的句子。 //文法 E-&gt;TK K-&gt;+TK K-&gt;$ T-&gt;FM M-&...

沐雨金鳞 2万+

LL1文法的预测分析表法

适用于任何的LL1文法表,在输入这做了些处理,可以直接按照说明的要求把整个分析表复制进去。

[编译原理]LL(1)分析法+例题 学习

LL(1)分析法 LL(1) 分析法又称预测分析法 ,是 一种不带回溯的非递归自上而下分析法。 LL(1)分析器 LL(1)分析表 LL(1)文法:分析表M不含多重定义入口的文法 1、一个LL(1)文法所定义得语言恰好就是它的分析表所能识别的全部句子。 2、一个上下文无关文法是LL(1)文法的充要条件(判断一个文法是否是LL(1)文法):对每一个非终结符A的任何两个不同的产生式A→α|β,有下面条件(都是避免了多重入口)成立 (1)FIRST(α) ∩ FIRST(β) = ∅:A的每个候选是都不存

qq_43717303的博客 3万+

RAD Studio 12安装全攻略:从下载到破解InterBase的完整流程(附KeyPatch使用技巧)

本文提供RAD Studio 12的完整安装指南,包括系统要求、安装步骤及InterBase数据库的高效配置方法。详细介绍了如何使用KeyPatch工具进行许可证处理,并分享了IDE优化和开发技巧,帮助开发者快速上手这一强大的跨平台开发工具。

q6r7s8t9的博客 949

人形机器人骨骼材料选型实战:从铝合金到碳纤维的5种方案对比

本文深入探讨人形机器人骨骼材料的选型策略,对比铝合金、镁合金、钛合金、碳纤维复合材料及3D打印材料等5种方案的性能优劣。通过建立强度-重量比、疲劳寿命等核心评价维度,结合具体应用场景,提供科学的材料决策方法论,助力开发者优化机器人结构设计,实现性能与成本的平衡。

weixin_29199873的博客 440

编译原理:LL(1)文法判定,自顶向下语法分析(预测分析表法)

编译原理: 1. LL(1)文法判定 2. 自顶向下语法分析 3. 预测分析表的构造 4. 自顶向下预测分析算法

Aslixzhou 374

泛微E9统一待办接口说明

需要第三方表单,在提交自己的流程后,通过【window.location.href=‘oa地址/workflow/request/ViewRequestOS.jsp?需要第三方表单,在提交自己的流程后,通过【window.location.href=‘oa地址/workflow/workflow/WfRefreshList.jsp’】通过中转页面与第三方系统对接,按照第三系统的验证方式开发中转页面中的程序。C)第三方根据相同的数据加密,结果一致就认证成功,打开流程。优点:可以灵活的对接各个系统。

泛微二次开发后端知识总结 6396

K - LL(1)文法系列(三)预测分析程序

第一行输入一个n(n < 10),表示表达式的个数,接下来n行,每行一个表达式。终结符和非终结符的个数都小于10。按照示例进行输出(从左到右按照栈、输入缓冲区、输出结果的顺序打印),使用\t进行格式控制,保证输入串合法。现在我们规定文法G[S]中每个表达式只包含一个语句,也就是说不会含有S -> A|B这样的表达式。已知文法G[S]的表达式,通过预测分析表,对输入串进行分析。在文法G[S]中使用’@’代表空。最后一行输入字符串,长度小于20,输入串以#结尾。为方便表示,将输入串翻转,在当前串中输出。

代码欢乐豆 242

用示波器抓取同步Buck自举电容波形:从充电回路到SW节点振铃的完整分析

本文通过实测TI TPS54561和MPS MPQ4572同步Buck芯片,详细解析了自举电容在充电、维持和放电三个工作阶段的波形特征。重点揭示了电感泄放回路与充电回路重叠时,在SW节点引发的振铃现象及其产生机理,并提供了串联阻尼电阻等有效的工程抑制方法。文章结合示波器实测,为硬件工程师提供了从波形观测到问题调试的完整实践指南。

weixin_29276847的博客 372

WKWebView 白屏问题,WKWebView request body丢失问题

1,WKWebView 白屏问题 WKWebView 自诩拥有更快的加载速度,更低的内存占用,但实际上 WKWebView 是一个多进程组件,Network Loading 以及 UI Rendering 在其它进程中执行。初次适配 WKWebView 的时候,我们也惊讶于打开 WKWebView 后,App 进程内存消耗反而大幅下降,但是仔细观察会发现,Other Process 的内存占用会...

weixin_37543822的博客 736

编译原理:LL(1)文法-构造预测分析表

LL(1)文法-构造预测分析表 复习笔记 LL(1)文法分析是语法分析中比较重要的一个方法,其中比较重要的环节是构造预测分析表。 当然,在构造预测分析表之前,需要掌握两个集合的求法:FIRST集合和FOLLOW集合。 注意:下文的测试用例中使用的文法如下: E→TE’ E’→+TE’|ε T→FT’ T’→*FT’|ε F→(E)|i FIRST集合的求法 方法步骤如下: 1、X∈VT (终结符号集合) FIRST(X)={X}(即:终结符号的FIRST集仍然是其本身)。 2、X∈VN(非终结符号集合)

jianbai_的博客 4万+

忘记安卓锁屏密码怎么办?3种方法教你用ADB恢复访问(含gesture.key解密)

本文详细解析了安卓设备锁屏密码的存储与加密机制,特别是gesture.key文件的解密原理。针对遗忘密码的常见问题,提供了三种核心恢复方法:利用ADB调试接口删除密码文件、对gesture.key进行离线分析与解密,以及应对高版本系统的替代方案。重点介绍了通过ADB工具在Recovery模式下操作的具体步骤,帮助用户在合法合规前提下恢复设备访问权限。

php55的博客 959

【编译原理】第4章 LL(1)文法及其分析程序

4 LL(1)文法及其分析程序 目录一、自顶向下分析的问题二、LL(1)文法FIRST集、FOLLOW集和SELECT集LL(1)文法定义LL(1)分析程序实现三、非LL(1)文法的改造 语法分析任务:在词法分析识别出单词符号串的基础上,分析并判定程序的语法结构是否符合语法规则 分析算法分类(语法分析方法): 自上而下分析法:从文法的开始符号出发,反复使用各种产生式,寻找与输入符号匹配的最...

小羊咩咩的博客 6892

大模型部署指南:SGLang 框架

本文介绍使用 SGLang 框架部署大模型

举世誉之而不加劝,举世非之而不加沮,定乎内外之分,辩乎荣辱之境,斯已矣。 1611

双馈风机并网系统宽频振荡机理与抑制方法研究

双馈风机并网系统宽频振荡分析与抑制 摘要:本文研究了双馈风机(DFIG)接入弱电网引发的宽频振荡问题。通过建立DFIG并网系统阻抗模型,分析了锁相环带宽、电流环带宽等参数对阻抗特性的影响。研究揭示了DFIG与电网阻抗交互导致交截频率处相位差超过180°的振荡机理。提出基于锁相环优化的阻抗重塑抑制策略,采用电压补偿和陷波器改善系统稳定性。仿真结果表明,该方法能有效降低相位差约10°-168°,显著抑制宽频振荡。代码实现了阻抗建模、稳定性分析和抑制策略验证,为工程应用提供了理论依据。

huanghm88的专栏 319

细讲如何判断文法是否是LL(1)文法

文章目录细讲如何判断文法是否是LL(1)文法🐳LL(1)文法求解🐳左递归的消除🐳FIRST集合求解🐳FOLLOW集合求解🐳SELECT集合求解🐳实战例题 细讲如何判断文法是否是LL(1)文法 前言: ​ 在自然语言中,文法是文章的书写法规,一般用来指以文字、词语、短句、句子的编排而组成的完整语句和文章的合理性组织。 而文法在计算机中是设计师制定的一些规则,编译器通过这些规则可以识别出程序设计语言的语义,然后通过分析编译出语言(代码)要表达的效果,它在就像是编译器的大脑,没有它编译器就不能识别这些编程语言

热爱编程、热爱生活、热爱探索 2万+

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

编译原理LL(1)文法分析

一、实验目的: 根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对预测分析LL(1)分析法的理解。 二、实验说明 1、LL(1)分析法的功能 LL(1)分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。 2、LL(1)分析法的前提 改造文法:消除二义性、消除左递归、提取左因子,判断是否为LL(1)文法, 3、LL(1)分析法实验设计思想及算法 三、实验要求...

archerll的博客 8121

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

c++实现LL1文法

打造简单的编译器(二)——语法分析(LL1文法) #include <iostream> #include <map> #include <vector> #include <set> #include <list> #include <cstdio> #include <iomanip> using namesp...

antRain的博客 5088

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

【编译原理】LL1文法的语法分析器(预测分析表)

输入LL(1)文法 #include<iostream> #include<vector> #include<map> #include<cstring> #include<stack> using namespace std; /*定义产生式的语法集结构*/ typedef struct { char formula[200];...

simle的博客 9521

编译原理(四)自顶向下语法分析方法、LL(1)文法的判别、非LL(1)文法转换为LL(1)文法

本文要点 理解 “能使用自顶向下分析技术的文法必须是LL(1)文法” LL(1)文法的充要条件 LL(1)文法的判别 某些 非LL(1)文法 到 LL(1)文法 的等价变换 1.提取左公共因子 2.消除左递归(直接左递归、间接左递归) 不确定的自顶向下分析思想 确定的自顶向下分析方法 1.递归子程序法 2.预测分析法[判别LL(1)文法;构造预测分析表;分析输入串] 4.1 确定的自顶向下分析思想 主要思想: 从文法的开始符号出发,如何根据当前的单词符号, 唯一地确定选用哪个产生式来替换相应的VN向

star_of_science的博客 6359

LL(1)文法

文章目录预测分析法的工作过程S_文法(简单的确定性文法)什么时候使用$\epsilon$产生式?非终结符的后继符号集产生式的可选集q_文法串首终结符集LL(1)文法 预测分析法的工作过程 从文法开始符号触发,在每一步推导过程中根据当前句型的最左非终结符A和当前输入符号a,选择正确的A-产生式。为保证分析的确定性,选出的候选式必须是唯一的。 S_文法(简单的确定性文法) 特点: 每个产生式的右部都...

Meskjei的博客 3万+
上一篇: DAG优化
下一篇: LL(1)文法系列(二)预测分析表
shadowam
博客等级 码龄10年 62粉丝 168原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值