50 lines
1.8 KiB
Kotlin
50 lines
1.8 KiB
Kotlin
package org.example
|
|
|
|
import com.github.h0tk3y.betterParse.combinators.*
|
|
import com.github.h0tk3y.betterParse.grammar.Grammar
|
|
import com.github.h0tk3y.betterParse.grammar.parser
|
|
import com.github.h0tk3y.betterParse.lexer.literalToken
|
|
import com.github.h0tk3y.betterParse.lexer.regexToken
|
|
import com.github.h0tk3y.betterParse.parser.Parser
|
|
|
|
class RegexParser : Grammar<RegexItem>() {
|
|
val postfixOperator by regexToken("[+*?]")
|
|
val alternationSymbol by literalToken("|")
|
|
val openParenSymbol by literalToken("(")
|
|
val closeParenSymbol by literalToken(")")
|
|
|
|
val dot by literalToken(".")
|
|
val charToken by regexToken("[a-zA-Z0-9]")
|
|
|
|
val char by charToken map { CharItem(it.text) }
|
|
|
|
val item: Parser<RegexItem> by
|
|
char or
|
|
(dot asJust DotItem()) or
|
|
(skip(openParenSymbol) and (parser(::rootParser)) and skip(closeParenSymbol))
|
|
|
|
val term: Parser<RegexItem> by
|
|
(item and optional(postfixOperator)) map
|
|
{ result ->
|
|
result.t1.let { first ->
|
|
result.t2?.let {
|
|
when (it.text) {
|
|
"+" -> PlusItem(first)
|
|
"*" -> StarItem(first)
|
|
"?" -> QuestionItem(first)
|
|
else -> first
|
|
}
|
|
}
|
|
?: first
|
|
}
|
|
}
|
|
val andThen: Parser<RegexItem> by
|
|
oneOrMore(term) map { items -> items.reduce { left, right -> AndThenItem(left, right) } }
|
|
val termWithAlternation: Parser<RegexItem> by
|
|
leftAssociative(
|
|
andThen,
|
|
alternationSymbol,
|
|
) { left, _, right -> AlternationItem(left, right) }
|
|
|
|
override val rootParser: Parser<RegexItem> by termWithAlternation
|
|
}
|