zoukankan      html  css  js  c++  java
  • LR--用栈实现移进--归约分析(demo)

    1.考虑文法

    (E->E+E)
    (E->E*E)
    (E->id)

    2.最右推导

    不难看出,这个文法是而二义的,所以有多个最右推导

    3.移进归约

    用一个栈存文法符号,用输入缓存区保存要分析的输入串,用$标记栈底

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<string>
    #include<stack>
    using namespace std;
    stack<string> stk, tmp;
    string w;
    bool flag = false;
    int main(void) {
    	cin >> w;	//输入串
    	w += "$";	//加上标识符
    	printf("----------|----------|----------
    ");
    	printf("    栈    |   输入   |    动作  
    ");
    	printf("----------|----------|----------
    ");
    	int now = 0;	//当前扫描字符位置
    	while (!flag) {
    		now = 0;
    		if (stk.empty()) {	//如果一开始栈为空,直接移进符号
    			stk.push("$");
    			cout << "$         |";
    			cout.setf(ios::right);	//设置字符对其方式
    			cout.width(10);			//设置字符宽度
    			cout << w;
    			cout<< "|移进" << endl;
    			printf("----------|----------|----------
    ");
    			string tt;
    			if (w[now] == 'i') {	//移进符号为id
    				tt = "id";
    				now = 2;
    			}
    			else {					//移进符号不为id
    				tt = w[now];
    				now = 1;
    			}
    			stk.push(tt);			//将符号压入栈
    			w = w.substr(now, w.size() - now);	//丢弃已扫描的字符
    			continue;
    		}
    		while (!stk.empty()) {		//用两个栈来回倒,输出字符
    			tmp.push(stk.top());
    			stk.pop();
    		}
    		while (!tmp.empty()) {
    			cout << tmp.top();
    			stk.push(tmp.top());
    			tmp.pop();
    		}
    		if (stk.top() == "id") {	//E-->id归约,优先级最高
    			cout.width(10-stk.size());
    			cout << "|";
    			cout.setf(ios::right);	//设置字符对其方式
    			cout.width(10);			//设置字符宽度
    			cout << w;
    			cout<< "|按E-->id进行归约" << endl;
    			printf("----------|----------|----------
    ");
    			stk.pop();
    			stk.push("E");
    			continue;
    		}
    		if (w[now]=='$'&&stk.size() == 2 && stk.top() == "E") {		//接受状态
    			flag = true;
    			cout<< "        |         $|接受"<< endl;
    			printf("----------|----------|----------
    ");
    			continue;
    		}
    		if (w[now]!='$') {		//移进字符
    			string tp;
    			if (w[now] == 'i') {
    				tp = "id";
    				now = 2;
    			}
    			else {
    				tp = w[now];
    				now = 1;
    			}
    			cout.width(11 - stk.size());
    			cout << "|";
    			cout.setf(ios::right);	//设置字符对其方式
    			cout.width(10);			//设置字符宽度
    			cout << w;
    			cout<< "|移进" << endl;
    			printf("----------|----------|----------
    ");
    			stk.push(tp);
    			w = w.substr(now, w.size() - now);	//丢弃已扫描的字符
    			continue;
    		}
    		if (w[now] == '$'  &&!flag) {	//E-->E+E或者E-->E*E归约
    			string  tc;
    			tc = stk.top();
    			if (tc == "E")
    				stk.pop();
    			tc += stk.top();
    			if (stk.top() != "E") {
    				stk.pop();
    				tc += stk.top();
    				cout.setf(ios::right);	//设置字符对其方式
    				cout.width(9- stk.size());//设置字符宽度
    				cout << "|";
    				cout << "         $|";
    				cout << "按E-->"<<tc<<"归约" << endl;
    				printf("----------|----------|----------
    ");
    				stk.pop();
    				stk.push("E");
    			}
    		}
    	}
    	return 0;
    }
    

    4.Sample

    输入

    id*id+id
    

    5.To be continued.

  • 相关阅读:
    Google开源框架盒子模型之Android---<FlexboxLayout>(认知篇)
    Android Studio配置中AndroidAnnotations
    Android Studio分包引发的血案(App启动一直黑屏问题)
    Android Studio打包APK过大问题的研究
    Android WebView JS互调案例
    Eclipse版本android 65535解决方案(原理等同android studio现在的分包方式)
    Android MVP + 泛型,实现了友好VP交互及Activity潜在的内存泄露的优化
    mysql数据监控(db.odbc.select[])
    zabbix 默认消息
    zabbix 利用脚本发邮件(mail)
  • 原文地址:https://www.cnblogs.com/FlyerBird/p/9940723.html
Copyright © 2011-2022 走看看