JavaにPegDownというmarkdown変換用ライブラリがあって、Parboiledはそれで使っているパーサジェネレータ。
同じ人が開発している。
parboiled
https://github.com/sirthias/parboiled/wiki
ドキュメントがしっかりあり、構文も短くて良いと思ったので、Simple Java Example のページを見ながらgroovyで書いて試そうとした。
Groovy Version: 2.0.6 JVM: 1.6.0_37 Vendor: Apple Inc. OS: Mac OS X
import org.parboiled.BaseParser
import org.parboiled.Rule
import org.parboiled.annotations.BuildParseTree
import org.parboiled.Parboiled
import org.parboiled.support.ParsingResult
import org.parboiled.parserunners.ReportingParseRunner
import org.parboiled.support.ParseTreeUtils
@Grab('org.parboiled:parboiled-java:latest.release')
@BuildParseTree
class CalculatorParser extends BaseParser {
Rule Expression() {
Sequence( Term(), ZeroOrMore(AnyOf("+-"), Term()) )
}
Rule Term() {
Sequence( Factor(), ZeroOrMore(AnyOf("*/"), Factor() ) )
}
Rule Factor() {
FirstOf( Number(), Sequence('(', Expression(), ')' ) )
}
Rule Number() {
OneOrMore(CharRange('0', '9'))
}
}
String input = "1+2"
CalculatorParser parser = Parboiled.createParser(CalculatorParser.class)
ParsingResult result = ReportingParseRunner.run(parser.Expression(), input)
String parseTreePrintOut = ParseTreeUtils.printNodeTree(result)
println parseTreePrintOut
が、なんかエラーが出て動かない。
Caught: java.lang.RuntimeException: Error creating extended parser class: Class not found
java.lang.RuntimeException: Error creating extended parser class: Class not found
at org.parboiled.Parboiled.createParser(Parboiled.java:58)
at test.run(test.groovy:27)
Caused by: java.io.IOException: Class not found
at org.objectweb.asm.ClassReader.a(Unknown Source)
at org.objectweb.asm.ClassReader.<init>(Unknown Source)
at org.parboiled.transform.AsmUtils.createClassReader(AsmUtils.java:56)
at org.parboiled.transform.ClassNodeInitializer.process(ClassNodeInitializer.java:62)
at org.parboiled.transform.ParserTransformer.extendParserClass(ParserTransformer.java:44)
at org.parboiled.transform.ParserTransformer.transformParser(ParserTransformer.java:38)
at org.parboiled.Parboiled.createParser(Parboiled.java:54)
... 1 more
納得いかなかったので、Parboiledのソースを落として調べた。
org.parboiled.transform.AsmUtils の、line 51
...
public static ClassReader createClassReader(Class<?> clazz) throws IOException {
checkArgNotNull(clazz, "clazz");
String classFilename = clazz.getName().replace('.', '/') + ".class"; //<- line51 ここ!
InputStream inputStream = clazz.getClassLoader().getResourceAsStream(classFilename);
if (inputStream == null) {
inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(classFilename);
}
return new ClassReader(inputStream);
}
...
ここで、クラス名から.classファイルを探し出し、ASMでバイトコードを読み出してるみたい。
.groovyファイルひとつで試してるから、当然 .classファイルはできていない。
だから使えなかったのか。そうかー。
groovyで気軽に使えるパーサライブラリが欲しいなぁ。