用PHP实现DSL

Jes*_*nch 8 php dsl

我有个主意.我想通过编写一些简单的代码,让我们的客户能够根据一些变量指定定价:

if customer.zip is "37208"
   return 39.99
else
   return 59.99
Run Code Online (Sandbox Code Playgroud)

在我的代码中,我会做这样的事情:

try {
   $variables = array('customer' => array('zip' => '63901'));
   $code = DSL::parse(DSL::tokenize($userCode))
   $returnValue = DSL::run($code, $variables);
} catch (SyntaxErrorException $e) {
   ...
}
Run Code Online (Sandbox Code Playgroud)

我想我想要的是在PHP中创建一个简单的DSL,它允许我们的客户在设置定价时具有很大的灵活性,而无需让我们为每个案例编写代码.

这是基本的想法:

  1. 我会提供一系列变量和客户编写的代码.
  2. 解析器将使用提供的变量评估用户编写的代码,并将客户返回的值返回给我.它会抛出任何语法错误等异常.
  3. 然后我将在应用程序的正常逻辑中使用返回的值.

那么你知道在PHP中构建一个简单的DSL的任何资源或框架吗?任何想法从哪里开始?

谢谢!

tro*_*skn 7

除了技术限制之外,你可能想要真正三思而后行(我推测)给非程序员提供这种编程能力.他们可能会以完全不可预测的方式陷入困境,你将成为必须清理混乱的人.至少要通过大量测试来保护它.也可能是法律术语.

但你问了一个问题,所以我会试着回答这个问题.内部风格DSL(大多数人使用单词DSL时的意思)和外部风格DSL(更像是迷你语言)之间存在着区别.Ruby以其语法为内部风格的DSL提供自我而闻名.另一方面,PHP在这方面相当糟糕.

也就是说,你仍然可以在PHP中做一些事情 - 最简单的可能只是编写一个函数库,然后让你的客户使用该库在纯PHP中编写代码.您当然必须审核代码,但它会提供使用现有运行时的所有好处.

如果这不够花哨,你将不得不深入挖掘重物.首先,你需要一个解析器.如果你知道如何,他们可以很容易手写,但除非你被迫在学校写一个或你有一个奇怪的爱好写这种东西只是为了好玩(我这样做),它可能会带你一个一点工作.解析器的基本组件是标记器和某种自动机(状态机),它将标记排列成树结构(AST).

获得解析后的结构后,需要对其进行评估.由于这是一个DSL,功能的数量是有限的,性能可能不是你最关心的问题,你可以在AST周围编写一些面向对象的代码并保留它.否则,您可以选择编写某种解释器或将其交叉编译为另一种格式(PHP将是一个明显的选择).

这一过程中棘手的部分主要是处理边缘情况,例如语法错误,并向用户报告有意义的内容.再次,只是给予访问PHP的子集,将免费提供给您,所以首先考虑.