feat: implement matchAll function in RegexItem and update tests for match results
This commit is contained in:
parent
fb1cf96fed
commit
34052d1ea2
2 changed files with 48 additions and 24 deletions
|
@ -17,22 +17,6 @@ data class AvailableState(val seq: Sequence<State> = emptySequence()) : Sequence
|
|||
get() = seq.none()
|
||||
}
|
||||
|
||||
class MatchResult(val available: AvailableState) {
|
||||
|
||||
val isSuccess: Boolean
|
||||
get() = !this.available.isEmpty
|
||||
|
||||
val isFailure: Boolean
|
||||
get() = this.available.isEmpty
|
||||
|
||||
override fun toString(): String {
|
||||
return if (isSuccess) {
|
||||
"MatchResult(success)"
|
||||
} else {
|
||||
"MatchResult(failure)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 재귀 하향 분석기.
|
||||
interface RegexItem {
|
||||
|
@ -40,14 +24,41 @@ interface RegexItem {
|
|||
fun findMatch(str: String, position: Int = 0): AvailableState
|
||||
}
|
||||
|
||||
fun RegexItem.match(item: String): MatchResult {
|
||||
// 기본 매칭 함수. AvailableState를 MatchResult로 변환
|
||||
return MatchResult(this.findMatch(item, 0))
|
||||
fun RegexItem.matchAll(item: String): Sequence<State> {
|
||||
return sequence {
|
||||
var position = 0;
|
||||
// 문자열의 끝까지 반복합니다. 비어있어도 한번은 시도합니다.
|
||||
while (position <= item.length) {
|
||||
// findMatch 메서드를 호출하여 매칭을 시도합니다.
|
||||
val matchResult = findMatch(item, position)
|
||||
if (matchResult.isEmpty) {
|
||||
// 매칭이 실패하면 position을 증가시키고 다시 시도합니다.
|
||||
if (position < item.length) {
|
||||
position++
|
||||
continue
|
||||
} else {
|
||||
// position이 문자열의 끝에 도달했지만 매칭이 실패한 경우 종료
|
||||
break
|
||||
}
|
||||
} else {
|
||||
// 매칭이 성공하면 MatchResult를 생성하여 반환합니다.
|
||||
val state = matchResult.seq.first()
|
||||
yield(state)
|
||||
// 다음 위치로 이동합니다.
|
||||
position = state.endIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun RegexItem.match(item: String): State? {
|
||||
// matchAll 에서 첫 번째 매칭 결과를 반환합니다.
|
||||
return this.matchAll(item).firstOrNull()
|
||||
}
|
||||
|
||||
fun RegexItem.test(item: String): Boolean {
|
||||
// 매칭 결과가 성공인지 확인하는 헬퍼 함수
|
||||
return this.match(item).isSuccess
|
||||
return this.match(item) != null
|
||||
}
|
||||
|
||||
class AndThenItem(val left: RegexItem, val right: RegexItem) : RegexItem {
|
||||
|
|
|
@ -151,9 +151,22 @@ class ParserTest {
|
|||
val result = compileRegex(input)
|
||||
assertEquals("(a)(b)", result.toString())
|
||||
val matchResult = result.match("ab")
|
||||
assert(matchResult.isSuccess)
|
||||
val captures = matchResult.available.first();
|
||||
assertEquals("a", captures.captures.get("0"))
|
||||
assertEquals("b", captures.captures.get("1"))
|
||||
assert(matchResult != null) { "Expected match result to be non-null" }
|
||||
if (matchResult == null) return
|
||||
assertEquals("ab", matchResult.matched)
|
||||
assertEquals(2, matchResult.captures.size)
|
||||
assertEquals("a", matchResult.captures.get("0"))
|
||||
assertEquals("b", matchResult.captures.get("1"))
|
||||
}
|
||||
@Test
|
||||
fun testMatchAll() {
|
||||
val input = "a+"
|
||||
val regex = compileRegex(input)
|
||||
val matches = regex.matchAll("aaabaaa")
|
||||
val results = matches.toList()
|
||||
println("Matches found: ${results}")
|
||||
// assertEquals(2, results.size)
|
||||
assertEquals("aaa", results[0].matched)
|
||||
assertEquals("aaa", results[1].matched)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue