Groovy DSL: how can I overload any () in Groovy when I create an internal DSL

I am creating an Internal DSL and I would overload any () method from DefaultGroovyMethods.

class RulesProcessor {

}

Any live cell with fewer than two live neighbours dies

      

The last line is my DSL. I tried propertyMissing, methodMissing, create my Any class, RulesProcessor.metaClass.any, DefaultGroovyMethods.metaClass.any but they don't work.

How can I write code to accept my DSL? Only the first step with the "Any" word gets complicated for me.

+3


source to share


1 answer


If you can put it in a closure, just delegate it to the object that responds to the method, any

or as in my example invokeMethod

:

class Dsl {
  def params = []
  def invokeMethod(String method, args) {
    params << [method, args]
    this
  }

  def propertyMissing(String prop) { prop }
}


a = {
  any live cell with fewer than two live neighbours dies
}


dsl = new Dsl()
a.delegate = dsl
a()

assert dsl.params == [
  ['any',   ['live']],
  ['cell',  ['with']],
  ['fewer', ['than']],
  ['two',   ['live']],
  ['neighbours', ['dies']],
]

      

If you are reading a script from a file, you need a method explicitly called any

:



import org.codehaus.groovy.control.CompilerConfiguration

class Dsl {
  def params = []
  def invokeMethod(String method, args) {
    params << [method, args]
    this
  }

  def any(param) { invokeMethod('any', [param]) }

  def propertyMissing(String prop) { prop }
}

code = 'any live cell with fewer than two live neighbours dies'

parsed = new GroovyShell(
    getClass().classLoader, 
    new Binding(), 
    new CompilerConfiguration(scriptBaseClass : DelegatingScript.class.name)
).parse( code )

dsl = new Dsl()

parsed.setDelegate( dsl )
parsed.run()

assert dsl.params == [
  ['any',   ['live']],
  ['cell',  ['with']],
  ['fewer', ['than']],
  ['two',   ['live']],
  ['neighbours', ['dies']],
]

      

Kudos to mrhaki at CompilerConfiguration.

+2


source







All Articles