作为演示如何从 中获取 AST GroovyRecognizer
,并避免尝试使用正则表达式解析语言,您可以在 Groovy 中执行此操作:
import org.codehaus.groovy.antlr.*
import org.codehaus.groovy.antlr.parser.*
def code = '''
// gremlin.groovy
def warm_cache() {
for (vertex in g.getVertices()) {
vertex.getOutEdges()
}
}
def clear() {
g.clear()
}
'''
def ast = new GroovyRecognizer( new GroovyLexer( new StringReader( code ) ).plumb() ).with { p ->
p.compilationUnit()
p.AST
}
while( ast ) {
println ast.toStringTree()
ast = ast.nextSibling
}
打印出 AST 中每个GroovySourceAST节点的 AST,为您提供(对于本示例):
( METHOD_DEF MODIFIERS TYPE warm_cache PARAMETERS ( { ( for ( in vertex ( ( ( . g getVertices ) ELIST ) ) ( { ( EXPR ( ( ( . vertex getOutEdges ) ELIST ) ) ) ) ) )
( METHOD_DEF MODIFIERS TYPE clear PARAMETERS ( { ( EXPR ( ( ( . g clear ) ELIST ) ) ) )
你应该可以用 Clojure 的 java interop 和 groovy-all jar 文件做同样的事情
编辑
要获得更多信息,您只需深入了解 AST 并稍微操作输入脚本。while
将上述代码中的循环更改为:
while( ast ) {
if( ast.type == GroovyTokenTypes.METHOD_DEF ) {
println """Lines $ast.line to $ast.lineLast
| Name: $ast.firstChild.nextSibling.nextSibling.text
| Code: ${code.split('\n')[ (ast.line-1)..<ast.lineLast ]*.trim().join( ' ' )}
| AST: ${ast.toStringTree()}""".stripMargin()
}
ast = ast.nextSibling
}
打印出来:
Lines 4 to 8
Name: warm_cache
Code: def warm_cache() { for (vertex in g.getVertices()) { vertex.getOutEdges() } }
AST: ( METHOD_DEF MODIFIERS TYPE warm_cache PARAMETERS ( { ( for ( in vertex ( ( ( . g getVertices ) ELIST ) ) ( { ( EXPR ( ( ( . vertex getOutEdges ) ELIST ) ) ) ) ) )
Lines 10 to 12
Name: clear
Code: def clear() { g.clear() }
AST: ( METHOD_DEF MODIFIERS TYPE clear PARAMETERS ( { ( EXPR ( ( ( . g clear ) ELIST ) ) ) )
显然,该Code:
部分只是重新连接在一起的行,因此如果粘贴回 groovy 中可能无法正常工作,但它们可以让您了解原始代码......