什么是算符优先分析法
算符优先分析法是一种简单、直观的自下而上分析法
算符优先分析法就是仿照算术表达式的四则运算过程而设计的一种语法分析方法。
这种分析方法首先要规定运算符之间(确切地说终结符之间)的优先关系和结合性质,然后借助这种关系,比较相邻运算符的优先级来确定句型的可归约串并进行归约。

分析步骤为:
1、扩展文法
S’ →#S#

2、求FIRSTVT()和LASTVT()集合
firstvt(S)={ a,^,( }
firstvt(T)={ , } ∪ firstvt(S) = {, ,a,^,( }
lastvt(S)= { a,^,) }
lastvt(T) = { , } ∪ lastvt(S) = { , ,a,^,) }

3、求优先关系
3.1 首先找 等于关系(两个vt之间只隔一个vn)
3.2 低于关系(vt在右,vn在左)
3.3 高于关系(vn在左,vt在右)
4、构造优先关系表
5、算符优先分析过程

一、实验目的

运用算符优先语法分析的基本原理实现对于句子的语法分析

二、实验要求

1、文法及待分析符号串由用户输入
2、数据结构可自行设计

三、实验内容

1、任意输入一个文法,判断它是否为简单优先文法
2、如果是,请构造该文法对应的简单优先分析表
3、输入一个字符串,判断它是否为该文法的一个句子。

