【编译原理】LL1文法语法分析器

时间:2022-06-18 02:28:55

上篇文章【编译原理】语法分析——自上向下分析 分析了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文法语法分析器的更多相关文章

  1. 编译原理LL1文法分析树&lpar;绘图过程&rpar;算法实现

    import hjzgg.analysistable.AnalysisTable; import hjzgg.first.First; import hjzgg.follow.Follow; impo ...

  2. 编译原理LL1文法分析表算法实现

    import hjzgg.first.First; import hjzgg.follow.Follow; import hjzgg.tablenode.TableNode; import hjzgg ...

  3. 编译原理LL1文法Follow集算法实现

    import hjzgg.first.First; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set ...

  4. 编译原理 LL1文法First集算法实现

    import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.TreeMap ...

  5. Compiler Theory&lpar;编译原理&rpar;、词法&sol;语法&sol;AST&sol;中间代码优化在Webshell检测上的应用

    catalog . 引论 . 构建一个编译器的相关科学 . 程序设计语言基础 . 一个简单的语法制导翻译器 . 简单表达式的翻译器(源代码示例) . 词法分析 . 生成中间代码 . 词法分析器的实现 ...

  6. 编译原理简单语法分析器(first&comma;follow&comma;分析表)源码下载

    编译原理(简单语法分析器下载) http://files.cnblogs.com/files/hujunzheng/%E5%8A%A0%E5%85%A5%E5%90%8C%E6%AD%A5%E7%AC ...

  7. &lt&semi;编译原理 - 函数绘图语言解释器(2)语法分析器 - python&gt&semi;

    <编译原理 - 函数绘图语言解释器(2)语法分析器 - python> 背景 编译原理上机实现一个对函数绘图语言的解释器 - 用除C外的不同种语言实现 设计思路: 设计函数绘图语言的文法, ...

  8. 【编译原理】c&plus;&plus;实现自下而上语法分析器

    写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...

  9. 【编译原理】c&plus;&plus;实现自上而下语法分析器

    写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...

随机推荐

  1. Java基础知识:代理

    一.代理的概念 动态代理技术是整个java技术中最重要的一个技术,它是学习java框架的基础,不会动态代理技术,那么在学习Spring这些框架时是学不明白的. 动态代理技术就是用来产生一个对象的代理对 ...

  2. Linux 下从头再走 GTK&plus;-3&period;0 &lpar;三&rpar;

    之前我们为窗口添加了一个按钮,接下来让这个按钮丰富一点.并给窗口加上图标. 首先创建 example3,c 的源文件. #include <gtk/gtk.h> static void a ...

  3. &lbrack;css&rsqb;需警惕CSS3属性的书写顺序

    转载张鑫旭:http://www.zhangxinxu.com/wordpress/2010/09/%E9%9C%80%E8%AD%A6%E6%83%95css3%E5%B1%9E%E6%80%A7% ...

  4. 一个高度压缩的bit位图字典的实现

    微软实现的字典功能简单方便,出于全局性考虑,其内部实现比较复杂,在对海量数据处理时,仅仅存放一个对象地址就将占据32个bit(64位机器中占据64个bit),而且其内部通过int[]来处理hash桶, ...

  5. routeProvider

    In a previous post about testing I mentioned that route resolves can make authoring unit tests for a ...

  6. php&lpar;验证网址是否存在&rpar;错误

      $ra=get_headers('http://hi.baidu.com'); if($ra[0]==='HTTP/1.1 200 OK'){ echo 'ok'; } 这是错误的,因为有时会返回 ...

  7. 【原码笔记】-- protobuf&period;js 与 Long&period;js

    protobuf.js的结构和webpack的加载之后的结构很相似.这样的模块化组合是个不错的结构方式.1个是适应了不同的加载方式,2个模块直接很独立.webpack的功能更全一点.但如果自己封装js ...

  8. mysql保存乱码(C&num;)

    解决办法只有一个就是在配置文件中强制指定编码格式:<add name="TSDBEntities" connectionString="metadata=res:/ ...

  9. N&excl;分解质因子p的个数&lowbar;快速求组合数C&lpar;n&comma;m&rpar;

    int f(int n,int p) { ) ; return f(n/p,p) + n/p; } https://www.xuebuyuan.com/2867209.html 求组合数C(n,m)( ...

  10. SQL语句or查询&comma;union all查询,分页查询&comma;分组&comma;AND查询

    一.OR查询 1.在AND多个筛选条件和一个or条件时,如果没有括号包裹,or会就近原则包裹之后的所有and条件,也就是同级的多个and条件只能对,or条件的一边起作用 2.如果or条件两边的筛选条件 ...