我正在用Groovy開發一個不錯的小DSL。groovy命令表達式如何做嵌套表達式?
我真的很喜歡高階函數的Command Expression。
很少的代碼,我可以這樣做:
timerange = from today to tomorrow
這其實是
timerange = from(today).to(tomorrow)
,但現在我願意做這樣的事情:
difference = difference from today to tomorrow
這將導致像這樣:
difference = difference(from(today).to(event.start))
我總是得到錯誤:
No such property: from for class: Script1.
下面是測試類主要方法。第三個斷言失敗:
任何人都可以告訴我一個例子如何做到這一點?
import groovy.time.DatumDependentDuration /** * Created by IntelliJ IDEA. * User: nils * Date: 2/18/12 * Time: 4:41 PM */ class SimpleTest { def static today = new Date(); def static tomorrow = new Date() + 1; def loadDSL(Closure cl) { cl.delegate = this return cl() } def toMethod = { date -> [to: { timeThing -> if (timeThing instanceof Date) { use(groovy.time.TimeCategory) { (date..timeThing) //return Range } } }] } def from(Date date) { toMethod(date) } def difference(Range range) { range.size() //for the sake of simplicity } static void eval(dslContent, assertion) { SimpleTest runner = new SimpleTest() def dsl = """ run { ${dslContent} } """ def binding = new Binding() binding.run = { Closure cl -> runner.loadDSL(cl) } binding.today = today; binding.tomorrow = tomorrow; GroovyShell shell = new GroovyShell(binding) shell.evaluate(dsl) assert binding.variables.x == assertion } static void main(String[] args) { eval("x = from today to tomorrow", (today..tomorrow)) eval("x = difference(from(today).to(tomorrow))", 2) eval("x = difference from today to tomorrow ", 2) } }
這下面是完整的例外:
Exception in thread "main" groovy.lang.MissingPropertyException: No such property: from for class: Script1 at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:50) at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:49) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:231) at Script1$_run_closure1.doCall(Script1.groovy:3) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141) at Script1$_run_closure1.doCall(Script1.groovy) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112) at SimpleTest.loadDSL(SimpleTest.groovy:17) at SimpleTest$loadDSL.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42) at SimpleTest$loadDSL.call(Unknown Source) at SimpleTest$_eval_closure2.doCall(SimpleTest.groovy:48) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883) at groovy.lang.MetaClassImpl.invokePropertyOrMissing(MetaClassImpl.java:1099) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1055) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:883) at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141) at Script1.run(Script1.groovy:2) at groovy.lang.GroovyShell.evaluate(GroovyShell.java:580) at groovy.lang.GroovyShell.evaluate(GroovyShell.java:618) at groovy.lang.GroovyShell.evaluate(GroovyShell.java:589) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrap.invoke(PogoMetaMethodSite.java:247) at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:64) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) at SimpleTest.eval(SimpleTest.groovy:54) at SimpleTest$eval.callStatic(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:50) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:157) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:169) at SimpleTest.main(SimpleTest.groovy:62)
大聲笑,這是從一個時間,當我認爲DSL可以完全人類可讀的任何人。但是我錯了。 – 2014-10-13 06:51:27
這不會對我有用,因爲「單詞序列」必須像英語一樣...... – 2014-10-13 07:59:38
我想你會需要去爲你自己的antlr。但即使如此,你可能正在尋找[自然語言解析器](http://nlp.stanford.edu/software/lex-parser.shtml) – Will 2014-10-13 12:59:48