预测分析表方法

简介: 代码遵从C++14标准,忙着别的事潦草的完成,还有许多需要优化的地方。预测表里面的数:-1代表这有报错,其他数字拆开十位代表行,个位代表列;行:给出文法的行,从0开始,如:E→TE’是第0行;因为只需要到了右半部分所以只保留了右半部分列:为什么会出现列呢?因为很多文法右半部分是或的关系,如:T’ →*FT’ |/ FT’ |%FT’|ε 依次的行列是(3,0),(3,1),(3,2),(3,3)所以预测表里存储的是30,31,32,33其他部分看代码的注释即可,有问题可以留言或加我QQ讨论

算术表达式文法

E→TE’

E’ → +TE’|- TE’|ε

T→FT’

T’ →*FT’ |/ FT’ |%FT’|ε

F→(E) |id|num


给定一符合该文法的句子,如id+id*id#,运行预测分析程序,给出分析过程和每一步的分析结果

前言

  • 代码遵从C++14标准,忙着别的事潦草的完成,还有许多需要优化的地方。
  • 预测表里面的数:-1代表这有报错,其他数字拆开十位代表行,个位代表列;
  • 行:给出文法的行,从0开始,如:E→TE’是第0行;因为只需要到了右半部分所以只保留了右半部分
  • 列:为什么会出现列呢?因为很多文法右半部分是或的关系,如:T’ →*FT’ |/ FT’ |%FT’|ε 依次的行列是(3,0),(3,1),(3,2),(3,3)所以预测表里存储的是30,31,32,33
  • 其他部分看代码的注释即可,有问题可以留言或加我QQ讨论

话不多说上代码


main.cpp

//

// Created by NorthS on 2022/5/5.

// QQ:1826496887

// url:www.vieuu.cn

//

#include "compilerwork.h"

//E`=X

//T`=Y

stack<char> reverAndPush(stack<char> s,string str);

int main(){

   string s[5][10];

   s[0][0]="TX";

   s[1][0]="+TX";s[1][1]="-TX";s[1][2]="$";

   s[2][0]="FY";

   s[3][0]="*FY";s[3][1]="/FY";s[3][2]="%FY";s[3][3]="$";

   s[4][0]="(E)";s[4][1]="i";s[4][2]="n";

   int patable[5][10]={0,0,-1,-1,-1,-1,-1,0,-1,-1,

                       -1,-1,10,11,-1,-1,-1,-1,12,12,

                       20,20,-1,-1,-1,-1,-1,20,-1,-1,

                       -1,-1,33,33,30,31,32,-1,33,33,

                       41,42,-1,-1,-1,-1,-1,40,-1,-1

   };

   int follow[5][10]={0,0,0,0,0,0,0,0,1,1,

                      0,0,0,0,0,0,0,0,1,1,

                      0,0,1,1,0,0,0,0,1,1,

                      0,0,1,1,0,0,0,0,1,1,

                      0,0,1,1,1,1,1,0,1,1

   };

   string str="ii#";

   int flag=0;

   stack<char> gra;

   gra.push('#');

   gra.push('E');

   while(1){

       if(flag-1==str.size())break;

       if(isNonterminator(gra.top())){//非终结符

           int i= inNonterminatorindex(gra.top());

           int j= inTerminatorindex(str[flag]);

           if(patable[i][j]!=-1){//在预测表中有交点

               int index=patable[i][j];

               int m=index/10;

               int n=index%10;

               cout<<gra.top()<<"\t\t\t"<<str[flag]<<"\t\t\t"<<"展开非终结符"<<gra.top()<<"->"<<s[m][n]<<endl;

              //在栈中弹出该非终结符

               gra.pop();

              //其右式逆序入栈

               gra= reverAndPush(gra,s[m][n]);

           }else{//在预测表中没交点

               if(follow[i][j]==1){//当前单词属于该follow集

                   cout<<gra.top()<<"\t\t\t"<<str[flag]<<"\t\t\t"<<"\033[31;1m"<<"从栈中弹出该非终结符"<<gra.top()<<"\033[0m"<<endl;

                  //从栈中弹出该非终结符继续分析

                   gra.pop();

               }else{//当前单词不属于该follow集

                   cout<<gra.top()<<"\t\t\t"<<str[flag]<<"\t\t\t"<<"\033[31;1m"<<"串指针下移(抛弃该单词不分析)"<<"\033[0m"<<endl;

                  //串指针下移(抛弃该单词不分析)

                   flag++;

                   if(flag==str.size()){//如果跳过的单词是最后一个单词报错并直接结束

                       break;

                   }

               }

           }

       }

       if(isTerminator(gra.top())){//终结符

           if(gra.top()==str[flag]){//匹配成功

               cout<<gra.top()<<"\t\t\t"<<str[flag]<<"\t\t\t"<<"匹配终结符"<<str[flag]<<endl;

               gra.pop();//栈顶元素出栈

               flag++;//串指针下移

           }else{//匹配不成功

              //第一种:从栈中弹出此终结符x(认为输入串中缺少单词a)√

              // 第二种:将串指针下移一个位置(认为串中当前单词a多余)

               cout<<gra.top()<<"\t\t\t"<<str[flag]<<"\t\t\t"<<"\033[31;1m"<<"从栈中弹出该终结符"<<"\033[0m"<<gra.top()<<endl;

               gra.pop();

           }

       }

   }

   return 0;

}

