【编译原理】LL1文法语法分析器
上篇文章【编译原理】语法分析——自上向下分析 分析了LL1语法,文章最后说给出栗子,现在补上去。
说明:
- 这个语法分析器是利用
LL1分析方法实现的。 - 预测分析表和终结符以及非终结符都是针对一个特定文法定义好的。
- 输入的分析串必须以
#开头和结尾。
原始文法:
E -> E + T | T
T -> T * T | F
F -> (E) | i
消除左递归之后
E -> TE'
E' -> +TE' | e
T -> FT'
T' -> *FT' | e
F -> (E) | i
//备注
e 表示 一步赛楞
E' 在实际程序中用Z代替
T' 在实际程序中用Y代替
程序如下:
#include<iostream>
#include<vector>
#include<string>
#include<stack>
#define BEGIN_SYB 'E'
class Tab { //预测分析表中单个产生式
public:
Tab(char n,char e,std::string p):noend(n),end(e),prod(p) {};
char noend;
char end;
std::string prod;
};
std::vector<Tab> pTab; //预测分析表
std::stack<char> pStack; //栈
std::string pStr; //输入串
int index = 0; //输入串的下标
int num = 0; //下标
char X; //从栈顶取出的符号
char a; //字符串目前分析到的位置
std::vector<char> VT{'i','+','*','(',')','#'}; //终结符号集合
std::vector<char> VN{'E','Z','T','Y','F'}; //非终结符号集合
int
isPartVT(char ch)
{
for(auto u:VT) {
if(u == ch) {
return 1;
}
}
return 0;
}
int
isPartVN(char ch)
{
for(auto u:VN) {
if(u == ch) {
return 1;
}
}
return 0;
}
void
initpTab()
{
pTab.push_back(Tab('E','i',"TZ")); //Z表示E'
pTab.push_back(Tab('E','(',"TZ"));
pTab.push_back(Tab('Z','+',"+TZ"));
pTab.push_back(Tab('Z',')',"$"));
pTab.push_back(Tab('Z','#',"$"));
pTab.push_back(Tab('T','i',"FY"));
pTab.push_back(Tab('T','(',"FY")); //Y表示T'
pTab.push_back(Tab('Y','+',"$"));
pTab.push_back(Tab('Y','*',"*FY"));
pTab.push_back(Tab('Y',')',"$"));
pTab.push_back(Tab('Y','#',"$"));
pTab.push_back(Tab('F','i',"i"));
pTab.push_back(Tab('F','(',"(E)"));
}
void
printStack()
{
std::stack<char> pTemp(pStack);
while(pTemp.size() != 0) {
std::cout << pTemp.top() << " ";
pTemp.pop();
}
std::cout << " ";
}
int
synaly()
{
pStack.push(pStr[index++]);
pStack.push(BEGIN_SYB);
a = pStr[index++];
bool flag = true;
while(flag) {
std::cout << num++ << " "; //输出行号
printStack();
if(pStack.size() != 0) {
X = pStack.top(); //将符号栈顶给X
pStack.pop();
}
if(isPartVT(X)) { //如果是终结符
if(X == '#' && a == '#') {
flag = false;
}else if(X == a){
std::cout << std::endl;
a = pStr[index++];
}else {
std::cout << "EROOR!" << std::endl;
return 0;
}
}else if (X == '#') {
if(X == a) {
flag = false;
}else {
std::cout << "EROOR!" << std::endl;
return 0;
}
}else if (isPartVN(X) && isPartVT(a)) { //如果非终结符
int type = 0;
for(auto u:pTab) {
if(u.noend == X && u.end == a) {
std::string tempProd = u.prod;
std::cout << X << "->" << tempProd << std::endl;
if(tempProd == "$") {
type = 1;
break;
}else {
for(int i = tempProd.size()-1;i >= 0;--i) {
pStack.push(tempProd[i]);
}
type = 1;
break;
}
}
}
if(type != 1) {
std::cout << "EROOR!" << std::endl;
return 0;
}
}else {
std::cout << "EROOR!" << std::endl;
return 0;
}
}
return 1;
}
int main(int argc,char *argv[])
{
initpTab();
std::cout << "请输入语法串:";
std::cin >> pStr;
std::cout << "步骤" << " " << "符号栈" << " " << "所用产生式" << std::endl;
int flag = synaly();
std::cout << std::endl;
if(flag == 1) {
std::cout << "分析成功~~" << std::endl;
}else {
std::cout << "分析失败~~" << std::endl;
}
return 0;
}
【编译原理】LL1文法语法分析器的更多相关文章
- 编译原理LL1文法分析树(绘图过程)算法实现
import hjzgg.analysistable.AnalysisTable; import hjzgg.first.First; import hjzgg.follow.Follow; impo ...
- 编译原理LL1文法分析表算法实现
import hjzgg.first.First; import hjzgg.follow.Follow; import hjzgg.tablenode.TableNode; import hjzgg ...
- 编译原理LL1文法Follow集算法实现
import hjzgg.first.First; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set ...
- 编译原理 LL1文法First集算法实现
import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap ...
- Compiler Theory(编译原理)、词法/语法/AST/中间代码优化在Webshell检测上的应用
catalog . 引论 . 构建一个编译器的相关科学 . 程序设计语言基础 . 一个简单的语法制导翻译器 . 简单表达式的翻译器(源代码示例) . 词法分析 . 生成中间代码 . 词法分析器的实现 ...
- 编译原理简单语法分析器(first,follow,分析表)源码下载
编译原理(简单语法分析器下载) http://files.cnblogs.com/files/hujunzheng/%E5%8A%A0%E5%85%A5%E5%90%8C%E6%AD%A5%E7%AC ...
- <编译原理 - 函数绘图语言解释器(2)语法分析器 - python>
<编译原理 - 函数绘图语言解释器(2)语法分析器 - python> 背景 编译原理上机实现一个对函数绘图语言的解释器 - 用除C外的不同种语言实现 设计思路: 设计函数绘图语言的文法, ...
- 【编译原理】c++实现自下而上语法分析器
写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...
- 【编译原理】c++实现自上而下语法分析器
写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...
随机推荐
- spring入门1-IOC和DI
1.概述 1.1.简介 Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Or ...
- 测试验收标准checklist
需求实现功能清单 功能实现目的 需求改造功能清单 关联功能清单 关联系统 端到端全流程场景 业务联系性场景 业务全流程场景 上下需求关联规则 业务角度在流程中关注项 财报.评级 授信方案 反洗钱 面向 ...
- 启动springboot出现错误 Caused by: java.net.BindException: Address already in use: bind
如果运行过程中出现端口被占用 抛出了这个异常 首先可以在cmd中调出命令窗口然后 执行命令 netstat -ano 可以查看所有活动的连接 找到你被占用的端口 可以看到我被占用的端口的进程是 4 ...
- Gaussion
# Kernel density estimation import numpy as np import matplotlib.pyplot as plt from scipy.stats impo ...
- shiro的使用与JWT整合
一.shiro入门 两大框架对比:安全框架Shiro和SpringSecurity的比较 了解shiro 什么是Shiro Apache Shiro是一个Java的安全(权限)框架.| Shiro可以 ...
- 10.8 location
创建一个前台站点 server { listen 80; server_name www.nginx.com; locaiton / { root /var/www/html/www; } } 创建一 ...
- 题解 [HAOI2016]字符合并
题目传送门 Description 有一个长度为 \(n\) 的 \(01\) 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数. 得到的新字符和分数由这 k 个字符确定.你需要 ...
- spoj839 Optimal Marks(最小割,dinic)
题目大意: 给你一个无向图\(G(V,E)\). 每个顶点都有一个int范围内的整数的标记. 不同的顶点可能有相同的标记. 对于边\((u,v)\),我们定义\(Cost(u,v)=mark [u]\ ...
- bzoj1407,洛谷2421 NOI2002荒岛野人
题目大意: 克里特岛以野人群居而著称.岛上有排列成环行的M个山洞.这些山洞顺时针编号为1,2,-,M.岛上住着N个野人,一开始依次住在山洞C1,C2,-,CN中,以后每年,第i个野人会沿顺时针向前走P ...
- 破解安装pyhotn
1.网址 https://www.jetbrains.com/pycharm/download/#section=windows,打开页面,点击下载专业版 2.这是下载好的文件,双击运行即可. //详 ...