#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;
}
}
}
}
LR文法四则运算器
最新推荐文章于 2022-05-02 23:56:57 发布