ALEX'S BLOG OF EVERYTHING

Equation Parsing with Lua

FFFFFFFFFFFFFFFF


	const std::unordered_set<std::string> mathlib_items = {
		"sin",
		"cos",
		"tan",
		"asin",
		"acos",
		"atan",
		"abs",
		"exp",
		"log",
		"sqrt",
		"floor",
		"ceil",
		"pi"
	};


	std::vector<std::string> splitTokens(const std::string& str)
	{
		std::vector<std::string> result;
		char token[10] = { '\0' };
		size_t toklen = 0;

		for (const char c : str)
		{
			switch (c)
			{
			case '(': case ')': case '+': case '-': case '*': case '/': case ',': case ' ':
				if (toklen > 0)
				{
					result.push_back(token);
					memset(token, '\0', 10);
					toklen = 0;
				}

				token[0] = c;
				result.push_back(token);
				token[0] = '\0';
				break;

			default:
				token[toklen++] = c;
				break;
			}
		}

		if (toklen > 0)
			result.push_back(token);

		return result;
	}


	bool FunctionGraph::setFunction(const std::string& str)
	{
		std::vector<std::string> tokens = splitTokens(str);

		for (auto& t : tokens)
		{
			if (t == "ln")
				t = "log";
			if (mathlib_items.find(t) != mathlib_items.end())
				t = "math." + t;
		}

		bool sigma = false;
		int commacount = 0;
		int parenscount = 0;
		for (auto& t : tokens)
		{
			if (t == "sigma")
				sigma = true;

			if (sigma)
			{
				if (t == ",")
				{
					if (++commacount == 3)
						t += " function (n) return ";
				}
				if (t == ")")
				{
					if (--parenscount == 0)
					{
						t = " end" + t;
						sigma = false;
					}
				}
				if (t == "(")
					parenscount++;
			}
		}

		bool integral = false;
		commacount = 0;
		parenscount = 0;
		for (auto& t : tokens)
		{
			if (t == "int")
				integral = true;

			if (integral)
			{
				if (t == ",")
				{
					if (++commacount == 2)
						t += " function (t) return ";
				}
				if (t == ")")
				{
					if (--parenscount == 0)
					{
						t = " end" + t;
						integral = false;
					}
				}
				if (t == "(")
					parenscount++;
			}
		}

		std::string funcstr = "require(\"stdlib\")\n\nfunction func(x)\n\treturn ";
		for (const auto& t : tokens)
			funcstr += t;
		funcstr += "\nend\n";

		//std::cout << funcstr << '\n';

		lua_pushnumber(L, 2.7182818);
		lua_setglobal(L, "e");

		if (lua_isvalid(L, luaL_dostring(L, funcstr.c_str())))
			return true;

		return false;
	}


	double FunctionGraph::operator()(double x) const
	{
		lua_getglobal(L, "func");
		lua_pushnumber(L, static_cast<float>(x));
		lua_call(L, 1, 1);

		return lua_tonumber(L, -1);
	}