void gen_aux (const Grammar &g, const std::string &start, std::vector<std::string> &result) { TokenStack lifo; expand_aux (g, start, lifo); while (!lifo.empty()) { const std::string curr_word = lifo.top(); lifo.pop(); if (!bracketed (curr_word)) { result.push_back (curr_word); } else { expand_aux (g, curr_word, lifo); } } }
// 逆波兰式计算求值 bool CalcExpr(const TokenVector & input, const TokenVector & expr, Token & result) { TokenStack stack; TokenVector::const_iterator it = expr.begin(); for (; it != expr.end(); ++it) { if (it->type == INT || it->type == FLOAT || it->type == BOOL) { stack.push(*it); } else if (it->type == ARG) { if (it->value.index >= input.size()) return false; const Token & a = input[it->value.index]; if (a.type == INT || a.type == FLOAT || a.type == BOOL) { stack.push(a); } else { return false; } } else if (it->type == RAND) { Token a; a.type = INT; a.value.i = rand(); stack.push(a); } else if (it->type == OP) { if (stack.size() < 2) return false; Token a = stack.top(); stack.pop(); Token b = stack.top(); stack.pop(); Token c; if (GetValue(it->value.op, b, a, c)) { stack.push(c); } else { return false; } } } if (!stack.empty()) { result = stack.top(); return true; } else { return false; } }
// 把解析好的表达式转换成逆波兰式 bool ConvertExpr(const TokenVector & input, TokenVector & output) { TokenStack stack; output.clear(); TokenVector::const_iterator it = input.begin(); for (; it != input.end(); ++it) { if (it->type == OP) { // 左括号,直接压进操作符栈 if (it->value.op == LEFT) { stack.push(*it); } // 右括号,从栈里弹出操作符,直到碰到右括号 else if (it->value.op == RIGHT) { bool find_left = false; while (!stack.empty()) { if (stack.top().value.op == LEFT) { find_left = true; stack.pop(); break; } else { output.push_back(stack.top()); stack.pop(); } } if (!find_left) return false; } // 其它操作符,和栈顶操作符比较优先级 else { while (!stack.empty() && stack.top().value.op != LEFT && OPPriority(stack.top().value.op) >= OPPriority(it->value.op)) { output.push_back(stack.top()); stack.pop(); } stack.push(*it); } } // 非操作符直接输出 else { output.push_back(*it); } } while (!stack.empty()) { output.push_back(stack.top()); stack.pop(); } return true; }