LR文法四则运算器

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
char arr[100060];
struct Expr {
	int left;
	int right[5];
	int rightlen;
};
enum Sym {
	id = 0,
	addorminus,
	mulordiv,
	lb,
	rb,
	end,
	E,
	T,
	F,
	start,
};
enum RS {
	none,
	acc,
	shift,
	reduce,
};
Expr expr[7] = {
	{0,{0},0},
	{E,{E,addorminus,T},3},
	{E,{T},1},
	{T,{T,mulordiv,F},3},
	{T,{F},1},
	{F,{lb,E,rb},3},
	{F,{id},1},
};


struct rsTable{
	RS type;
	int state;
};

rsTable tb[12][9] = {
	{{shift,5},{none,0},{none,0},{shift,4},{none,0},{none,0},{shift,1},{shift,2},{shift,3}},
	{{none,0},{shift,6},{none,0},{none,0},{none,0},{acc,0},{none,0},{none,0},{none,0},},
	{{none,0},{reduce,2},{shift,7},{none,0},{reduce,2},{reduce,2},{none,0},{none,0},{none,0},},
	{{none,0},{reduce,4},{reduce,4},{none,0},{reduce,4},{reduce,4},{none,0},{none,0},{none,0},},
	{{shift,5},{none,0}, {none,0},{shift,4},{none,0},{none,0},{shift,8},{shift,2},{shift,3},},
	{{none,0},{reduce,6},{reduce,6},{none,0},{reduce,6},{reduce,6},{none,0},{none,0},{none,0},},
	{{shift,5},{none,0},{none,0},{shift,4},{none,0},{none,0},{none,0},{shift,9},{shift,3},},
	{{shift,5},{none,0},{none,0},{shift,4},{none,0},{none,0},{none,0},{none,0},{shift,10},},
	{{none,0},{shift,6},{none,0},{none,0},{shift,11},{none,0},{none,0},{none,0},{none,0},},
	{{none,0},{reduce,1},{shift,7},{none,0},{reduce,1},{reduce,1},{none,0},{none,0},{none,0},},
	{{none,0},{reduce,3},{reduce,3},{none,0},{reduce,3},{reduce,3},{none,0},{none,0},{none,0},},
	{{none,0},{reduce,5},{reduce,5},{none,0},{reduce,5},{reduce,5},{none,0},{none,0},{none,0},},
};
int pos = 0;
int NumVal;
int n;
int getNextToken() {
	NumVal = 0;
	if (isdigit(arr[pos])) {
		while (isdigit(arr[pos])) {
			NumVal *= 10;
			NumVal += arr[pos] - '0';
			pos++;
		}
		return id;
	}
	else {
		if (arr[pos] == '(') {
			pos++;
			return lb;
		}
		if (arr[pos] == ')') {
			pos++;
			return rb;
		}
		if (arr[pos] == '+') {
			pos++;
			return addorminus;
		}
		if (arr[pos] == '-') {
			pos++;
			return addorminus;
		}
		if (arr[pos] == '*' || arr[pos] == '/') {
			pos++;
			return mulordiv;
		}
		if (pos == n)return Sym::end;
	}
}
int calc(int l, int op, int r) {
	switch (op) {
	case '+':return l + r;
	case'-':return l - r;
	case'*':return l * r;
	case'/':return l / r;
	}
	return 0;
}

int main() {
	while (cin >> arr) {
		pos = 0;
		n = strlen(arr);
		struct Node {
			int state;
			Sym sym;
			char ch;
			int val;
		};
		vector<Node> st;
		auto show = [&]() {
			for (auto i : st) {
				
				switch (i.sym) {
				case start:cout << "$"; break;
				case Sym::end:cout << "$"; break;
				case E:
					cout << "E(" << i.val << ')'; break;
				case T:
					cout << "T(" << i.val << ')'; break;
				case F:
					cout << "F(" << i.val << ')'; break;
				case id:
					cout << i.val ; break;
				default:cout << i.ch ;
					break;
				}
				cout << i.state ;
			}
			cout << endl;
		};
		st.push_back({ 0,start,' ',0 });
		Sym sym = (Sym)getNextToken();
		while (true) {
			
			auto action = tb[st.back().state][sym];
			if (action.type == shift) {
				st.push_back({ action.state,sym,arr[pos - 1],NumVal });
				show();
				sym = (Sym)getNextToken();
				continue;
			}
			if (action.type == reduce) {
				auto reducesym = expr[action.state].left;
				auto pop_len = expr[action.state].rightlen;
				int rtnval;
				rtnval = (st.end() - 1)->val;
				if (action.state == 1 || action.state == 3) {
					auto exprleft = st.end() - pop_len;
					rtnval = calc(exprleft->val, (exprleft + 1)->ch, (exprleft + 2)->val);
				}
				if (action.state == 5) {
					rtnval = (st.end() - 2)->val;
				}

				while (pop_len) {
					st.pop_back();
					pop_len--;
				}
				auto gotoaction = tb[st.back().state][reducesym];
				st.push_back({ gotoaction.state,(Sym)reducesym,' ',rtnval });
				show();
				continue;
			}
			if (action.type == none) {
				cout << "error" << endl;
				break;
			}
			if (action.type == acc) {
				cout << st.back().val << endl;
				break;
			}
		}
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值