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);
}