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()
|
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 {
|
interface RegexItem {
|
||||||
|
@ -40,14 +24,41 @@ interface RegexItem {
|
||||||
fun findMatch(str: String, position: Int = 0): AvailableState
|
fun findMatch(str: String, position: Int = 0): AvailableState
|
||||||
}
|
}
|
||||||
|
|
||||||
fun RegexItem.match(item: String): MatchResult {
|
fun RegexItem.matchAll(item: String): Sequence<State> {
|
||||||
// 기본 매칭 함수. AvailableState를 MatchResult로 변환
|
return sequence {
|
||||||
return MatchResult(this.findMatch(item, 0))
|
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 {
|
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 {
|
class AndThenItem(val left: RegexItem, val right: RegexItem) : RegexItem {
|
||||||
|
|
|
@ -151,9 +151,22 @@ class ParserTest {
|
||||||
val result = compileRegex(input)
|
val result = compileRegex(input)
|
||||||
assertEquals("(a)(b)", result.toString())
|
assertEquals("(a)(b)", result.toString())
|
||||||
val matchResult = result.match("ab")
|
val matchResult = result.match("ab")
|
||||||
assert(matchResult.isSuccess)
|
assert(matchResult != null) { "Expected match result to be non-null" }
|
||||||
val captures = matchResult.available.first();
|
if (matchResult == null) return
|
||||||
assertEquals("a", captures.captures.get("0"))
|
assertEquals("ab", matchResult.matched)
|
||||||
assertEquals("b", captures.captures.get("1"))
|
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