handle.cpp

//

// Created by NorthS on 2022/5/5.

// QQ:1826496887

// url:www.vieuu.cn

//

#include "compilerwork.h"

char Nonterminator[10]={'E','X','T','Y','F'};

char Terminator[10]={'i','n','+','-','*','/','%','(',')','#'};

bool isNonterminator(char ch){

   for(int i=0;i<strlen(Nonterminator);i++){

       if(Nonterminator[i]==ch)return true;

   }

   return false;

}

bool isTerminator(char ch){

   for(int i=0;i<strlen(Terminator);i++){

       if(Terminator[i]==ch)return true;

   }

   return false;

}

int inNonterminatorindex(char ch){

   for(int i=0;i<strlen(Nonterminator);i++){

       if(Nonterminator[i]==ch)return i;

   }

   return -4;

}

int inTerminatorindex(char ch){

   for(int i=0;i<strlen(Terminator);i++){

       if(Terminator[i]==ch)return i;

   }

   return -4;

}

stack<char> reverAndPush(stack<char> s,string str){

   if(str.size()==1&&str[0]=='$')return s;

   for(int i=str.size()-1;i>=0;i--){

       s.push(str[i]);

   }

   return s;

}

compilerwork.h

//

// Created by NorthS on 2022/5/5.

// QQ:1826496887

// url:www.vieuu.cn

//

#ifndef COMPILERW4_COMPILERWORK_H

#define COMPILERW4_COMPILERWORK_H

#include<bits/stdc++.h>

using namespace std;

/**

* 是否是非终结符

* @param ch

* @return

*/

bool isNonterminator(char ch);

/**

* 是否是终结符

* @param ch

* @return

*/

bool isTerminator(char ch);

/**

* 该非终结符在非终结符表中的位置

* @param ch

* @return

*/

int inNonterminatorindex(char ch);

/**

* 该终结符在终结符表中的位置

* @param ch

* @return

*/

int inTerminatorindex(char ch);

#endif //COMPILERW4_COMPILERWORK_H

 


目录
相关文章
|
SQL 数据挖掘 数据库
从管控角度谈慢SQL治理
慢SQL指的是执行效率低、响应时间长的SQL查询,其定义需综合考虑执行时间、业务场景、资源消耗、频率及影响、用户体验等多个维度。产生慢SQL的原因包括硬件问题、无索引或索引失效、锁等待及不当的SQL语句。慢SQL会增加资源占用,影响其他请求响应时间,可能导致系统故障,引发数据不一致问题,并影响用户体验。优化慢SQL需善用工具发现、设置合理告警机制,并进行分级治理与长期追踪。
|
9月前
|
开发者 异构计算
高效部署通义万相Wan2.1:ComfyUI文生/图生视频实战,工作流直取!
通义万相Wan2.1开源不到一周,已登顶HuggingFace Model 和 Space 榜双榜首,在HuggingFace和ModelScope平台的累计下载量突破100万次,社区热度持续攀升!为响应小伙伴们对ComfyUI工作流运行Wan2.1的强烈需求,社区开发者整理了实战教程👇
7054 23
高效部署通义万相Wan2.1:ComfyUI文生/图生视频实战,工作流直取!
编译原理(1)----LL(1)文法(首符号集,后跟符号集,选择符号集)
编译原理(1)----LL(1)文法(首符号集,后跟符号集,选择符号集)
368 5
|
关系型数据库 MySQL 数据库
MySQL 什么是意向锁?为什么要有意向锁?
【8月更文挑战第24天】MySQL 什么是意向锁?为什么要有意向锁?
1485 0
编译原理——构造预测分析表(判断某字符串是否是文法G(E)的句子)
编译原理——构造预测分析表(判断某字符串是否是文法G(E)的句子)
354 0
|
Shell 网络安全 开发工具
Gerrit✨Gerrit服务器简介 与 配置SSH keys
Gerrit✨Gerrit服务器简介 与 配置SSH keys
|
Java 程序员 数据处理
从软件危机中处理软件工程问题
【6月更文挑战第28天】本文介绍软件危机及其处理方式。1968年的北约会议首次提出“软件危机”,指软件开发的复杂性和成本超支问题。现代解决策略包括多种方法和模型,如OO、结构化、RUP和SOA,旨在提高效率和适应性。
1229 0
从软件危机中处理软件工程问题
|
监控 Java 调度
Spring Boot中的定时任务调度
Spring Boot中的定时任务调度
|
编解码 安全 Linux
基于arm64架构国产操作系统|Linux下的RTMP|RTSP低延时直播播放器开发探究
这段内容讲述了国产操作系统背景下,大牛直播SDK针对国产操作系统与Linux平台发布的RTMP/RTSP直播播放SDK。此SDK支持arm64架构,基于X协议输出视频,采用PulseAudio和Alsa Lib处理音频,具备实时静音、快照、缓冲时间设定等功能,并支持H.265编码格式。此外,提供了示例代码展示如何实现多实例播放器的创建与管理,包括窗口布局调整、事件监听、视频分辨率变化和实时快照回调等关键功能。这一技术实现有助于提高直播服务的稳定性和响应速度,适应国产操作系统在各行业中的应用需求。
424 3
|
消息中间件 存储 Java
Java中的消息队列应用与性能优化
Java中的消息队列应用与性能优化