算符优先系列之(二)算符优先关系表

python:天天向上与三天打鱼两天晒网 ​ 滴水能把石穿透,万事功到自然成。不积跬步,无以至千里;不积小流,无以成江海。 ​ 阅读详情

Problem Description

学过编译原理的菊苣们都知道算符优先文法,作为一个有点深度的分析方法,我们怎么能只止步于理论呢,实践才是王道哦。

已知文法G[S]的表达式,求算符优先关系表。因为某些特殊的原因,我们在这规定一下输入输出格式。

已知文法G[S]为:

S`->#S#(拓展文法,不是题目给出的文法)

S->a|@|(T)

T->T,S|S

表达式算符优先关系表中从左到右(从上到下)的顺序为从表达式文法中从左到右从上到下的顺序即为

a @ ( ) , #  (我们默认把#放在最右边或者最下边)

Input

多组输入。第一行输入一个n,表示表达式的个数,接下来n行每行一个表达式(记得还有一个要在自己程序中添加的拓展文法哦)

Output

根据上述的格式,输出算符优先关系表(输出的格式用水平制表符\t)

Sample Input

2
S->a|@|(T)
T->T,S|S

Sample Output

	a	@	(	)	,	#
a	 	 	 	>	>	>	
@	 	 	 	>	>	>	
(	<	<	<	=	<	 	
)	 	 	 	>	>	>	
,	<	<	<	>	>	 	
#	<	<	<	 	 	=	

code:

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <set>
#include <queue>
#include <stack>
#include <map>
#include <bitset>
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long LL;
const int inf=0x3f3f3f3f;
const double pi= acos(-1.0);
const double esp=1e-6;
using namespace std;

const int Maxn=110;
const int maxn=20;
char str[maxn][Maxn];//输入文法
char st[maxn];//输入串
char stac[maxn];//模拟栈的数组
char nstr[maxn][maxn];//储存转化文法
char mstr[maxn][maxn];
char fin[maxn];//存储终结符
char firstvt[maxn][maxn],lastvt[maxn][maxn];
char cmp[maxn][maxn];//存储表中的比较符
int firstflag[maxn],lastflag[maxn];//非终结符的firstvt,lastvt是否求出
int fcnt[maxn],lcnt[maxn];//非终结符firsvt和lastvt的个数
int is_fin(char c) { //判断终结符
    for(int i=0; fin[i]!='\0'; i++) {
        if(fin[i]==c)
            return 1;
    }
    return 0;
}
int site(char c) { //求在表中的下标
    for(int i=0; fin[i]!='\0'; i++) {
        if(fin[i]==c)
            return i;
    }
}

void get_firstvt(char s,int t) { //求s非终结符的firstvt值
    int i,j,ii,jj,tt;
    for(i=0; i<t; i++) {
        if(str[i][0]==s)
            break;
    }
    if(!firstflag[i]) {
        int k=fcnt[i];
        for(j=0; str[i][j]!='\0'; j++) {
            if(j==2||str[i][j]=='|') {
                if(is_fin(str[i][j+1])) {
                    firstvt[i][k++]=str[i][j+1];
                } else {
                    if(is_fin(str[i][j+2])) {
                        firstvt[i][k++]=str[i][j+2];
                    }
                    if(str[i][j+1]!=s) {
                        get_firstvt(str[i][j+1],t);
                        for(ii=0; ii<t; ii++) {
                            if(str[ii][0]==str[i][j+1])
                                break;
                        }
                        for(jj=0; jj<fcnt[ii]; jj++) {
                            for(tt=0; tt<k; tt++) {
                                if(firstvt[i][tt]==firstvt[ii][jj])
                                    break;
                            }
                            if(tt==k) {
                                firstvt[i][k++]=firstvt[ii][jj];
                            }
                        }
                    }
                }
            }
        }
        firstvt[i][k]='\0';
        fcnt[i]=k;
        firstflag[i]=1;
    }
}

void output_firstvt(int T) { //输出firstvt集
    for(int i=0; i<T; i++) {
        get_firstvt(str[i][0],T);
    }

}

void get_lastvt(char s,int t) { //求s非终结符的lastvt值
    int i,j,ii,jj,tt;
    for(i=0; i<t; i++) {
        if(str[i][0]==s)
            break;
    }
    if(!lastflag[i]) {
        int k=lcnt[i];
        for(j=0; str[i][j]!='\0'; j++) {
            if(str[i][j+1]=='|'||str[i][j+1]=='\0') {
                if(is_fin(str[i][j])) {
                    lastvt[i][k++]=str[i][j];
                } else {
                    if(is_fin(str[i][j-1])) {
                        lastvt[i][k++]=str[i][j-1];
                    }
                    if(str[i][j]!=s) {
                        get_lastvt(str[i][j],t);
                        for(ii=0; ii<t; ii++) {
                            if(str[ii][0]==str[i][j])
                                break;
                        }
                        for(jj=0; jj<lcnt[ii]; jj++) {
                            for(tt=0; tt<k; tt++) {
                                if(lastvt[i][tt]==lastvt[ii][jj])
                                    break;
                            }
                            if(tt==k) {
                                lastvt[i][k++]=lastvt[ii][jj];
                            }
                        }
                    }
                }
            }
        }
        lastvt[i][k]='\0';
        lcnt[i]=k;
        lastflag[i]=1;
    }
}

void output_lastvt(int T) { //输出lastvt集
    for(int i=0; i<T; i++) {
        get_lastvt(str[i][0],T);
    }

}

void get_table(int T,int cnt) { //得到表
    int x=0,y=0;
    int i,j,ii,jj;
    for(i=0; i<T; i++) {
        for(j=0; str[i][j]!='\0'; j++) {
            if(str[i][j]!='|')
                nstr[x][y++]=str[i][j];
            else if(str[i][j]=='|') {
                nstr[x][y]='\0';
                x++;
                y=0;
                nstr[x][y++]=str[i][0];
                nstr[x][y++]='-';
                nstr[x][y++]='>';
            }
        }
        nstr[x][y]='\0';
        x++;
        y=0;
    }
    //对于S1->#S#;
    char a='#';
    cmp[site(a)][site(a)]='=';
    for(i=0; i<fcnt[0]; i++) {
        cmp[site(a)][site(firstvt[0][i])]='<';
    }
    for(i=0; i<lcnt[0]; i++) {
        cmp[site(lastvt[0][i])][site(a)]='>';
    }
    //对于初始的文法
    for(i=0; i<x; i++) {
        for(j=3; nstr[i][j+1]!='\0'; j++) {
            if(is_fin(nstr[i][j])&&is_fin(nstr[i][j+1]))
                cmp[site(nstr[i][j])][site(nstr[i][j+1])]='=';
            if(is_fin(nstr[i][j])&&!is_fin(nstr[i][j+1])&&is_fin(nstr[i][j+2])&&nstr[i][j+2]!='\0')
                cmp[site(nstr[i][j])][site(nstr[i][j+2])]='=';
            if(!is_fin(nstr[i][j])&&is_fin(nstr[i][j+1])) { //对于非终结符在终结符之前
                for(ii=0; ii<T; ii++) {
                    if(str[ii][0]==nstr[i][j])
                        break;
                }
                for(jj=0; jj<lcnt[ii]; jj++)
                    cmp[site(lastvt[ii][jj])][site(nstr[i][j+1])]='>';
            }
            if(is_fin(nstr[i][j])&&!is_fin(nstr[i][j+1])) { //对于终结符在非终结符之前
                for(ii=0; ii<T; ii++) {
                    if(str[ii][0]==nstr[i][j+1])
                        break;
                }
                for(jj=0; jj<fcnt[ii]; jj++)
                    cmp[site(nstr[i][j])][site(firstvt[ii][jj])]='<';
            }
        }
    }
    for(i=0; fin[i]!='\0'; i++)
        printf("\t%c",fin[i]);
    puts("");
    for(i=0; i<cnt; i++) {
        printf("%c\t",fin[i]);
        for(j=0; j<cnt; j++) {
            if(cmp[i][j]!=0)
                printf("%c\t",cmp[i][j]);
            else
                printf(" \t");
        }
        puts("");
    }

}
void output(int i,int j,char *str) {
    printf("\t");
    for(int ii=i; ii<=j; ii++)
        printf("%c",str[ii]);
}

int isDX(char c)
{
    if(c>='A'&&c<='Z')
        return 1;
    return 0;
}
void exchange()
{
    int ecnt=0;
    for(int i=0;i<10;i++){
        int mcnt=0;
        for(int j=3;nstr[i][j]!='\0';j++){
            if(isDX(nstr[i][j])&&strlen(nstr[i])!=4)
                mstr[ecnt][mcnt++]='N';
            else if(!isDX(nstr[i][j]))
                mstr[ecnt][mcnt++]=nstr[i][j];
            else{
                break;
            }
        }
        mstr[ecnt][mcnt]='\0';
        if(strlen(mstr[ecnt])!=0)
        ecnt++;
    }
}

int main() {
    //freopen("D:\\input.txt","r",stdin);
    //freopen("D:\\output.txt","w",stdout);
    int T;
    while(~scanf("%d",&T)){
    int cnt=0;//终结符的个数
    memset(firstflag,0,sizeof(firstflag));
    memset(lastflag,0,sizeof(lastflag));
    memset(cmp,0,sizeof(cmp));
    for(int i=0; i<T; i++) {
        scanf("%s",str[i]);
        fcnt[i]=lcnt[i]=0;
    }
    for(int i=0; i<T; i++) {
        for(int j=0; str[i][j]!='\0'; j++) {
            if((str[i][j]<'A'||str[i][j]>'Z')&&(str[i][j]!='-'&&str[i][j]!='>')&&str[i][j]!='|')
                fin[cnt++]=str[i][j];
        }
    }
    fin[cnt++]='#';
    fin[cnt]='\0';
    output_firstvt(T);
    output_lastvt(T);
    get_table(T,cnt);
    }
    return 0;
}

 

算法与数据结构课后习题第三章 第三章-栈和队列-作业 一、单选题(共15题,7) 1.对于栈操作数据的原则是( )。 A. 先进先出 B. 后进先出 C. 后进后出 D. 不分顺序 我的答案: B正确答案: B答案解析:基本概念 2.一个栈的输入序列为123…n,若输出序列的第一个元素是n,输出第i(1<=i<=n)个元素是( )。 A. 不确定 B. n-i+1 C. i D. n-i 我的答案: B正确答案: B答案解析:基本概念 3.若一个栈的输入序列为1,2,3,…,n,输出序列的第一个元 阅读详情

相关推荐

C语言运算符优先级表详解

优先级

Eliauk1234的博客 2万+

Spark Streaming状态管理函数updateStateByKey和mapWithState

updateStateByKey可以在指定的批次间隔内返回之前的全部历史数据,包括新增的,改变的和没有改变的。由于updateStateByKey在使用的时候一定要做checkpoint,当数据量过大的时候,checkpoint会占据庞大的数据量,会影响性能,效率不高。如果不输入新的数据,会一直展示之前的结果查看checkpoint文件夹下,发现有很多类似于checkpoint-1542090065000的状态文件这些checkpoint文件都是小文件,对hdfs的压力很大,怎么解决呢?下文会讲。...

大数据 1万+

编译原理核心算法实战:算符优先分析法Java实现

句柄是归约过程中最关键的概念。在一个句型中,句柄是指某个产生式右部的子串,将其归约为对应非终结符后,能够继续完成剩余归约直至起始符号。形式化地说:设 $ \alpha A \beta $ 是一个句型,且存在推导 $ S \Rightarrow^\alpha A \beta \Rightarrow \alpha \gamma \beta $,其中 $ A \to \gamma $ 是一条产生式,则称 $ \gamma $ 在位置 $ |\alpha| $ 处是该句型的一个短语;

weixin_29215509的博客 1011

构造优先关系表

在自底向下优先分析一章中有一个非常重要的题型——构造优先关系表,接下来我们就来看看具体是怎么操作的。注意:进行这一步的前提是要知道FIRSTVT和LASTVT的求法,大家可以看我之前写的博客:FIRSTVT和LASTVT的计算(很长但是很详细)_驼驼学编程的博客-优快云博客 1.基本概念 大家可能不太好理解,我们把它转化成伪代码的形式供同学们理解。 2.伪代码呈现 大伙可能看的还是云里雾里,我来和大家解释一下。 给大家举一个例子:P->ABC 我们来看ABC三者的关系, .

qq_55168827的博客 1万+

数字孪生在智慧医疗中的5个创新应用:从手术模拟到个性化治疗

数字孪生技术通过创建患者或医疗流程的动态虚拟映射,正在深刻变革智慧医疗。本文重点剖析了其在个性化治疗、手术模拟与导航、药物研发、医院管理优化及慢性病管理五大核心场景的创新应用,展现了如何利用智能映射与数据融合,为精准医疗和高效决策提供强大支持。

weixin_29189003的博客 443

【Anaconda】conda国内镜像源快速配置指南(清华/阿里云)

本文详细介绍了如何为Anaconda配置国内镜像源(清华/阿里云),以显著提升conda包下载速度并减少安装失败率。通过分步指南和实用技巧,帮助开发者快速完成配置,优化Python开发环境。

weixin_33725722的博客 1486

H - 算符优先系列之(二)算符优先关系表

第一行输入一个n,表示表达式的个数,接下来n行每行一个表达式(记得还有一个要在自己程序中添加的拓展文法哦)学过编译原理的菊苣们都知道算符优先文法,作为一个有点深度的分析方法,我们怎么能只止步于理论呢,实践才是王道哦。已知文法G[S]的表达式,求算符优先关系表。表达式算符优先关系表中从左到右(从上到下)的顺序为从表达式文法中从左到右从上到下的顺序即为。根据上述的格式,输出算符优先关系表(输出的格式用水平制表符\t)S`->#S#(拓展文法,不是题目给出的文法)

