diff --git a/src/test/java/org/jetbrains/plugins/ideavim/regex/VimRegexEngineTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/regex/VimRegexEngineTest.kt
new file mode 100644
index 000000000..6500dd3cc
--- /dev/null
+++ b/src/test/java/org/jetbrains/plugins/ideavim/regex/VimRegexEngineTest.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2003-2023 The IdeaVim authors
+ *
+ * Use of this source code is governed by an MIT-style
+ * license that can be found in the LICENSE.txt file or at
+ * https://opensource.org/licenses/MIT.
+ */
+
+package org.jetbrains.plugins.ideavim.regex
+
+import com.maddyhome.idea.vim.api.injector
+import com.maddyhome.idea.vim.common.TextRange
+import com.maddyhome.idea.vim.mark.VimMark
+import com.maddyhome.idea.vim.newapi.vim
+import com.maddyhome.idea.vim.regexp.VimRegex
+import org.jetbrains.plugins.ideavim.VimTestCase
+import org.junit.jupiter.api.Test
+import kotlin.test.assertEquals
+
+class VimRegexEngineTest : VimTestCase() {
+  private fun findAll(pattern: String): List<TextRange> {
+    val regex = VimRegex(pattern)
+    return regex.findAll(fixture.editor.vim).map { it.range }
+  }
+
+  @Test
+  fun `test end of word at middle of text`() {
+    configureByText("Lorem Ipsum")
+    val result = findAll("Lorem\\>")
+    assertEquals(result, listOf(TextRange(0, 5)))
+  }
+
+  @Test
+  fun `test end of word should fail`() {
+    configureByText("Lorem Ipsum")
+    val result = findAll("Lo\\>rem")
+    assertEquals(result, emptyList())
+  }
+
+  @Test
+  fun `test start of word at offset`() {
+    configureByText("Lorem Ipsum")
+    val result = findAll("\\<Ipsum")
+    assertEquals(result, listOf(TextRange(6, 11)))
+  }
+
+  @Test
+  fun `test start of word should fail`() {
+    configureByText("Lorem Ipsum")
+    val result = findAll("Lo\\<rem")
+    assertEquals(result, emptyList())
+  }
+
+  @Test
+  fun `test end of word at end of text`() {
+    configureByText("Lorem Ipsum")
+    val result = findAll("Ipsum\\>")
+    assertEquals(result, listOf(TextRange(6, 11)))
+  }
+
+  @Test
+  fun `test start of word at start of text`() {
+    configureByText("Lorem Ipsum")
+    val result = findAll("\\<Lorem")
+    assertEquals(result, listOf(TextRange(0, 5)))
+  }
+
+  @Test
+  fun `test cursor and mark belong to the same cursor`() {
+    /*
+    In this test, there are two cursors, one at offset 3 and the other at 6.
+    The second cursor (at offset 6) has a mark 'm' at offset 0.
+    The pattern reads as "match the character at the cursor position that is after a mark 'm'".
+    Since the cursor and mark tokens have to "belong" to the same cursor, the resulting match
+    is at offset 6 (the offset of the second cursor), even though the first cursor appears first
+    in the text.
+    */
+    configureByText("Lor${c}em ${c}Ipsum")
+    val editor = fixture.editor.vim
+    val mark = VimMark.create('m', 0, 0, editor.getPath(), editor.extractProtocol())!!
+    val secondCaret = editor.carets().maxByOrNull { it.offset.point }!!
+    secondCaret.markStorage.setMark(mark)
+
+    val result = findAll("\\%>'m\\%#.")
+    assertEquals(result, listOf(TextRange(6, 7)))
+  }
+
+  @Test
+  fun `test text at mark position`() {
+    configureByText("Lorem Ipsum")
+    val editor = fixture.editor.vim
+    val mark = VimMark.create('m', 0, 5, editor.getPath(), editor.extractProtocol())!!
+    injector.markService.setMark(editor.primaryCaret(), mark)
+
+    val result = findAll("\\%'m...")
+    assertEquals(result, listOf(TextRange(5, 8)))
+  }
+
+  @Test
+  fun `test text before mark position`() {
+    configureByText("Lorem Ipsum")
+    val editor = fixture.editor.vim
+    val mark = VimMark.create('m', 0, 5, editor.getPath(), editor.extractProtocol())!!
+    injector.markService.setMark(editor.primaryCaret(), mark)
+
+    val result = findAll("\\%<'m...")
+    assertEquals(result, listOf(TextRange(0, 3), TextRange(3, 6)))
+  }
+
+  @Test
+  fun `test text after mark position`() {
+    configureByText("Lorem Ipsum")
+    val editor = fixture.editor.vim
+    val mark = VimMark.create('m', 0, 5, editor.getPath(), editor.extractProtocol())!!
+    injector.markService.setMark(editor.primaryCaret(), mark)
+
+    val result = findAll("\\%>'m...")
+    assertEquals(result, listOf(TextRange(6, 9)))
+  }
+}
\ No newline at end of file
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/regexp/engine/nfa/matcher/EndOfWordMatcher.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/regexp/engine/nfa/matcher/EndOfWordMatcher.kt
index 4a33bcc4b..57ebd835c 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/regexp/engine/nfa/matcher/EndOfWordMatcher.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/regexp/engine/nfa/matcher/EndOfWordMatcher.kt
@@ -26,7 +26,7 @@ internal class EndOfWordMatcher : Matcher {
   ): MatcherResult {
     if (index > editor.text().length || index == 0) return MatcherResult.Failure
 
-    val isKeywordAtIndex = KeywordOptionHelper.isKeyword(editor, editor.text()[index])
+    val isKeywordAtIndex =  editor.text().getOrNull(index)?.let { KeywordOptionHelper.isKeyword(editor, it) } ?: false
     val isKeywordBeforeIndex = editor.text().getOrNull(index - 1)?.let { KeywordOptionHelper.isKeyword(editor, it) } ?: false
 
     return if (isKeywordBeforeIndex && !isKeywordAtIndex) MatcherResult.Success(0) else MatcherResult.Failure
diff --git a/vim-engine/src/test/kotlin/com/maddyhome/idea/vim/regexp/internal/VimRegexEngineTest.kt b/vim-engine/src/test/kotlin/com/maddyhome/idea/vim/regexp/internal/VimRegexEngineTest.kt
index be2447bf3..29349414e 100644
--- a/vim-engine/src/test/kotlin/com/maddyhome/idea/vim/regexp/internal/VimRegexEngineTest.kt
+++ b/vim-engine/src/test/kotlin/com/maddyhome/idea/vim/regexp/internal/VimRegexEngineTest.kt
@@ -839,54 +839,6 @@ class VimRegexEngineTest {
     )
   }
 