四、实验代码

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <stack>
#include <iomanip>
#include <cstdlib>using namespace std;string V[100][2]; //存储拆分后的文法
int vi = 0; //存储拆分后有多少行
int t = 0;
int s = 0;
int l;
int r;string FIRSTVT[20][2]; //存储firstvt集
string LASTVT[20][2]; //存储lastvt集
string str; //存储输入文法
string str_a = "#"; // 下堆栈
string str_b; // 剩余输入串
string analysis_table[100][5]; // 文法分析过程char table[100][100]; // 算符优先关系表void init_string(string &a) // 删除字符串的第一个元素
{for (int i = 1; i <= a.length(); ++i){a[i - 1] = a[i];}
}bool is_CHAR(char c) // 判断是否为大写字母
{if (c >= 'A' && c <= 'Z'){return true;}else{return false;}
}bool is_in(int i, string x) // 判断从字符串x从最好一个开始算起连续的i个字符是否含有非大写字母
{bool flag = false;for (int j = 0; j < i; j++){if (!is_CHAR(x[x.length() - j - 1])){flag = true;}}return flag;
}void split(string a) // 拆分文法,使其不含有|
{for (int i = 3; i < a.length(); ++i){V[vi][0] = a[0];while (a[i] != '|' && i < a.length()){V[vi][1] += a[i];i++;}vi++;}
}void read_file(string file_path) //按行读取文件
{fstream f;f.open(file_path.c_str());vector<string> words;string line;while (getline(f, line)){words.push_back(line);}cout << "输入文法:" << endl;for (int i = 0; i < words.size(); i++){cout << words[i] << endl;split(words[i]);}
}int find_index(char a) //寻找字符a在firstvt或者lastvt中的位置
{for (int i = 0; i < t; ++i){if (FIRSTVT[i][0][0] == a){return i;}}return -1;
}int find_table_index(char a) //寻找字符a在算符优先关系表中的位置
{for (int i = 0; i <= s; ++i){if (table[i][0] == a){return i;}}return -1;
}void get_start() //获取非终结符
{for (int i = 0; i < vi; ++i){bool flag = true;for (int j = 0; j < t; ++j){if (FIRSTVT[j][0] == V[i][0]){flag = false;}}if (flag){FIRSTVT[t][0] = V[i][0];LASTVT[t][0] = V[i][0];t++;}}
}void add_firstvt(string b, int a) //判断字符串b是否在序号为a的firstvt中,没有则加入
{for (int s = 0; s < b.length(); ++s){bool flag = true;char c = b[s];if (c <= 'Z' && c >= 'A'){continue;}for (int i = 0; i < FIRSTVT[a][1].length(); ++i){if (c == FIRSTVT[a][1][i]){flag = false;}}if (flag){FIRSTVT[a][1] += c;}}
}void add_firstvt(char c, int a) //判断字符c是否在序号为a的firstvt中,没有则加入
{bool flag = true;for (int i = 0; i < FIRSTVT[a][1].length(); ++i){if (c <= 'Z' && c >= 'A'){continue;}if (c == FIRSTVT[a][1][i]){flag = false;}}if (flag){FIRSTVT[a][1] += c;}
}void add_lastvt(string b, int a) //判断字符串b是否在序号为a的lastvt中,没有则加入
{for (int s = 0; s < b.length(); ++s){bool flag = true;char c = b[s];if (c <= 'Z' && c >= 'A'){continue;}for (int i = 0; i < LASTVT[a][1].length(); ++i){if (c == LASTVT[a][1][i]){flag = false;}}if (flag){LASTVT[a][1] += c;}}
}void add_lastvt(char c, int a) //判断字符串c是否在序号为a的lastvt中,没有则加入
{bool flag = true;for (int i = 0; i < LASTVT[a][1].length(); ++i){if (c <= 'Z' && c >= 'A'){continue;}if (c == LASTVT[a][1][i]){flag = false;}}if (flag){LASTVT[a][1] += c;}
}string get_cur_firstvt(char c, int a) //获取当前字符的firstvt,并放入序号为a的firstvt中
{string temp;for (int i = 0; i < vi; ++i){if (c == V[i][0][0]){if (!(V[i][1][0] <= 'Z' && V[i][1][0] >= 'A')){add_firstvt(V[i][1][0], a);}else{if (c != V[i][1][0]){temp = get_cur_firstvt(V[i][1][0], find_index(V[i][1][0]));add_firstvt(temp, a);}if (V[i][1].length() > 2){if (!(V[i][1][1] <= 'Z' && V[i][1][1] >= 'A')){add_firstvt(V[i][1][1], a);}}}}}return FIRSTVT[a][1];
}string get_cur_lastvt(char c, int a) //获取当前字符的lastvt,并放入序号为a的lastvt中
{string temp;for (int i = 0; i < vi; ++i){int s = V[i][1].length();if (c == V[i][0][0]){if (!(V[i][1][s - 1] <= 'Z' && V[i][1][s - 1] >= 'A')){add_lastvt(V[i][1][s - 1], a);}else{if (c != V[i][1][s - 1]){temp = get_cur_lastvt(V[i][1][s - 1], find_index(V[i][1][0]));add_lastvt(temp, a);}if (V[i][1].length() > 2){if (!(V[i][1][s - 2] <= 'Z' && V[i][1][s - 2] >= 'A')){add_lastvt(V[i][1][s - 2], a);}}}}}return LASTVT[a][1];
}void get_firstvt() //获取所有文法的firstvt
{for (int i = 0; i < t; i++){get_cur_firstvt(FIRSTVT[i][0][0], i);}
}void get_lastvt() //获取所有文法的lastvt
{for (int i = 0; i < t; i++){get_cur_lastvt(LASTVT[i][0][0], i);}
}void print_firstvt(string t, string a) //打印非终极符为t的firstvt
{cout << "FIRSTVT(" << t << ") = {";for (int i = 0; i < a.length(); ++i){if (i == a.length() - 1){cout << "\"" << a[i] << "\"";}else{cout << "\"" << a[i] << "\"" << ", ";}}cout << "}" << endl;
}void print_lastvt(string t, string a) //打印非终结符为t的lastvt
{cout << "LASTVT(" << t << ") = {";for (int i = 0; i < a.length(); ++i){if (i == a.length() - 1){cout << "\"" << a[i] << "\"";}else{cout << "\"" << a[i] << "\"" << ", ";}}cout << "}" << endl;
}void init_table() //初始化算符优先关系表
{table[0][0] = '\\';for (int i = 0; i < vi; ++i){for (int j = 0; j < V[i][1].length(); ++j){bool flag = true;for (int k = 0; k < s + 1; ++k){if (table[k + 1][0] == V[i][1][j] || (V[i][1][j] <= 'Z' && V[i][1][j] >= 'A')){flag = false;}}if (flag){table[s + 1][0] = V[i][1][j];table[0][s + 1] = V[i][1][j];s++;}}}for (int l = 1; l < s + 1; ++l){for (int i = 1; i < s + 1; ++i){table[l][i] = ' ';}}
}void get_table() //生成算符优先关系表
{for (int i = 0; i < vi; ++i){for (int j = 0; j < V[i][1].length(); ++j){//abif (!(V[i][1][j] <= 'Z' && V[i][1][j] >= 'A') && !(V[i][1][j + 1] <= 'Z' && V[i][1][j + 1] >= 'A') &&j + 1 < V[i][1].length()){table[find_table_index(V[i][1][j])][find_table_index(V[i][1][j + 1])] = '=';}//aQbif ((!(V[i][1][j] <= 'Z' && V[i][1][j] >= 'A')) && (V[i][1][j + 1] <= 'Z' && V[i][1][j + 1] >= 'A') &&(!(V[i][1][j + 2] <= 'Z' && V[i][1][j + 2] >= 'A')) && j + 2 < V[i][1].length()){table[find_table_index(V[i][1][j])][find_table_index(V[i][1][j + 2])] = '=';}//aQif ((!(V[i][1][j] <= 'Z' && V[i][1][j] >= 'A')) && (V[i][1][j + 1] <= 'Z' && V[i][1][j + 1] >= 'A') &&j + 1 < V[i][1].length()){for (int k = 0; k < FIRSTVT[find_index(V[i][1][j + 1])][1].length(); ++k){table[find_table_index(V[i][1][j])][find_table_index(FIRSTVT[find_index(V[i][1][j + 1])][1][k])] = '<';}}//Qaif ((V[i][1][j] <= 'Z' && V[i][1][j] >= 'A') && !(V[i][1][j + 1] <= 'Z' && V[i][1][j + 1] >= 'A') &&j + 1 < V[i][1].length()){for (int k = 0; k < LASTVT[find_index(V[i][1][j])][1].length(); ++k){table[find_table_index(LASTVT[find_index(V[i][1][j])][1][k])][find_table_index(V[i][1][j + 1])] = '>';}}}}
}void print_table() //打印算符优先关系表
{for (int i = 0; i < s + 1; ++i){for (int j = 0; j < s + 1; ++j){cout << table[i][j] << " ";}cout << endl;}
}char get_relationship(char a, char b) //获取终结符a,b的优先关系
{return table[find_table_index(a)][find_table_index(b)];
}bool is_reduce() //判断是否可以规约
{for (int i = 0; i < vi; ++i){int count = 0;int f = str_a.length() - 1;for (int j = V[i][1].length() - 1; j >= 0 && f >= 0; j--, f--){if (is_in(V[i][1].length(), str_a)){if (is_CHAR(str_a[f]) && is_CHAR(V[i][1][j])){count++;}else if (str_a[f] == V[i][1][j]){count++;}}else{continue;}}if (count == V[i][1].length()){r = i;return true;}}return false;
}void analyze_input_string() // 生成算符优先文法的分析过程
{analysis_table[0][0] = "步骤";analysis_table[0][1] = "下堆栈";analysis_table[0][2] = "优先关系";analysis_table[0][3] = "剩余输入串";analysis_table[0][4] = "移进或规约";str_b = str;char relationship;l = 1;int x;stringstream ss;while (true){ss << l;int index = str_a.length() - 1;analysis_table[l][0] = ss.str();analysis_table[l][3] = str_b;analysis_table[l][1] = str_a;ss.clear();ss.str("");if (is_CHAR(str_a[index])){for (int i = str_a.length() - 1; i >= 0; i--){if (!is_CHAR(str_a[i])){index = i;break;}}}relationship = get_relationship(str_a[index], str_b[0]);analysis_table[l][2] = relationship;if (relationship == '='){if (str_a[index] == '#' && str_b[0] == '#'){analysis_table[l][4] = "完成";break;}else{analysis_table[l][4] = "移进";str_a += str_b[0];analysis_table[l + 1][1] = str_a;init_string(str_b);}}else if (relationship == '<'){analysis_table[l][4] = "移进";str_a += str_b[0];analysis_table[l + 1][1] = str_a;init_string(str_b);}else if (relationship == '>'){if (is_reduce()){analysis_table[l][4] = "规约";str_a[str_a.length() - V[r][1].length()] = V[r][0][0];str_a.erase(str_a.length() - V[r][1].length() + 1, V[r][1].length() - 1);}else{cout << "输入串非法" << endl;exit(-1);}}l++;}
}void print_analyze_process() //打印算符优先文法的分析过程
{cout << "算符优先分析过程" << endl;cout << setw(12) << analysis_table[0][0] << setw(16) << analysis_table[0][1] << setw(16) << analysis_table[0][2]<< setw(24)<< analysis_table[0][3] << setw(20)<< analysis_table[0][4] << endl;for (int i = 1; i <= l; ++i){cout.width(10);cout << analysis_table[i][0];cout.width(12);cout << analysis_table[i][1];cout.width(10);cout << analysis_table[i][2];cout.width(20);cout << analysis_table[i][3];cout << analysis_table[i][4];cout << endl;}
}int main(int argv, char *arg[])
{cout.setf(std::ios::left);read_file("D:\\in.txt");cout << "拆分后文法:" << endl;for (int i = 0; i < vi; ++i){cout << V[i][0] << "->" << V[i][1] << endl;}cout << "非终结符:" << endl;get_start();for (int j = 0; j < t; ++j){cout << FIRSTVT[j][0] << endl;}cout << "FIRSTVT:" << endl;get_firstvt();for (int k = 0; k < t; ++k){print_firstvt(FIRSTVT[k][0], FIRSTVT[k][1]);}cout << "LASTVT:" << endl;get_lastvt();for (int k = 0; k < t; ++k){print_lastvt(LASTVT[k][0], LASTVT[k][1]);}cout << "算符优先关系表" << endl;init_table();get_table();print_table();cout << "请输入文法并以#结束:" << endl;cin >> str;analyze_input_string();print_analyze_process();return 0;
}//E→E+T∣T//T→T*F∣F//F→(E)∣i

五、测试结果

1.从文件中读取文法,然后构造优先表
2.输入待分析串,输出分析过程
in.txt中文法为:
S->#E#
E->E+T|T
T->T*F|F
F->(E)|i

编译原理:算符优先分析实验相关推荐

  1. 算符优先分析法代码 java_编译原理——算符优先分析文法(附源代码)

    1 源代码2 模块一:3 /****************#include"firstVT_lastVT.h"************************/ 4 5 //程序 ...

  2. 编译原理 —— 算符优先分析法

    什么是算符优先分析法 算符优先分析法是一种简单.直观的自下而上分析法 算符优先分析法就是仿照算术表达式的四则运算过程而设计的一种语法分析方法. 这种分析方法首先要规定运算符之间(确切地说终结符之间)的 ...

  3. 编译原理简单优先分析算法

    简单优先分析算法 编译原理简单优先分析算法是一种自下而上的分析算法,本例是编译原理第三版何炎祥中一个简单优先分析算法的例子,未给出分析过程分析代码,读者可以参考我的语法分析器中输出代码,写出此算法的输 ...

  4. 编译技术算符优先分析课设c++_2020年河北省专接本理工类计算机科学与技术软件工程专业考试大纲...

    河北省普通高校专科接本科教育考试 计算机科学与技术/软件工程/网络工程/物联网工程 专业考试说明 第一部分:C 语言程序设计 I.课程简介 一.内容概述与要求 C 语言程序设计课程考试是为招收计算机科 ...

  5. java编程实现算符优先分析法,编译原理实验三-算符优先分析法

    编译原理实验3-算符优先分析法 #include #include #include #include #define SIZE 128 char priority[6][6]; //算符优先关系表数 ...

  6. 算符优先文法编写java语法分析器,编译原理课程设计实验报告——基于算符优先分析方法的表达式语法分析器...

    内容简介: 一.设计目的 了解用算符优先法对表达进行语法分析的方法,掌握自顶向下的预测语法分析程序的手工构造方法. 二.设计内容 对简单表达式文法构造算符优先分析器. 三.设计要求 1.对下列简单表达 ...

  7. 编译原理实验:自下而上的语法分析---(算符优先分析)

    ** 算符优先分析程序(NCWU慎用) ** 1.实验要求 ⑴ 选择算符优先分析方法: ⑵ 选择对各种常见程序语言都用的语法结构,如赋值语句或表达式或控制流语句等作为分析对象,并且与所选语法分析方法要 ...

  8. 编译原理 词法分析 算符优先分析法

    编译原理 词法分析 算符优先分析法 实验目的 加深对语法分析器工作工程的理解,加强对算符优先分析法实现语法分析程序的掌握:能够采用一种编程语言实现简单的语法分析程序:能够使用自己辨析的分析程序对简单的 ...

  9. 编译原理(五)自底向上分析之算符优先分析法

    自底向上分析之算符优先分析法 说明:以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记. 基本过程 1. 一般方法:采用自左向右地扫描和分析输入串,从输入符号串开始,通过反复查找当前句型的句 ...

最新文章

  1. RDKit | 基于RDKit获取分子3D距离矩阵
  2. linux安装oracle 操作系统内核参数 aio,Linux安装Oracle 11G过程(测试未写完)
  3. lamp mysql大小限制_[转]LAMP 系统性能调优,第 3 部分: MySQL 服务器调优
  4. gpu处理信号_GPU显卡不仅用来打游戏那么简单,它还可以用于通用加速计算
  5. 用C#写MSN机器人
  6. pip keras 失败_关于 Python 机器学习导包失败 简短的补充
  7. 初始化bean(二)—— 缓存部分
  8. r语言简介_R语言简介
  9. 学习笔记--2014年7月7日
  10. 最常见的Java框架有哪些?
  11. Spring--超简单利用quartz实现定时作业
  12. 使用图片验证码进行登录验证
  13. 机器学习面试题60~100
  14. 1s看懂555定时器,以及应用?
  15. 小米笔记本linux无线网失效,小米笔记本无线网络打不开怎么办
  16. Emacs - Verilog mode 自动实例化
  17. C++Error2208:…尝试引用已删除的函数
  18. poi 启用保护后取消_保护模式禁用怎么解除
  19. 设计模式之CS和BS结构的区别
  20. 如何看待996的工作模式

热门文章

  1. 线性代数之——行列式公式及代数余子式
  2. Win7系统下如何设置改变文本文档背景颜色
  3. c语言中的除号什么作用,c语言中除号用什么表示
  4. 什么是绿色工厂,怎么进行绿色工厂认证
  5. 负载均衡服务器性能数据,用缓存服务器负载均衡 提数据库查询效率
  6. android service拦截按键,android里面屏蔽home键/禁止Home键或者随你DIY
  7. Superset 制作 地图 柱状图 饼状图
  8. 微信小程序——给用户发送通知
  9. 看了一遍蝴蝶效应1,在看到了一篇很好的《蝴蝶效应1》影评
  10. leetcode学习打卡--572. 另一个树的子树(递归,二叉树遍历)