代码欢乐豆 265

Mac本地部署OpenClaw:从零搭建企业级知识库AI助手

大语言模型(LLM)作为当前人工智能的核心技术,通过其强大的自然语言理解和生成能力,正在深刻改变信息交互方式。其原理是基于海量数据训练的深度神经网络,能够根据上下文预测并生成连贯文本。这一技术的核心价值在于,它能够作为智能中枢,理解和执行复杂指令,从而将通用AI能力转化为解决特定业务问题的生产力。在工程实践中,通过AI Agent框架(如OpenClaw)将LLM与外部工具和知识系统连接,是实现其价值的关键。这涉及到**本地部署**与**私有化**部署,以确保数据安全与成本可控。具体应用场景包括企业知识库问

weixin_33402252的博客 378

【编译原理】C++实现算符优先分析(超详细系列+有源码+有注释+可运行)

目录 算符优先分析 1.实验目的 2.实验过程 2.1算符优先关系表的构造方法 2.2思路 3.实验代码: 4.实验结果 算符优先分析 1.实验目的 了解用算符优先法对表达进行语法分析的方法,掌握自顶向下的预测语法分析程序的手工构造方法。 实验要求:一个交互式面向对象的算符优先分析程序基本功能是: (1) 输入文法规则 (2) 对文法进行转换 (3) 生成每个非终结符的FirstVT和LastVT (4) 生成算符优先分析表 (5) 再输入文法符号串 (6) 生...