-  @Test
-  fun `test start of word at start of text`() {
-    doTest(
-      "${START}Lorem$END Ipsum",
-      "\\<Lorem",
-    )
-  }
-
-  @Test
-  fun `test start of word at offset`() {
-    doTest(
-      "Lorem ${START}Ipsum$END",
-      "\\<Ipsum",
-    )
-  }
-
-  @Test
-  fun `test start of word should fail`() {
-    assertFailure(
-      "Lorem Ipsum",
-      "Lo\\<rem"
-    )
-  }
-
-  @Test
-  fun `test end of word at end of text`() {
-    doTest(
-      "Lorem ${START}Ipsum$END",
-      "Ipsum\\>",
-    )
-  }
-
-  @Test
-  fun `test end of word at middle of text`() {
-    doTest(
-      "${START}Lorem$END Ipsum",
-      "Lorem\\>",
-    )
-  }
-
-  @Test
-  fun `test end of word should fail`() {
-    assertFailure(
-      "Lorem Ipsum",
-      "Lo\\>rem"
-    )
-  }
-
   @Test
   fun `test collection with EOL`() {
     doTest(
@@ -1678,29 +1630,7 @@ class VimRegexEngineTest {
     )
   }
 
-  @Test
-  fun `test text at mark position`() {
-    doTest(
-      "Lorem ${START}${MARK('m')}Ips${END}um",
-      "\\%'m..."
-    )
-  }
 
-  @Test
-  fun `test text before mark position`() {
-    doTest(
-      "${START}Lor${END}em ${MARK('m')}Ipsum",
-      "\\%<'m..."
-    )
-  }
-
-  @Test
-  fun `test text after mark position`() {
-    doTest(
-      "Lorem ${MARK('m')}I${START}psu${END}m",
-      "\\%>'m..."
-    )
-  }
 
   @Test
   fun `test mark does not exist`() {
@@ -1710,26 +1640,6 @@ class VimRegexEngineTest {
     )
   }
 
-  @Test
-  fun `test cursor and mark belong to the same cursor`() {
-    /*
-    In this test, there are two cursors, one at offset 3 and the other at 6.
-    The second cursor (at offset 6) has a mark 'm' at offset 0.
-    The pattern reads as "match the character at the cursor position that is after a mark 'm'".
-    Since the cursor and mark tokens have to "belong" to the same cursor, the resulting match
-    is at offset 6 (the offset of the second cursor), even though the first cursor appears first
-    in the text.
-    */
-    doTest(
-      "Lorem ${START}I${END}psum",
-      "\\%>'m\\%#.",
-      listOf(
-        mockCaret(3),
-        mockCaret(6, marks = mapOf(Pair('m', BufferPosition(0, 0))))
-      )
-    )
-  }
-
   @Test
   fun `test cursor and visual belong to the same cursor`() {
     doTest(