我有一个想法。我想通过编写一些像这样的简单代码,让我们的客户能够根据许多变量指定定价:
if customer.zip is "37208"
return 39.99
else
return 59.99
在我的代码中,我会做这样的事情:
try {
$variables = array('customer' => array('zip' => '63901'));
$code = DSL::parse(DSL::tokenize($userCode))
$returnValue = DSL::run($code, $variables);
} catch (SyntaxErrorException $e) {
...
}
我想我想要的是用 PHP 创建一个简单的 DSL,让我们的客户在设置定价方面有很大的灵 active ,而不必让我们为每个案例编写代码。
基本思路是:
那么您是否知道在 PHP 中构建简单 DSL 的任何资源或框架?有什么想法从哪里开始吗?
谢谢!
最佳答案
撇开技术限制不谈,您可能真的要三思而后行,将这种编程能力赋予(我想)非程序员。他们可能会以完全不可预测的方式搞砸,而您将成为必须收拾残局的人。至少通过大量测试来保护它。可能还有法律术语。
但是你问了一个问题,所以我会尽力回答这个问题。内部风格 DSL(大多数人使用 DSL 这个词时的意思)和外部风格 DSL(更像是一种迷你语言)之间存在区别。 Ruby 以拥有适合内部风格 DSL 的语法而闻名。另一方面,PHP 在这方面非常糟糕。
也就是说,您仍然可以用 PHP 做一些事情 - 最简单的可能就是编写一个函数库,然后让您的客户使用该库以纯 PHP 编写代码。您当然必须审核代码,但它会提供使用现有运行时的所有好处。
如果这还不够花哨,您将不得不深入研究繁重的内容。首先你需要一个解析器。如果你知道如何,它们可以很容易地手写,但除非你在学校被迫写一个,或者你有一种奇怪的爱好,即为了好玩而写那种东西(我有),否则你可能会花很多时间一点工作。解析器的基本组件是标记器和某种自动机(状态机),它将标记排列成树结构(AST)。
一旦你有你的解析结构,你需要评估它。由于这是一个 DSL,功能的数量是有限的,性能可能不是您最关心的问题,您可以围绕 AST 编写一些面向对象的代码并将其留在那里。否则,您可以选择编写某种解释器或将其交叉编译为另一种格式(PHP 将是一个明显的选择)。
整个过程中棘手的部分主要是处理边缘情况,例如语法错误并向用户报告一些有意义的事情。再次重申,只需授予对 PHP 子集的访问权限,就可以免费为您提供该子集,因此请先考虑这一点。
关于php - 在 PHP 中实现 DSL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13940641/
我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)
我需要在RubyonRails中实现无向图G=(V,E)并考虑构建一个Vertex和一个Edge模型,其中Vertex有_多条边。由于边恰好连接两个顶点,您将如何在Rails中执行此操作?您是否知道任何有助于实现此类图表的gem或库(对重新发明轮子不感兴趣;-))? 最佳答案 不知道有任何现有库在ActiveRecord之上提供图形逻辑。您可能必须实现自己的Vertex、EdgeActiveRecord支持的模型(请参阅Rails安装的rails/activerecord中的vertex.rb和edge.rb/test/fixtur
我正在尝试找出如何为我的Ruby项目创建一种“无类DSL”,类似于在Cucumber步骤定义文件中定义步骤定义或在Sinatra应用程序中定义路由。例如,我想要一个文件,其中调用了我的所有DSL函数:#sample.rbwhen_string_matches/hello(.+)/do|name|call_another_method(name)end我认为用我的项目特有的一堆方法污染全局(内核)命名空间是一种不好的做法。因此方法when_string_matches和call_another_method将在我的库中定义,并且sample.rb文件将以某种方式在我的DSL方法的上下文中
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道rubyonrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim
我haveaclass它公开了一个字符串值和一个int值(分别是命令输出和退出代码)。除了通过to_s和to_i公开它们之外,我还使用to_str和to_int,如下所示:classStatusdefto_s@outputendalias:to_str:to_sdefto_i@status.exitstatusendalias:to_int:to_iend我的想法是能够在尽可能多的情况下使用这个对象。将其强制转换为字符串或整数会增加可用性。例如,我可以将对象与字符串连接起来:a_string="Outputwas:"+results(我想用这个作为int强制转换的例子,但是Fixnum
我一直在尝试在Ruby中实现BinaryTree类,但我得到了stackleveltoodeep错误,尽管我似乎没有在该特定代码段中使用任何递归:1.classBinaryTree2.includeEnumerable3.4.attr_accessor:value5.6.definitialize(value=nil)7.@value=value8.@left=BinaryTree.new#stackleveltoodeephere9.@right=BinaryTree.new#andhere10.end11.12.defempty?13.(self.value==nil)?true:
来自Java,我正在尝试在Ruby中实现LinkedList。我在Java中实现它的通常方法是有一个名为LinkedList的类和一个名为Node的私有(private)内部类,其中LinkedList的每个对象都作为Node对象。classLinkedListprivateclassNodeattr_accessor:val,:nextendend我不想将Node类暴露给外部世界。然而,通过Ruby中的这个设置,我可以使用这个访问LinkedList类之外的私有(private)Node类对象-node=LinkedList::Node.new我知道,在Ruby1.9中,我们可以使用
我正在尝试为文件操作编写自己的DSL,只是为了学习。我的目标是让它易于理解和编码。这里有3种将字符串附加到database.yml的替代方法:1.append("windows").to("database.yml")2.append(string:"windows").to(file:"database.yml")3.append_string("windows").to_file("database.yml")4.append_string"windows",to_file:"database.yml"5.appendstring:"windows",to_file:"databa
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它
我一直在尝试用Ruby实现Luhn算法。我一直在执行以下步骤:该公式根据其包含的校验位验证数字,该校验位通常附加到部分帐号以生成完整帐号。此帐号必须通过以下测试:从最右边的校验位开始向左移动,每第二个数字的值加倍。将乘积的数字(例如,10=1+0=1、14=1+4=5)与原始数字的未加倍数字相加。如果总模10等于0(如果总和以零结尾),则根据Luhn公式该数字有效;否则无效。http://en.wikipedia.org/wiki/Luhn_algorithm这是我想出的:defvalidCreditCard(cardNumber)sum=0nums=cardNumber.to_s.s