Наивный синтаксический анализатор, использующий petit - но, конечно, оставляет много для покрытия, так как грамматика c неизвестна.
@Grab("com.github.petitparser:petitparser-core:2.2.0")
import org.petitparser.tools.GrammarDefinition
import org.petitparser.tools.GrammarParser
import org.petitparser.parser.primitive.CharacterParser as CP
import org.petitparser.parser.primitive.StringParser as SP
import org.petitparser.utils.Functions as F
class FakeMLGrammerDefinition extends GrammarDefinition {
FakeMLGrammerDefinition() {
define("start",
ref("tag").trim())
define("tag",
ref("tag-start")
.seq(ref("tag").star())
.seq(ref("text").optional())
.seq(ref("tag").star())
.seq(ref("tag-end")))
define("tag-start",
SP.of('<:')
.seq(ref("keyword"))
.seq(SP.of(">"))
.trim())
define("tag-end",
SP.of("</>")
.trim())
define("text",
CP.pattern("^<").star().flatten().trim())
define("keyword",
CP.letter()
.seq(CP.pattern("^>").plus())
.star()
.flatten())
}
/** Helper for `def`, which is a keyword in groovy */
void define(s, p) { super.def(s,p) }
}
class FakeMLParserDefinition extends FakeMLGrammerDefinition {
FakeMLParserDefinition() {
action("tag", { tag, c1, t, c2, _ ->
[(tag): [children: c1+c2, text: t]]
})
action("tag-start", { it[1] })
}
}
class FakeMLParser extends GrammarParser {
FakeMLParser() {
super(new FakeMLParserDefinition())
}
}
println(new FakeMLParser().parse("""
<:openingtag>
<:openingtag2>
<:openingtag3>
text
</>
</>
</>
"""))
// Success[9:1]: {openingtag={children=[{openingtag2={children=[{openingtag3={children=[], text=text}}], text=}}], text=}}