refactor: more kotlin style
This commit is contained in:
parent
fe8dc05937
commit
ac1d5da01b
1 changed files with 71 additions and 56 deletions
|
@ -30,7 +30,7 @@ class MatchResult(val available: AvailableState) {
|
|||
// 재귀 하향 분석기.
|
||||
interface RegexItem {
|
||||
override fun toString(): String
|
||||
fun findMatch(item: String): AvailableState
|
||||
fun findMatch(str: String): AvailableState
|
||||
}
|
||||
|
||||
fun RegexItem.match(item: String): MatchResult {
|
||||
|
@ -40,8 +40,8 @@ fun RegexItem.match(item: String): MatchResult {
|
|||
|
||||
class AndThenItem(val left: RegexItem, val right: RegexItem) : RegexItem {
|
||||
override fun toString(): String = "${left}${right}"
|
||||
override fun findMatch(item: String): AvailableState {
|
||||
val leftMatch = left.findMatch(item)
|
||||
override fun findMatch(str: String): AvailableState {
|
||||
val leftMatch = left.findMatch(str)
|
||||
if (leftMatch.isEmpty) {
|
||||
return AvailableState() // If left match fails, return empty sequence
|
||||
}
|
||||
|
@ -67,67 +67,83 @@ class AndThenItem(val left: RegexItem, val right: RegexItem) : RegexItem {
|
|||
|
||||
class CharItem(val value: String) : RegexItem {
|
||||
override fun toString(): String = value
|
||||
override fun findMatch(item: String): AvailableState {
|
||||
return if (item.isNotEmpty() && item[0].toString() == value) {
|
||||
// If the first character matches, return a successful match
|
||||
AvailableState(sequenceOf(State(value, item.substring(1))))
|
||||
override fun findMatch(str: String): AvailableState {
|
||||
return when {
|
||||
// 첫번째 문자가 value와 일치하는지 확인
|
||||
str.isNotEmpty() && str[0].toString() == value -> {
|
||||
AvailableState(sequenceOf(State(value, str.substring(1))))
|
||||
}
|
||||
else -> AvailableState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun matchMany(
|
||||
str: String,
|
||||
item: RegexItem,
|
||||
): Sequence<State> {
|
||||
// 욕심쟁이 매칭을 위한 헬퍼 함수
|
||||
return item.findMatch(str).seq.flatMap { state ->
|
||||
if (state.remaining.isEmpty()) {
|
||||
sequenceOf(state) // If remaining is empty, return the matched state
|
||||
} else {
|
||||
// If it doesn't match, return an empty sequence
|
||||
AvailableState()
|
||||
// Otherwise, continue matching with the remaining string
|
||||
matchMany(state.remaining, item).map { nextState ->
|
||||
State(state.matched + nextState.matched, nextState.remaining)
|
||||
} + sequenceOf(state) // Include the current state as well
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fun matchMany(str: String, item: RegexItem): Sequence<State> = sequence {
|
||||
// val stack = mutableListOf(item.findMatch(str).seq)
|
||||
// while (stack.isNotEmpty()) {
|
||||
// val current = stack.removeAt(stack.lastIndex)
|
||||
// for (state in current) {
|
||||
// yield(state) // Yield the current state
|
||||
// if (state.remaining.isNotEmpty()) {
|
||||
// // If there is remaining string, continue matching
|
||||
// stack.add(item.findMatch(state.remaining).seq.map { nextState ->
|
||||
// State(state.matched + nextState.matched, nextState.remaining)
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
class PlusItem(val item: RegexItem) : RegexItem {
|
||||
override fun toString(): String = "${item}+"
|
||||
override fun findMatch(item: String): AvailableState {
|
||||
// 욕심쟁이 매칭해야 함. 그래서 가능한 한 많이 매칭해야 함.
|
||||
val results = mutableListOf<State>()
|
||||
var remaining = item
|
||||
|
||||
while (true) {
|
||||
val matchResult = this.item.findMatch(remaining)
|
||||
if (matchResult.isEmpty) {
|
||||
break // No more matches possible
|
||||
}
|
||||
matchResult.forEach { state -> results.add(State(state.matched, state.remaining)) }
|
||||
remaining = matchResult.first().remaining // Update remaining string
|
||||
}
|
||||
|
||||
return AvailableState(results.reversed().asSequence()) // Return all successful matches
|
||||
override fun findMatch(str: String): AvailableState {
|
||||
return AvailableState(matchMany(str, item))
|
||||
}
|
||||
}
|
||||
|
||||
class StarItem(val item: RegexItem) : RegexItem {
|
||||
override fun toString(): String = "${item}*"
|
||||
override fun findMatch(item: String): AvailableState {
|
||||
// 욕심쟁이 매칭해야 함. 그래서 가능한 한 많이 매칭해야 함.
|
||||
val results = mutableListOf<State>(State("", item)) // Start with an empty match
|
||||
var remaining = item
|
||||
while (true) {
|
||||
val matchResult = this.item.findMatch(remaining)
|
||||
override fun findMatch(str: String): AvailableState {
|
||||
// *는 0개 이상의 매칭을 의미하므로, 먼저 시도해보고 실패하면 빈 시퀀스를 반환
|
||||
val matchResult = this.item.findMatch(str)
|
||||
if (matchResult.isEmpty) {
|
||||
break // No more matches possible
|
||||
// If the item does not match, return an empty sequence
|
||||
return AvailableState(sequenceOf(State("", str)))
|
||||
}
|
||||
matchResult.forEach { state -> results.add(State(state.matched, state.remaining)) }
|
||||
remaining = matchResult.first().remaining // Update remaining string
|
||||
if (remaining.isEmpty()) {
|
||||
break // If remaining string is empty, stop matching
|
||||
// If it matches, return the successful match and continue matching with the remaining string
|
||||
return AvailableState(
|
||||
matchResult.flatMap { state ->
|
||||
sequenceOf(state) + matchMany(state.remaining, this.item)
|
||||
}
|
||||
}
|
||||
// 반드시 reverse해서 가장 긴 매칭부터 시작해야 함.
|
||||
return AvailableState(results.reversed().asSequence()) // Return all successful matches
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class QuestionItem(val item: RegexItem) : RegexItem {
|
||||
override fun toString(): String = "${item}?"
|
||||
override fun findMatch(item: String): AvailableState {
|
||||
override fun findMatch(str: String): AvailableState {
|
||||
// ?는 0개 또는 1개 매칭을 의미하므로, 먼저 시도해보고 실패하면 빈 시퀀스를 반환
|
||||
val matchResult = this.item.findMatch(item)
|
||||
val matchResult = this.item.findMatch(str)
|
||||
if (matchResult.isEmpty) {
|
||||
// If the item does not match, return an empty sequence
|
||||
return AvailableState(sequenceOf(State("", item)))
|
||||
return AvailableState(sequenceOf(State("", str)))
|
||||
}
|
||||
// If it matches, return the successful match
|
||||
return AvailableState(matchResult.map { State(it.matched, it.remaining) })
|
||||
|
@ -136,25 +152,24 @@ class QuestionItem(val item: RegexItem) : RegexItem {
|
|||
|
||||
class DotItem : RegexItem {
|
||||
override fun toString(): String = "."
|
||||
override fun findMatch(item: String): AvailableState {
|
||||
override fun findMatch(str: String): AvailableState =
|
||||
// .은 임의의 한 문자와 매칭되므로, 첫 문자가 존재하면 매칭 성공
|
||||
return if (item.isNotEmpty()) {
|
||||
AvailableState(sequenceOf(State(item[0].toString(), item.substring(1))))
|
||||
} else {
|
||||
AvailableState() // 빈 문자열에 대해서는 매칭 실패
|
||||
}
|
||||
when {
|
||||
str.isNotEmpty() ->
|
||||
AvailableState(sequenceOf(State(str[0].toString(), str.substring(1))))
|
||||
else -> AvailableState() // 빈 문자열에 대해서는 매칭 실패
|
||||
}
|
||||
}
|
||||
|
||||
class AlternationItem(val left: RegexItem, val right: RegexItem) : RegexItem {
|
||||
override fun toString(): String = "(${left}|${right})"
|
||||
override fun findMatch(item: String): AvailableState {
|
||||
override fun findMatch(str: String): AvailableState {
|
||||
// Alternation은 왼쪽 또는 오른쪽 항목 중 하나와 매칭되므로, 각각 시도해보고 성공하는 경우를 반환
|
||||
val leftMatch = left.findMatch(item)
|
||||
val rightMatch = right.findMatch(item)
|
||||
val leftMatch = left.findMatch(str)
|
||||
val rightMatch = right.findMatch(str)
|
||||
|
||||
return AvailableState(
|
||||
(leftMatch + rightMatch).asSequence() // 두 매칭 결과를 합쳐서 반환
|
||||
(leftMatch + rightMatch) // 두 매칭 결과를 합쳐서 반환
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue