c++ - 如何存储多次插件解析的函数表达式?

标签 c++ parsing

如题所示,我的程序需要多次读取多个函数表达式并插入不同的变量。每次我需要插入一个新值时都重新解析整个表达式肯定太丑陋了,所以我需要一种方法来存储解析后的表达式。

表达式可能类似于 2x + sin(tan(5x)) + x^2。哦,还有非常重要的一点——我使用的是 C++。

目前我有三个想法,但都不是很优雅:

  1. 将 S 表达式存储为树;通过重复评估它。它可能 是处理这个问题的老派方法,但它很丑陋,我会 必须处理不同数量的参数(例如 + 与 sin)。

  2. 使用 boost::lambda 编写匿名函数。它可能工作得很好, 但我个人不喜欢提升。

  3. 编写一个小的 python/lisp 脚本,使用它的原生 lambda 表达式并用 IPC 调用它...好吧,这太疯狂了。

那么,有什么想法吗?

更新:

我没有尝试实现对括号和只有一个参数的函数的支持,比如 sin()

我先尝试了第二种方式;但我没有使用 boost::lambda,而是 gcc 的一个特性,它可以用来创建(假的)匿名函数,我从 here 中找到了它。 .生成的代码有 340 行,并且由于范围界定和堆栈的细微问题而无法正常工作。

使用 lambda 无法使它变得更好;而且我不知道它是否可以正确处理范围界定。很抱歉没有测试 boost::lambda。

将解析后的字符串存储为 S 表达式肯定可行,但实现会更长——可能约 500 行?我的项目不是那种几万行代码的庞然大物,花那么大的精力去维护那种不常使用的扭曲代码,似乎不是什么好主意。

所以最后我尝试了第三种方法——太棒了! Python 脚本只有 50 行,非常简洁易读。但是,另一方面,它也会使 python 成为我的程序的先决条件。在 *nix 机器上还不错,但在 Windows 上……我想非程序员安装 Python 会非常痛苦。 lisp 也是如此。

不过,我最终的解决方案是将 bc 作为子进程打开。在大多数情况下,这可能是一个糟糕的选择,但是,它很适合我。

另一方面,对于仅在 *nix 下工作或已经有 python 作为先决条件的项目,如果表达式足够简单可以用手写解析器解析,我个人推荐第三种方法。如果它非常复杂,就像 Hurkyl 所说的,您可以考虑创建一种迷你语言。

最佳答案

为什么不使用专门为这种目的而设计的脚本语言呢?有几种这样的语言在流传,但我的经验是使用 lua。

我“一直”用lua来做这种事。嵌入和解析这样的表达式的代码非常小。它看起来像这样(未经测试):

std::string my_expression = "2*x + math.sin( math.tan( x ) ) + x * x";

//Initialise lua and load the basic math library.
lua_State * L = lua_open();
lua_openmath(L);

//Create your function and load it into lua
std::string fn = "function myfunction(x) return "+my_expression+"end";
luaL_dostring( L, fn.c_str(), fn.size() );

//Use your function

for(int i=0; i<10; ++i)
{
  // add the function to the stack
  lua_getfield(L, LUA_GLOBALSINDEX, "myfunction");
  // add the argument to the stack 
  lua_pushnumber(L, i);
  // Make the call, using one argument and expecting one result.
  // stack looks like this : FN ARG
  lua_pcall(L,1,1)
  // stack looks like this now : RESULT
  // so get the result and print it 
  double result = lua_getnumber(L,-1);
  std::cout<<i<<" : "<<result<<std::endl;
  // The result is still on the stack, so clean it up.
  lua_pop(L,1);
}

关于c++ - 如何存储多次插件解析的函数表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8627818/

相关文章:

C++:如何制作一个简单的字典?

c++ - Wxwidgets回调

string - 解析具有不明确数据的地址

c++ - 促进规则的精神转变

c++ - 在 C++ 中调用数组时删除运算符行为?

c++ - 函数运算符的 undefined reference >>

c++ - 如何标记 C++ 源代码文件(转换为标记序列)?

Swift 2.0 和 3.0 中的 Json 解析

c# - 将字符串解析为 Unity3D 中的代码 (C#)

javascript - 如何使用 lxml 从文本区域获取 javascript 代码?