Groovy vs JRuby – 4:4

Alright. Funny enough. After another day with both, Groovy and JRuby, I would say Groovy did catch up. Here’s the whole story:

After accepting the fact that Groovy is very OO, I found a way to add my plugin’s configuration folder to the classpath and load additional stuff from there. This way I was able to write a simple LexerAdapter and LexerBase class in Groovy. The resulting lexer specification looks something like this:

import jfun.parsec.*
import jfun.parsec.tokens.*
import jfun.parsec.pattern.*

class MyRubySyntax extends jparsec.LexerBase
    {
    protected void setup()
        {
        def s_block_open = Scanners.isPattern( Patterns.regex( /(?m:^=begin)/ ), "BLOCK_OPEN" )
        def s_block_close = Scanners.isPattern( Patterns.regex( /(?m:^=end$)/ ), "BLOCK_CLOSE" )
        def s_block_commented = Scanners.anyChar()

        scanner "DOC_COMMENT",	        Scanners.isBlockComment( s_block_open, s_block_close, s_block_commented )

        regex "LINE_COMMENT",           /(?m:#.*$)/
        regex "SPECIAL_QUOTED_STRING",  /%[qQ]\{(?:(?:\\\})|(?:[^\}]))*\}/
        (..snip..)
        regex "IDENTIFIER",             /\b[a-z]\w*\b/
        regex "NUMBER",                 /\b(?:0x[0-9A-Fa-f]+)|(?:[0-9]+(?:\.[0-9]+)?)\b/
        }
    }

return new MyRubySyntax().lexer()

This is still a lot uglier than the (J)Ruby version. But the thing is: This compiles to Java byte code. And with the LexerAdapter implemented in the scripting part of the system this is significant. To remedy the situation for JRuby I still have the pure Java LexerAdapter available on the classpath. (More on this in the example configuration files.)

What I didn’t figure out: There’s a nice use (“with”) codeword in Groovy. But it didn’t really work. It should provide functionality to merge a module’s methods into a closure/block of code. This way I wouldn’t have to create this MyRubySyntax class, etc and could get away with something like this:

use ( jparsec.LexerBase )
{
    (..snip..)
    regex "NUMBER",                 /\b(?:0x[0-9A-Fa-f]+)|(?:[0-9]+(?:\.[0-9]+)?)\b/

    return lexer()
}

But I guess I still don’t understand Groovy good enough. It has quite a few little quirks.

Another of those would be that I cannot use closures in all the places that should allow them. Here’s one:

for ( idx in 0..myCache.size() - 1 )
{
    def token = myCache.get( idx )
    if ( aStartOffset >= token.start && aStartOffset < token.end ) return token
    if ( aStartOffset < token.end ) return token
}

With myCache being an ArrayList I would expect myCache.each { token -> ... } to work. Somehow I get a compiler error mumbling about 1 parameter where 2 are expected or something like that. Weird.

Anyway, with the compiled approach of Groovy it suddenly feels a lot more practicable for the intended purpose of lexer adaptation and specification. Nice.

With the next step planned - extending the plugin to allow simple parser functionality - I assume JRuby will become even less an option. But it should be helpful to get some quick results. Especially for the Ruby configuration of the plugin. I intend to use one of the existing pure Ruby parsers for the Ruby syntax. We'll see how that turns out..

tfdj

One Response to “Groovy vs JRuby – 4:4”

  1. January 2nd, 2007 | 9:21 am

    Hello! Good posts so far. JRuby will soon compile to bytecode, and we already have some prototype work done on the compiler that are very promising. We also currently can’t extend Java classes, but that will likely change before the next release. We’d love to hear more about things you think would make JRuby a better contender. So far everything you’ve called out as a problem is on the roadmap to be remedied soon.

Leave a reply