Пример #1
0
// 词法分析,解析表达式
bool ParseExpr(const string & expr, TokenVector & tokens)
{
	// 表达式的解析较简单,就不用状态机了,直接一个一个解析。。。
	int i = 0;
	Token token;
	string buffer;
	tokens.clear();
	while (i < expr.length())
	{
		// 空白跳过
		if (isblank(expr[i]))
		{
			++i;
			continue;
		}

		// 单个字符的操作符和括号
		if (expr[i] == '+' ||
			expr[i] == '-' ||
			expr[i] == '*' ||
			expr[i] == '/' ||
			expr[i] == '%' ||
			expr[i] == '^' ||
			expr[i] == '(' ||
			expr[i] == ')')
		{
			token.type = OP;
			if (expr[i] == '+') token.value.op = ADD;
			else if (expr[i] == '-') token.value.op = SUB;
			else if (expr[i] == '*') token.value.op = MUL;
			else if (expr[i] == '/') token.value.op = DIV;
			else if (expr[i] == '%') token.value.op = MOD;
			else if (expr[i] == '^') token.value.op = POW;
			else if (expr[i] == '(') token.value.op = LEFT;
			else if (expr[i] == ')') token.value.op = RIGHT;

			tokens.push_back(token);

			++i;
			continue;
		}
		// 整数或浮点数
		else if (isdigit(expr[i]))
		{
			buffer.clear();
			buffer += expr[i++];
			bool point = false;

			while (i < expr.length())
			{
				if (isdigit(expr[i]))
				{
					buffer += expr[i++];
				}
				else if (expr[i] == '.' && !point)
				{
					buffer += expr[i++];
					point = true;
				}
				else
				{
					break;
				}
			}
			if (point)
			{
				token.type = FLOAT;
				token.value.f = strtof(buffer.c_str(), NULL);
			}
			else
			{
				token.type = INT;
				token.value.i = strtoul(buffer.c_str(), NULL, 0);

			}
			tokens.push_back(token);
		}
		// 随机数
		else if (expr[i] == 'r')
		{
			token.type = RAND;
			token.value.i = 0;
			tokens.push_back(token);
			++i;
		}
		// 参数
		else if (expr[i] == 'x')
		{
			++i;
			buffer.clear();

			while (i < expr.length() && isdigit(expr[i]))
			{
				buffer += expr[i];
				++i;
			}
			if (buffer.empty())
			{
				return false;
			}

			token.type = ARG;
			token.value.index = strtoul(buffer.c_str(), NULL, 0);
			tokens.push_back(token);
			continue;
		}
		// > 或 >=
		else if (expr[i] == '>')
		{
			token.type = OP;
			++i;
			if (i < expr.length() && expr[i] == '=')
			{
				token.value.op = GE;
				++i;
			}
			else
			{
				token.value.op = GT;
			}
			tokens.push_back(token);
		}
		// < 或 <=
		else if (expr[i] == '<')
		{
			token.type = OP;
			++i;
			if (i < expr.length() && expr[i] == '=')
			{
				token.value.op = LE;
				++i;
			}
			else
			{
				token.value.op = LT;
			}
			tokens.push_back(token);
		}
		// ==
		else if (i + 1 < expr.length() && expr[i] == '=' && expr[i + 1] == '=')
		{
			token.type = OP;
			token.value.op = EQ;
			tokens.push_back(token);
			i += 2;
		}
		// !=
		else if (i + 1 < expr.length() && expr[i] == '!' && expr[i + 1] == '=')
		{
			token.type = OP;
			token.value.op = NE;
			tokens.push_back(token);
			i += 2;
		}
		// &&
		else if (i + 1 < expr.length() && expr[i] == '&' && expr[i + 1] == '&')
		{
			token.type = OP;
			token.value.op = AND;
			tokens.push_back(token);
			i += 2;
		}
		// ||
		else if (i + 1 < expr.length() && expr[i] == '|' && expr[i + 1] == '|')
		{
			token.type = OP;
			token.value.op = OR;
			tokens.push_back(token);
			i += 2;
		}
		else
		{
			return false;
		}
	}

	return true;
}
Пример #2
0
// 把解析好的表达式转换成逆波兰式
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;
}