2

我正在尝试为某些特定任务编写迷你 DSL。为此,我一直在尝试解决如下问题(不使用括号):

give me 5 like romanLetter    
give me 5 like word

其中第一行将返回“V”,第二行将返回“五”

我对第一部分的定义给了我 5看起来像这样

def give = { clos -> clos() } 
def me = { clos ->  [:].withDefault { it 
                println it} 
         }

然后给我 5张照片 5

问题是如何在右侧添加更多元类方法。例如

give me 5 like romanLetter -> prints V OR 
give me 5 like word -> prints five 

我的直觉是我将like定义为

Object.metaClass.like = {orth -> if (orth.equals("roman")){ println "V"} 
                                 else {println "five"} }

这个 metaClass 方法只有在左侧有一个返回值要应用时才有效,对吧?我尝试在左侧的所有闭包中添加一个 return 语句,但我总是收到

groovy.lang.MissingPropertyException: No such property: like 
for class: com.ontotext.paces.rules.FERulesScriptTest ... 

你知道我该怎么做吗?

=========================================

这是我所要求的应用程序。我想制定如下规则

add FEATURE of X opts A,B,C named Y

其中add是闭包,of,optsnamed是 MetaClass 方法(至少我是这么想的),X,A,B,C,Y是最有可能是字符串的参数,而FEATURE是 MetaClass 属性,或者是没有的闭包参数或带参数的闭包。

如果FEATURE不带参数,那么addFEATURE作为参数并返回一个值就足够了

Object.metaClass.of 将使用参数 X 执行

Object.metaClass.opts 将在带有参数 A、B、C 的 OF 值返回时执行

Object.metaClass.named 将在 opts 返回的带有参数 Y 的值上执行

这些元类方法中的每一个都将其参数设置为映射中的值,在调用命名时将其传递给 JAVA 方法。

我不确定这是解决此类问题的最佳解决方案,但目前在我看来是这样。问题是,如果 FEATURE 本身不是一个属性,而是一个带有参数的闭包(例如 feature1 ARG1)。然后

add feature1 ARG1 of X opts A,B,C named Y

这就是我坚持的情况。add feature1 ARG1给我 5部分,我正在尝试将其余部分添加到其中。

==================================================== ======

示例:我需要同时具备以下两项工作:

add contextFeature "text" of 1,2,3 opts "upperCase" named "TO_UPPER"
add length named "LENGTH"

在第一种情况下,通过解析规则,每当调用opts、named的每个元类方法时,我都会在以下映射中填写相应的值:

params = [feature: "text",
        of: 1,2,3,
        opts: "upperCase",
        named: "TO_UPPER"]

填充这张地图的那些,在解析命名时发生,我调用一个java方法setFeature(params.of,params.named,params.opts,params.feature)

在第二种情况下,长度预定义为长度 =“长度”,参数值将仅

params = [feature : length, 
    of: null,
    opts: null,
    named: "LENGTH"]

由于 of 为 null,将调用另一个 java 方法,即 addSurfaceFeature(params.feature, params.named)。第二种情况或多或少是直截了当的,但第一种是我无法管理的。

提前致谢!Ⅳ

4

1 回答 1

0

你可以做这种事情......这会让你接近吗?

def contextFeature( type ) {
  "FEATURE_$type"
}

// Testing

new IvitaParser().parse {
  a = add text of 1,2,3 opts "upperCase" named "TO_UPPER"
  b = add length named "LENGTH"
  c = add contextFeature( "text" ) of 1,2,3 opts "upperCase" named "TO_UPPER"
}

assert a == [feature:'text', of:[1, 2, 3], opts:'upperCase', named:'TO_UPPER']
assert b == [feature:'length', of:null, opts:null, named:'LENGTH']
assert c == [feature:'FEATURE_text', of:[1, 2, 3], opts:'upperCase', named:'TO_UPPER']

// Implementation

class IvitaParser {
  Map result

  def parse( Closure c ) {
    c.delegate = this
    c.resolveMethod = Closure.DELEGATE_FIRST
    c()
  }

  def propertyMissing( String name ) {
    name
  }

  def add( String param ) {
    result = [ feature:param, of:null, opts:null, named:null ]
    this
  }

  def of( Object... values ) {
    result.of = values
    this
  }

  def named( String name ) {
    result.named = name
    result
  }

  def opts( String opt ) {
    result.opts = opt
    this
  }
}

你甚至可以去掉定义中的引号:

a = add text of 1,2,3 opts upperCase named TO_UPPER
b = add length named LENGTH

由于 propertyMissing 方法只是将未知属性转换为其名称的字符串

于 2012-08-14T10:21:28.827 回答