Liny_@NotePad

沉迷ACG中

算符优先分析

YOYO posted @ 2009年6月12日 02:52 in 【C/C++】 with tags 编译原理 语法分析 , 2774 阅读

一、功能描述:
根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确并计算结果。
二、程序结构描述:
 全局变量:

#define N 8    ——算符个数
string ops = "+-*/()i#";  ——算符
map<char, int> ophash; ——算符哈希表
int opv[N][N];    ——算符优先表: 0-无 1-大于 2-等于 3-小于

string str;    ——存放输入串
int top;     ——输入串位置
stack<char> st;   ——堆栈
stack<int> stnum;   ——存储结果堆栈
bool divzero;    ——除零标志

程序分成如下几个函数:

 void init() —— 初始化函数:构造算符优先表。

 bool isNumber(string s, int v = 0) ——判断一个串是否是无符号整数
 int toInt(string s) —— 转换一个数字串为无符号整数

 string next()   —— 取得下一个单词

 bool out(string s) —— 归约过程,不能归约则返回false
 char first()   —— 获得距离栈顶最近的VT元素
 bool check()  —— 分析过程,不匹配则返回false

 main —— 主函数
处理输入串的部分,对输入的文件test2.txt内容进行算符优先语法分析。
* 输入串必须以“;”结束。当输入串合法时将计算该串的值,结果将显示在控制台。

程序总体执行流程详见代码。

三、实验总结:
完成总使用八课时:
其中纸上时间四课时,编程两课时,调试两课时。

 收获:
了解到一些算符优先语法分析的知识。