小树じ的博客 6650

保姆级避坑指南:在Ubuntu 22.04上从零编译Autoware.universe(含ROS2 Humble和CUDA配置)

本文提供了一份详细的Autoware.universe编译指南,涵盖Ubuntu 22.04系统优化、ROS2 Humble安装避坑、CUDA配置及Demo运行技巧。通过分步操作和实战经验,帮助开发者高效完成环境搭建,避免常见错误,提升自动驾驶开发效率。

weixin_30642561的博客 347

从零开始用STM32驱动RGB屏:配置PCLK、DE同步信号的避坑指南

本文详细介绍了如何使用STM32驱动RGB接口LCD屏幕,重点解析了PCLK配置、同步信号极性和DE使能等关键参数的设置方法。通过实战代码示例和常见问题排查指南,帮助开发者避免常见配置错误,实现稳定的显示效果。特别针对800x480 IPS屏提供了优化建议和调试技巧。

sky77的博客 540

深入i-算符优先:输入串分析的奥秘

回顾算符优先分析输入串的要点,我们首先要明确算符文法的定义,它是输入串分析的基石,只有符合算符文法的条件,才能进一步探讨算符优先关系和算符优先文法。算符优先关系的确定,包括 “<・”“=・”“・>” 这三种关系,是整个分析过程的核心,通过仔细分析文法的产生式,我们可以构建出准确的算符优先关系表,这张表就像是我们在分析输入串时的指南针,引导我们正确地进行移进和规约操作。

大雨淅淅的博客 1033

Langfuse实战:从评估打分到问题解决的完整指南

本文详细介绍了如何利用开源LLM工程平台Langfuse对AI应用进行系统性评估与优化。从创建评估数据集、设计自动化评分函数,到深入排查常见问题并关联Trace进行精准打分,提供了完整的实战指南。最后,探讨了如何利用评估结果驱动提示词迭代与A/B测试,并给出了生产环境部署与性能优化的关键考量,帮助开发者构建可测量、可分析、可改进的LLM应用。

backprop5master的博客 651

算符优先分析之输入串分析

算符优先分析是一种自底向上的语法分析方法,主要用于分析简单的算术表达式。它通过比较相邻文法符号之间的优先关系(包括“>”、“<”、“=”)来决定归约的时机,从而构建语法分析树。分析过程包括初始化、扫描输入串、根据优先关系执行移进或归约操作,直到输入串分析完毕。算符优先分析的优点在于实现简单、分析效率高,特别适用于表达式类语法分析,且不需要回溯。然而,它需要文法满足算符文法条件,难以处理复杂的语言结构,且不适用于某些含有二义性的文法。在实际编译器实现中,算符优先分析通常用于表达式解析阶段,并可能与

weixin_47233946的博客 547

2024年数字IC秋招-速腾聚创-数字芯片验证工程师-笔试题

