class TreeMLBuilder { def sb = new StringBuilder() def declarations = [:] def methodMissing(String name, args) { println "methodMissing $name, args : $args, length : $args.length" switch (name) { case 'tree': assert args.length == 1 && args[0] instanceof Closure args[0].delegate = this sb.append '' args[0]() sb.append '' break case 'declarations': assert args.length == 1 && args[0] instanceof Closure args[0].delegate = this sb.append '' args[0]() sb.append '' break case 'attributeDecl': assert args.length == 1 && args[0] instanceof HashMap && args[0].size() == 2 assert args.name && args.type declarations."${args.name[0]}" = args.type[0] sb.append "" break case 'branch': assert args.length == 1 && args[0] instanceof Closure args[0].delegate = this sb.append '' args[0]() sb.append '' break case 'leaf': assert args.length == 1 && args[0] instanceof Closure args[0].delegate = this sb.append '' args[0]() sb.append '' break default: // Dans le contexte d'une branche ou d'un noeud println "default : $name" if (declarations."$name") { assert args.length == 1 sb.append "" } } } def build() { sb.toString() } } def builder = new TreeMLBuilder() builder.tree { declarations { attributeDecl(name: 'nom', type: 'String') } branch { nom 'Groovy' branch { nom 'Language' branch { nom 'Literals' leaf { nom 'Strings / RegEx' } leaf { nom 'Lists / Maps / Ranges' } leaf { nom 'Closures' } } branch { nom 'Every is an object' leaf { nom 'Object operators' } leaf { nom 'Multimethods' } leaf { nom 'GroovyBeans' } } branch { nom 'Meta Object Protocol' leaf { nom 'Method interception' } leaf { nom 'Category use (Mixin)' } leaf { nom 'Dynamic methods and properties' } } branch { nom 'Control Flow' leaf { nom 'Groovy Truth' } leaf { nom 'Switch' } leaf { nom 'Advanced operators' } leaf { nom 'GPath' } leaf { nom 'Iterations' } } branch { nom 'Execution' leaf { nom 'Scriptablility' } leaf { nom 'Hot class reloading' } } } branch { nom 'Library' leaf { nom 'SQL' } leaf { nom 'XML' } leaf { nom 'Swing' } leaf { nom 'Ant' } leaf { nom 'Templates' } leaf { nom 'Groovlets' } leaf { nom 'Stubs and Mocks' } } branch { nom 'GDK' leaf { nom 'Object Inspection' } branch { nom 'Groovy-aware methods' leaf { nom 'Strings' } leaf { nom 'Lists' } leaf { nom 'Maps' } } leaf { nom 'Files and I/O' } leaf { nom 'Threads and Processes' } } } } builder.build()