• Groovy实现的字符串逻辑运算DSL - [自写]

    2007-12-31

    今天帮朋友写了一个小东西,主要是使用一个表达式,这个表达式支持逻辑运算,例如abc & def,这表示在一个字符串中如果同时有abc和def这两个子串,则返回true,否则返回false.

    最初想使用Antrl实现,不过Antrl没用过,得学习段时间才行,时间来不及了。

    我简单地用Groovy实现一个"DSL",可以利用Groovy语言本身的逻辑运算。

    先定义一下需要的表达式元素:
    & 与 
    | 或
    - 不存在 +存在
    () 逻辑分组
    '' 字符串用 ''引起来,如果字符串中有',需要转义一下,用\\'

    &,|,-,+可以使用操作符重载实现。

    一个复杂点儿的例子:

    ('abc' & 'def') | ('def' & ('fgh' | '123'))
    这个表达式表示:如果包括abc,那么就必须包括def;而如果有def,就必须有fgh或者123.

    实现如下:

    1.重载了 &,|,-和+ 这四个操作符

    2.使用categories(StringCategory)来限定上面那个操作符的作用范围

    3.PBinding,用于动态的查找被检测的字符串中是否包含表达式的子串

    class PBinding extends Binding{
            private String btext;
            public PBinding(String text){
                    btext = text;
            }
            public Object   getProperty(String name){
                    return btext.indexOf(name)>=0;
            }
            public Object   getVariable(String name){
                    return btext.indexOf(name)>=0;
            }
    }
    def isMatch(pattern,text){
    GroovyShell sc = new GroovyShell(new PBinding(text));
    def script="""
    class StringCategory {
        def static text = "${text}";
        def static check(def s){
            if(s instanceof String){
                    return (text.indexOf(s) >=0);  
            }else{
                    return s;
            }
        }  
        def static and(def s,def b){
            def left = check(s);
            def right = check(b);
            return left && right;
        }  
        def static or(def s,def b){
            def left = check(s);
            def right = check(b);
            return left ||  right;
        }  
        def static negative(def s){
     return !check(s)
        }

    def static positive(def s){
    return check(s)
    }

    }
    use(StringCategory){
    ${pattern} //在此执行表达式
    }
    """
    return sc.evaluate(script);
    }

    //test
    println "1. isMatch ${isMatch(+'abc','343/abc')}";
    println """2. isMatch ${isMatch("abc|\'def\'",'343/abc')}""";
    println """3. isMatch ${isMatch("'abc'&'def'",'defabc')}""";
    println """4. isMatch ${isMatch("('abc' & 'def') | ('def' & ('fgh' | '123'))
    ",'abcdef')}""";

    //called from java 

    //return isMatch(pattern,text)

    上面的代码可以嵌入到Java程序中去,在java代码里调用这个groovy脚本,并传入pattern和text两个参数就可以了。

    可以看得出,Groovy在写DSL的时候,还是很方便的。

    2007就要过去了,这也是我今年的最后一个blog了,祝大家新年快乐!:)


    收藏到:Del.icio.us




    评论

  • oh,sorry!should be http://www.chinagroovy.org/forum
  • 现在才看到你的blog,很不错,有一定深度。
    想必你也是Groovy的高手了,有时间的话,光临一下Groovy中国社区(http://www.chiangroovy.org/forum),希望你在这里能给更多的Groovier解惑 :)
    agilejava回复agile-boy说:
    呵呵,我对Groovy也只是熟悉我所要用的,其它也不熟悉 :)
    http://www.chiangroovy.org/forum,这个地址打不开啊,还没开张?
    2008-03-16 19:47:52

发表评论

您将收到博主的回复邮件
记住我