my-regex-engine/lib/src/main/kotlin/org/example/Parser.kt
2025-06-28 17:50:28 +09:00

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
}