From 5335bdbe34528ef92997a752280457133255a55c Mon Sep 17 00:00:00 2001 From: George Potoshin Date: Wed, 25 Feb 2026 14:33:09 +0100 Subject: [PATCH] [core:text/regex] Follow up to fix #6323 and add test case. As was said in the issue discussion I had suspicion that there may be a sibling bug in .Assert_Non_Word_Boundary implementation and I was able to confirm that with `re.findall(rB", ")` python code. Odin implementation outputed an empty string wherase python gave "'". That is the same bug related to incorrect logic on string ends. This commit makes implementation of those 2 instructions cleaner and adds a test case. --- .../virtual_machine/virtual_machine.odin | 24 +++++++------------ .../core/text/regex/test_core_text_regex.odin | 4 ++++ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/core/text/regex/virtual_machine/virtual_machine.odin b/core/text/regex/virtual_machine/virtual_machine.odin index e90a27e63..ab2e9515c 100644 --- a/core/text/regex/virtual_machine/virtual_machine.odin +++ b/core/text/regex/virtual_machine/virtual_machine.odin @@ -204,15 +204,8 @@ add_thread :: proc(vm: ^Machine, saved: ^[2 * common.MAX_CAPTURE_GROUPS]int, pc: case .Assert_Word_Boundary: sp := vm.string_pointer+vm.current_rune_size - left_is_wc := false - if sp > 0 { - left_is_wc = is_word_class(vm.current_rune) - } - - right_is_wc := false - if sp < len(vm.memory) { - right_is_wc = is_word_class(vm.next_rune) - } + left_is_wc := sp > 0 && is_word_class(vm.current_rune) + right_is_wc := sp < len(vm.memory) && is_word_class(vm.next_rune) if left_is_wc != right_is_wc { pc += size_of(Opcode) @@ -221,14 +214,13 @@ add_thread :: proc(vm: ^Machine, saved: ^[2 * common.MAX_CAPTURE_GROUPS]int, pc: case .Assert_Non_Word_Boundary: sp := vm.string_pointer+vm.current_rune_size - if sp != 0 && sp != len(vm.memory) { - last_rune_is_wc := is_word_class(vm.current_rune) - this_rune_is_wc := is_word_class(vm.next_rune) - if last_rune_is_wc && this_rune_is_wc || !last_rune_is_wc && !this_rune_is_wc { - pc += size_of(Opcode) - continue - } + left_is_wc := sp > 0 && is_word_class(vm.current_rune) + right_is_wc := sp < len(vm.memory) && is_word_class(vm.next_rune) + + if left_is_wc == right_is_wc { + pc += size_of(Opcode) + continue } case .Wait_For_Byte: diff --git a/tests/core/text/regex/test_core_text_regex.odin b/tests/core/text/regex/test_core_text_regex.odin index 578ebc242..732a3d321 100644 --- a/tests/core/text/regex/test_core_text_regex.odin +++ b/tests/core/text/regex/test_core_text_regex.odin @@ -564,6 +564,10 @@ test_non_word_boundaries :: proc(t: ^testing.T) { EXPR :: `.+\B` check_expression(t, EXPR, "abc", "ab") } + { + EXPR :: `\B'` + check_expression(t, EXPR, "'", "'") + } } @test