feat: add bracket content parsing and corresponding tests
This commit is contained in:
parent
60ec5916d0
commit
78472511e7
3 changed files with 52 additions and 3 deletions
|
@ -5,6 +5,7 @@ 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.lexer.token
|
||||
import com.github.h0tk3y.betterParse.parser.Parser
|
||||
|
||||
class RegexParser : Grammar<RegexItem>() {
|
||||
|
@ -14,8 +15,29 @@ class RegexParser : Grammar<RegexItem>() {
|
|||
val alternationSymbol by literalToken("|")
|
||||
val openParenSymbol by literalToken("(")
|
||||
val closeParenSymbol by literalToken(")")
|
||||
val bracketOpen by literalToken("[")
|
||||
val bracketClose by literalToken("]")
|
||||
val bracketContent by
|
||||
token(
|
||||
name = "bracketContent",
|
||||
matcher = { seq, from ->
|
||||
if (seq[from] != '[') {
|
||||
0 // 대괄호로 시작하지 않으면 매칭 실패
|
||||
} else {
|
||||
// 대괄호의 시작 위치에서부터 ']'를 찾음
|
||||
var to = seq.indexOf(']', from)
|
||||
// 이스케이프 ']' 건너 뛰기
|
||||
while (to >= 0 && to > from && seq[to - 1] == '\\') {
|
||||
to = seq.indexOf(']', to + 1)
|
||||
}
|
||||
if (to < 0) {
|
||||
0
|
||||
} else if (to == from + 1) {
|
||||
0 // 빈 대괄호는 허용하지 않음
|
||||
} else {
|
||||
to - from + 1 // 대괄호의 시작 위치부터 ']'까지의 길이
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
val dot by literalToken(".")
|
||||
val charToken by regexToken("[a-zA-Z0-9]")
|
||||
|
@ -26,6 +48,7 @@ class RegexParser : Grammar<RegexItem>() {
|
|||
char or
|
||||
(dot asJust DotItem()) or
|
||||
(escapedCharacter map { CharItem(it.text.substring(1)) }) or
|
||||
(bracketContent map { BracketItem(it.text.substring(1, it.text.length - 1)) }) or
|
||||
(skip(openParenSymbol) and (parser(::rootParser)) and skip(closeParenSymbol))
|
||||
|
||||
val term: Parser<RegexItem> by
|
||||
|
|
|
@ -92,6 +92,21 @@ class CharItem(val value: String) : RegexItem {
|
|||
}
|
||||
}
|
||||
|
||||
class BracketItem(val content: String) : RegexItem {
|
||||
override fun toString(): String = "[$content]"
|
||||
|
||||
// TODO: 범위 처리
|
||||
override fun findMatch(str: String): AvailableState {
|
||||
// 대괄호 안의 내용과 일치하는 첫 문자를 찾음
|
||||
return when {
|
||||
str.isNotEmpty() && content.contains(str[0]) -> {
|
||||
AvailableState(sequenceOf(State(str[0].toString(), str.substring(1))))
|
||||
}
|
||||
else -> AvailableState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun matchMany(
|
||||
str: String,
|
||||
item: RegexItem,
|
||||
|
|
|
@ -116,4 +116,15 @@ class ParserTest {
|
|||
assert(result.match("+").isSuccess)
|
||||
assert(!result.match("a").isSuccess)
|
||||
}
|
||||
@Test
|
||||
fun testBracketContent() {
|
||||
val input = "[abc]"
|
||||
val parser = RegexParser()
|
||||
val result = parser.parseToEnd(input)
|
||||
assertEquals("[abc]", result.toString())
|
||||
assert(result.match("a").isSuccess)
|
||||
assert(result.match("b").isSuccess)
|
||||
assert(result.match("c").isSuccess)
|
||||
assert(!result.match("d").isSuccess)
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue