diff --git a/lib/src/main/kotlin/org/example/RegexItem.kt b/lib/src/main/kotlin/org/example/RegexItem.kt index 13900f0..fc98960 100644 --- a/lib/src/main/kotlin/org/example/RegexItem.kt +++ b/lib/src/main/kotlin/org/example/RegexItem.kt @@ -17,22 +17,6 @@ data class AvailableState(val seq: Sequence = 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 { + 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 { diff --git a/lib/src/test/kotlin/org/example/ParserTest.kt b/lib/src/test/kotlin/org/example/ParserTest.kt index 6ef8535..fae0984 100644 --- a/lib/src/test/kotlin/org/example/ParserTest.kt +++ b/lib/src/test/kotlin/org/example/ParserTest.kt @@ -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) } }