笔试题型:单选 + 问答题笔试平台:牛客(手机+电脑监控)笔试时间:1hA. len取10的概率是1/2;B. len取10的概率是1/3;C. len取10的概率是1/4;D. len取10的概率是1;

qq_42135020的博客 1399

2026 Claude Code 标准化前端UI SKILL——Frontend Design

是 Anthropic 官方开源的技能包,在 Claude 官方插件站中排名第一,超过 52k 的下载量。场景推荐方案快速体验批量安装官方 Skills深度设计策略叠加完整打磨流程集成终端跑claude一句话总结:Frontend Design 不是给 AI 加新能力,而是给 AI 加审美标准。它让 AI 从“能画”变成“会设计”——先想清楚风格,再动手写代码。

十年老程序猿,AI 疯狂研究专家,前沿硬核知识分享 3612

实验3:算符优先分析法

本次实验要求根据算符优先关系表编制一个算符优先分析程序,以便对任意输入的符号串进行分析。”一列中如果是规约则写明规约串;如果为移进则写明移进的终结符;如分析异常出错则写为“出错”;若成功结束则写为“成功”。注意:此代码为速成品,存在诸多问题,仅供参考。3.掌握算符优先驱动程序的构造方法。1.掌握算符优先分析法的基本原理。2.掌握算符优先分析表的构造方法。4.加深对算符优先分析法的理解。

m0_67368095的博客 843

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

算符优先系列之(三)输入串分析算符优先分析法是一种自底向上的语法分析方法,特别适用于表达式的分析。在算符优先分析中,输入串的分析过程是关键步骤。

你似乎切换到了一个关于 **算符优先分析** 的话题。3. **可能导致错误规约**(如 `E + E * E` 可能被错误规约成 `(E + E) * E`,但算符优先分析不会这样)。| $ E + E * E | $ | `* > $`,规约 `E * E → E` || $ E + id | * id $ | `id > *`,规约 `id → E` || $ E + E | * id $ | `+ < *`,移进 `*` |

weixin_66625287的博客 495

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

编译原理实战指南:从算符优先到LR(1)分析的完整解析

本文深入解析编译原理中的自下而上分析技术,重点介绍算符优先分析和LR(1)分析的原理与实现。通过详细的算法步骤和实战案例,帮助开发者掌握语法分析的核心技术,提升编译器开发能力。内容涵盖FIRSTVT/LASTVT集合构造、优先关系表构建、LR(0)项目集计算等关键知识点,并对比不同分析方法的适用场景。

weixin_29268331的博客 333

编译i原理5 算符优先文法

基本思想:就是从待分析的终结符号串出发,反向使用产生式规则,将产生式规则右部的符号串归约为左部的非终结符。通过一系列这样的归约,最终能归约出文法的起始符号,则证明待分析的终结符号串是合法的句子。

weixin_43747148的博客 763

C语言实现算符优先分析算法:FIRSTVT、LASTVT与优先关系表

语法分析器的核心任务是在词法单元序列上判定句子结构,自下而上分析通过移进与归约不断构造语法树。算符优先分析算法以终结符间的优先关系为依据,定位最左素短语并完成归约,是理解该机制的经典入口。FIRSTVT 与 LASTVT 集合描述非终结符两端可能出现的终结符,配合优先关系表即可驱动分析栈完成移进-归约。其价值在于规则简单、代码量可控,适合表达式求值、编译器前端教学与原型验证。围绕 C 语言手写算符优先分析器,可把集合迭代、二维关系建模、栈操作和错误处理串成完整工程实践,并形成可编译、可调试的实现路径。

weixin_30086969的博客 223

编译原理陈火旺版第五章:从课后题解析到自下而上语法分析实战

本文深入解析编译原理陈火旺版第五章内容,重点探讨自下而上语法分析实战技巧。通过课后题详细讲解句型识别、句柄定位、规范归约等核心概念,并结合算符优先分析、LR分析家族等关键技术,提供完整的解题思路和方法。适合编译原理学习者参考,帮助掌握语法分析的核心算法和实现技巧。

weixin_30876945的博客 245
上一篇: 算符优先系列之(一)Firstvt和Lastvt集
下一篇: 分治算法——顺序表应用7:最大子段和之分治递归法
shadowam
博客等级 码龄10年 62粉丝 168原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值