四、程式源码:

  1. #include<iostream>
  2. #include<string>
  3. #include<stack>
  4. #include<map>
  5. using namespace std;
  6.  
  7. #define N 8                    //   算符个数
  8. string ops = "+-*/()i#";        //      算符
  9.  
  10. map<char, int> ophash;  //        算符哈希表
  11. int opv[N][N];      //        算符优先表: 0-无 1-大于 2-等于 3-小于
  12.  
  13. string str;                    //   存放输入串
  14. int top;                                //      输入串位置
  15. stack<char> st;   //       堆栈
  16. stack<int> stnum;              //     存储结果堆栈
  17. bool divzero;         // 除零标志
  18.  
  19. /* 判断一个串是否是无符号整数 */
  20. bool isNumber(string s, int v = 0){
  21.         if(s[v]>='0'&&s[v]<='9')return true;
  22.         return false;
  23. }
  24.  
  25. /* 转换一个数字串为无符号整数 */
  26. int toInt(string s){
  27.         int x = 0;
  28.         for(int i=0; s[i]!='\0'; i++){
  29.                 x = x*10 + s[i]-'0';
  30.         }
  31.         return x;
  32. }
  33.  
  34. /* 取得下一个单词 */
  35. string next(){
  36.         string tmp = "";
  37.  
  38.         if(str.size()-1==top){
  39.                 top ++;
  40.                 return "#";
  41.         }
  42.  
  43.         if(str.size()==top)return "";
  44.  
  45.         //      如果不是数字 说明是运算符 直接返回该字符的串
  46.         if(!isNumber(str, top)){
  47.                 tmp.append(1, str[top++]);
  48.                 return tmp;
  49.         }
  50.  
  51.         //      如果是数字 读完整个数字
  52.         while(isNumber(str, top))tmp.append(1, str[top++]);
  53.         return tmp;
  54. }
  55.  
  56. /* 初始化 */
  57. void init(){
  58.         int i,j;
  59.  
  60.         //      构造算符哈希表
  61.         for(i=0; i<N; i++){
  62.                 ophash[ops[i]] = i;
  63.         }
  64.  
  65.         //      构造算符优先表
  66.         {
  67.                 {
  68.                         opv[ophash['+']][ophash['+']] = 1;
  69.                         opv[ophash['+']][ophash['-']] = 1;
  70.                         opv[ophash['+']][ophash['*']] = 3;
  71.                         opv[ophash['+']][ophash['/']] = 3;
  72.                         opv[ophash['+']][ophash['(']] = 3;
  73.                         opv[ophash['+']][ophash[')']] = 1;
  74.                         opv[ophash['+']][ophash['i']] = 3;
  75.                         opv[ophash['+']][ophash['#']] = 1;
  76.                 }
  77.                 {
  78.                         opv[ophash['-']][ophash['+']] = 1;
  79.                         opv[ophash['-']][ophash['-']] = 1;
  80.                         opv[ophash['-']][ophash['*']] = 3;
  81.                         opv[ophash['-']][ophash['/']] = 3;
  82.                         opv[ophash['-']][ophash['(']] = 3;
  83.                         opv[ophash['-']][ophash[')']] = 1;
  84.                         opv[ophash['-']][ophash['i']] = 3;
  85.                         opv[ophash['-']][ophash['#']] = 1;
  86.                 }
  87.                 {
  88.                         opv[ophash['*']][ophash['+']] = 1;
  89.                         opv[ophash['*']][ophash['-']] = 1;
  90.                         opv[ophash['*']][ophash['*']] = 1;
  91.                         opv[ophash['*']][ophash['/']] = 1;
  92.                         opv[ophash['*']][ophash['(']] = 3;
  93.                         opv[ophash['*']][ophash[')']] = 1;
  94.                         opv[ophash['*']][ophash['i']] = 3;
  95.                         opv[ophash['*']][ophash['#']] = 1;
  96.                 }
  97.                 {
  98.                         opv[ophash['/']][ophash['+']] = 1;
  99.                         opv[ophash['/']][ophash['-']] = 1;
  100.                         opv[ophash['/']][ophash['*']] = 1;
  101.                         opv[ophash['/']][ophash['/']] = 1;
  102.                         opv[ophash['/']][ophash['(']] = 3;
  103.                         opv[ophash['/']][ophash[')']] = 1;
  104.                         opv[ophash['/']][ophash['i']] = 3;
  105.                         opv[ophash['/']][ophash['#']] = 1;
  106.                 }
  107.                 {
  108.                         opv[ophash['(']][ophash['+']] = 3;
  109.                         opv[ophash['(']][ophash['-']] = 3;
  110.                         opv[ophash['(']][ophash['*']] = 3;
  111.                         opv[ophash['(']][ophash['/']] = 3;
  112.                         opv[ophash['(']][ophash['(']] = 3;
  113.                         opv[ophash['(']][ophash[')']] = 2;
  114.                         opv[ophash['(']][ophash['i']] = 3;
  115.                         opv[ophash['(']][ophash['#']] = 0;
  116.                 }
  117.                 {
  118.                         opv[ophash[')']][ophash['+']] = 1;
  119.                         opv[ophash[')']][ophash['-']] = 1;
  120.                         opv[ophash[')']][ophash['*']] = 1;
  121.                         opv[ophash[')']][ophash['/']] = 1;
  122.                         opv[ophash[')']][ophash['(']] = 0;
  123.                         opv[ophash[')']][ophash[')']] = 1;
  124.                         opv[ophash[')']][ophash['i']] = 0;
  125.                         opv[ophash[')']][ophash['#']] = 1;
  126.                 }
  127.                 {
  128.                         opv[ophash['i']][ophash['+']] = 1;
  129.                         opv[ophash['i']][ophash['-']] = 1;
  130.                         opv[ophash['i']][ophash['*']] = 1;
  131.                         opv[ophash['i']][ophash['/']] = 1;
  132.                         opv[ophash['i']][ophash['(']] = 0;
  133.                         opv[ophash['i']][ophash[')']] = 1;
  134.                         opv[ophash['i']][ophash['i']] = 0;
  135.                         opv[ophash['i']][ophash['#']] = 1;
  136.                 }
  137.                 {
  138.                         opv[ophash['#']][ophash['+']] = 3;
  139.                         opv[ophash['#']][ophash['-']] = 3;
  140.                         opv[ophash['#']][ophash['*']] = 3;
  141.                         opv[ophash['#']][ophash['/']] = 3;
  142.                         opv[ophash['#']][ophash['(']] = 3;
  143.                         opv[ophash['#']][ophash[')']] = 0;
  144.                         opv[ophash['#']][ophash['i']] = 3;
  145.                         opv[ophash['#']][ophash['#']] = 2;
  146.                 }
  147.         }
  148. }
  149.  
  150. /* 归约 */
  151. bool out(string s){
  152.         if(s=="i"){
  153.                 st.push('E');
  154.                 return true;
  155.         }
  156.         if(s==")E("||s=="E/E"||s=="E*E"||s=="E-E"||s=="E+E"){
  157.                 st.push('E');
  158.                 if(s[0] == 'E'){
  159.                         int b = stnum.top();
  160.                         stnum.pop();
  161.                         int a = stnum.top();
  162.                         stnum.pop();
  163.                         switch(s[1]){
  164.                         case '/':
  165.                                 if(b==0){
  166.                                         divzero = true;
  167.                                         b = 1;
  168.                                 }
  169.                                 stnum.push(a/b);
  170.                                 break;
  171.                         case '*':
  172.                                 stnum.push(a*b);
  173.                                 break;
  174.                         case '-':
  175.                                 stnum.push(a-b);
  176.                                 break;
  177.                         case '+':
  178.                                 stnum.push(a+b);
  179.                                 break;
  180.                         }
  181.                 }
  182.                 return true;
  183.         }
  184.         return false;
  185. }
  186.  
  187. /* 获得距离栈顶最近的VT元素 */
  188. char first(){
  189.         stack<char> tmpst;
  190.         while(!st.empty()&&ops.find(st.top(),0)==-1){
  191.                 tmpst.push(st.top());
  192.                 st.pop();
  193.         }
  194.         char x = st.top();
  195.         while(!tmpst.empty()){
  196.                 st.push(tmpst.top());
  197.                 tmpst.pop();
  198.         }
  199.         return x;
  200. }
  201.  
  202. /* 进行算符优先分析 */
  203. bool check(){
  204.         string s;
  205.         char t;
  206.         bool flag = false;
  207.  
  208.         while(!st.empty())st.pop();
  209.         st.push('#');
  210.         while((s=next())!="\0"){
  211.                 if(isNumber(s)){        //      如果串是无符号整数 则把它看成i
  212.                         t = 'i';
  213.                         stnum.push(toInt(s));
  214.                 }else{        //        否则当成操作符
  215.                         t = s[0];
  216.                 }
  217.                 char h = st.top();
  218.                 char b = first();
  219.                 bool f;
  220.                 switch(opv[ophash[first()]][ophash[t]]){
  221.                 case 1:  //       大于则归约
  222.                         s = ""; f = false;
  223.                         do{
  224.                                 s.append(1, h);
  225.                                 st.pop();
  226.                                 if(out(s)){
  227.                                         s = "";
  228.                                         break;
  229.                                 }
  230.                                 if(st.empty())break;
  231.                                 h = st.top();
  232.                                 f = first()!=h;
  233.                         }while(f||opv[ophash[first()]][ophash[b]]!=3);    //        直到第一个<关系出现
  234.                         if(s==""){
  235.                                 top--;
  236.                                 flag = true;
  237.                                 break;
  238.                         }
  239.                         //      不能归约则报错
  240.                         if(!out(s)){
  241.                                 if(t=='#'&&st.size()==1&&s=="E")return true;
  242.                                 if(!flag){
  243.                                         return false;
  244.                                 }else{
  245.                                         for(int i = s.size()-1; i>=0; i--) st.push(s[i]);
  246.                                         st.push(t);
  247.                                         flag = false;
  248.                                 }
  249.                         }else{
  250.                                 top--;
  251.                                 flag = true;
  252.                         }
  253.                         break;
  254.                 case 2:  //       等于
  255.                         if(t=='#'){     //   输入是# 则检测是否正常结束
  256.                                 if(top<str.size()-1)return false;
  257.                                 return true;
  258.                         }
  259.                                         //      否则移进
  260.                 case 3:  //       小于则移进
  261.                         st.push(t);
  262.                         flag = false;
  263.                         break;
  264.                 case 0:  //       无关则报错
  265.                         return false;
  266.                 }
  267.         }
  268.  
  269.         return true;
  270. }
  271.  
  272. int main(){
  273.         init();
  274.  
  275.         freopen("test2.txt", "r", stdin);
  276.  
  277.         while(cin>>str){
  278.                 if(str == "exit")break;
  279.                 divzero = false;
  280.                
  281.                 cout<<str<<endl;
  282.  
  283.                 top = 0;
  284.  
  285.                 if(check()){        //  若合法则输出计算结果
  286.                         if(!divzero){
  287.                                 cout<<"正确"<<endl
  288.                                         <<"结果是"<<stnum.top()<<endl;
  289.                         }else{
  290.                                 cout<<"除零异常!"<<endl;
  291.                         }
  292.                 }else{        //        非法提示
  293.                         cout<<"错误"<<endl;
  294.                 }
  295.                
  296.                 cout<<"===================================="<<endl;
  297.         }
  298.  
  299.         return 0;
  300. }

 

 

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter