prompt: 
  We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  "Dropped elements in sequence matching" when doubled semicolon
  ## Expected Behaviour
  Frankly, I'm not sure whether it (doubled `;`) should be just ignored or rather some specific rule should be triggered.
  ## Observed Behaviour
  ```console
  (.venv) ?master ~/prod/_inne/sqlfluff> echo "select id from tbl;;" | sqlfluff lint -
  Traceback (most recent call last):
    File "/home/adam/prod/_inne/sqlfluff/.venv/bin/sqlfluff", line 11, in <module>
      load_entry_point('sqlfluff', 'console_scripts', 'sqlfluff')()
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 1137, in __call__
      return self.main(*args, **kwargs)
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 1062, in main
      rv = self.invoke(ctx)
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 1668, in invoke
      return _process_result(sub_ctx.command.invoke(sub_ctx))
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 1404, in invoke
      return ctx.invoke(self.callback, **ctx.params)
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 763, in invoke
      return __callback(*args, **kwargs)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/cli/commands.py", line 347, in lint
      result = lnt.lint_string_wrapped(sys.stdin.read(), fname="stdin")
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 789, in lint_string_wrapped
      linted_path.add(self.lint_string(string, fname=fname, fix=fix))
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 668, in lint_string
      parsed = self.parse_string(in_str=in_str, fname=fname, config=config)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 607, in parse_string
      return self.parse_rendered(rendered, recurse=recurse)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 313, in parse_rendered
      parsed, pvs = cls._parse_tokens(
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 190, in _parse_tokens
      parsed: Optional[BaseSegment] = parser.parse(
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/parser/parser.py", line 32, in parse
      parsed = root_segment.parse(parse_context=ctx)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/parser/segments/base.py", line 821, in parse
      check_still_complete(segments, m.matched_segments, m.unmatched_segments)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/parser/helpers.py", line 30, in check_still_complete
      raise RuntimeError(
  RuntimeError: Dropped elements in sequence matching! 'select id from tbl;;' != ';'
  
  ```
  ## Steps to Reproduce
  Run 
  ```console
  echo "select id from tbl;;" | sqlfluff lint -
  ```
  ## Dialect
  default (ansi)
  ## Version
  ```
  sqlfluff, version 0.6.6
  Python 3.9.5
  ```
  ## Configuration
  None
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  
  --- BEGIN FILE ---
  ```
  ### src/sqlfluff/core/parser/helpers.py
  """Helpers for the parser module."""
  
  from typing import Tuple, List, Any, Iterator, TYPE_CHECKING
  
  from sqlfluff.core.string_helpers import curtail_string
  
  if TYPE_CHECKING:
      from sqlfluff.core.parser.segments import BaseSegment  # pragma: no cover
  
  
  def join_segments_raw(segments: Tuple["BaseSegment", ...]) -> str:
      """Make a string from the joined `raw` attributes of an iterable of segments."""
      return "".join(s.raw for s in segments)
  
  
  def join_segments_raw_curtailed(segments: Tuple["BaseSegment", ...], length=20) -> str:
      """Make a string up to a certain length from an iterable of segments."""
      return curtail_string(join_segments_raw(segments), length=length)
  
  
  def check_still_complete(
      segments_in: Tuple["BaseSegment", ...],
      matched_segments: Tuple["BaseSegment", ...],
      unmatched_segments: Tuple["BaseSegment", ...],
  ) -> bool:
      """Check that the segments in are the same as the segments out."""
      initial_str = join_segments_raw(segments_in)
      current_str = join_segments_raw(matched_segments + unmatched_segments)
      if initial_str != current_str:  # pragma: no cover
          raise RuntimeError(
              "Dropped elements in sequence matching! {!r} != {!r}".format(
                  initial_str, current_str
              )
          )
      return True
  
  
  def trim_non_code_segments(
      segments: Tuple["BaseSegment", ...]
  ) -> Tuple[
      Tuple["BaseSegment", ...], Tuple["BaseSegment", ...], Tuple["BaseSegment", ...]
  ]:
      """Take segments and split off surrounding non-code segments as appropriate.
  
      We use slices to avoid creating too many unnecessary tuples.
      """
      pre_idx = 0
      seg_len = len(segments)
      post_idx = seg_len
  
      if segments:
          seg_len = len(segments)
  
          # Trim the start
          while pre_idx < seg_len and not segments[pre_idx].is_code:
              pre_idx += 1
  
          # Trim the end
          while post_idx > pre_idx and not segments[post_idx - 1].is_code:
              post_idx -= 1
  
      return segments[:pre_idx], segments[pre_idx:post_idx], segments[post_idx:]
  
  
  def iter_indices(seq: List, val: Any) -> Iterator[int]:
      """Iterate all indices in a list that val occurs at.
  
      Args:
          seq (list): A list to look for indices in.
          val: What to look for.
  
      Yields:
          int: The index of val in seq.
  
      Examples:
          The function works like str.index() but iterates all
          the results rather than returning the first.
  
          >>> print([i for i in iter_indices([1, 0, 2, 3, 2], 2)])
          [2, 4]
      """
      for idx, el in enumerate(seq):
          if el == val:
              yield idx
  
  ```
  --- END FILE ---
  
  Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.
  
  Every *SEARCH/REPLACE* edit must use this format:
  1. The file path
  2. The start of search block: <<<<<<< SEARCH
  3. A contiguous chunk of lines to search for in the existing source code
  4. The dividing line: =======
  5. The lines to replace into the source code
  6. The end of the replace block: >>>>>>> REPLACE
  
  Here is an example:
  
  ```python
  ### mathweb/flask/app.py
  <<<<<<< SEARCH
  from flask import Flask
  =======
  import math
  from flask import Flask
  >>>>>>> REPLACE
  ```
  
  Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
  Wrap the *SEARCH/REPLACE* edit in blocks ```python...```.
  
instance: {"FAIL_TO_PASS": "[\"test/dialects/ansi_test.py::test__dialect__ansi_multiple_semicolons[select\"]", "PASS_TO_PASS": "[\"test/dialects/ansi_test.py::test__dialect__ansi__file_lex[a\", \"test/dialects/ansi_test.py::test__dialect__ansi__file_lex[b.c-res1]\", \"test/dialects/ansi_test.py::test__dialect__ansi__file_lex[abc\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectKeywordSegment-select]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[NakedIdentifierSegment-online_sales]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[BareFunctionSegment-current_timestamp]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[FunctionSegment-current_timestamp()]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[NumericLiteralSegment-1000.0]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-online_sales\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[IntervalExpressionSegment-INTERVAL\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-CASE\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-CAST(ROUND(online_sales\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-name\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectClauseElementSegment-MIN\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-DATE_ADD(CURRENT_DATE('America/New_York'),\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-my_array[1]]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-my_array[OFFSET(1)]]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-my_array[5:8]]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-4\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-bits[OFFSET(0)]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectClauseElementSegment-(count_18_24\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-count_18_24\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectStatementSegment-SELECT\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectClauseElementSegment-t.val/t.id]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectClauseElementSegment-CAST(num\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectClauseElementSegment-a.*]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectClauseElementSegment-a.b.*]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectClauseElementSegment-a.b.c.*]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ObjectReferenceSegment-a..c.*]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectClauseElementSegment--some_variable]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectClauseElementSegment--\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-concat(left(uaid,\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-c\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectClauseElementSegment-c\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[ExpressionSegment-NULL::INT]\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[SelectClauseElementSegment-NULL::INT\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_parses[TruncateStatementSegment-TRUNCATE\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_not_match[ObjectReferenceSegment-\\\\n\", \"test/dialects/ansi_test.py::test__dialect__ansi_specific_segment_not_parse[SELECT\", \"test/dialects/ansi_test.py::test__dialect__ansi_is_whitespace\", \"test/dialects/ansi_test.py::test__dialect__ansi_parse_indented_joins[select\", \"test/dialects/ansi_test.py::test__dialect__ansi_multiple_semicolons[;;-Line\"]", "base_commit": "304a197829f98e7425a46d872ada73176137e5ae", "created_at": "2021-10-06T07:57:35Z", "environment_setup_commit": "67023b85c41d23d6c6d69812a41b207c4f8a9331", "hints_text": "Sounds similar to #1458 where we should handle \"empty\" statement/files better?\nNope, that's the different issue. I doubt that solving one of them would help in other one. I think both issues should stay, just in the case.\nBut what do you think @tunetheweb - should it just ignore these `;;` or raise something like `Found unparsable section:`? \nJust tested and in BigQuery it's an error.\r\nInterestingly Oracle is fine with it.\r\n\r\nI think it should be raised as `Found unparsable section`.", "instance_id": "sqlfluff__sqlfluff-1517", "patch": "diff --git a/src/sqlfluff/core/parser/helpers.py b/src/sqlfluff/core/parser/helpers.py\n--- a/src/sqlfluff/core/parser/helpers.py\n+++ b/src/sqlfluff/core/parser/helpers.py\n@@ -2,6 +2,7 @@\n \n from typing import Tuple, List, Any, Iterator, TYPE_CHECKING\n \n+from sqlfluff.core.errors import SQLParseError\n from sqlfluff.core.string_helpers import curtail_string\n \n if TYPE_CHECKING:\n@@ -26,11 +27,11 @@ def check_still_complete(\n     \"\"\"Check that the segments in are the same as the segments out.\"\"\"\n     initial_str = join_segments_raw(segments_in)\n     current_str = join_segments_raw(matched_segments + unmatched_segments)\n-    if initial_str != current_str:  # pragma: no cover\n-        raise RuntimeError(\n-            \"Dropped elements in sequence matching! {!r} != {!r}\".format(\n-                initial_str, current_str\n-            )\n+\n+    if initial_str != current_str:\n+        raise SQLParseError(\n+            f\"Could not parse: {current_str}\",\n+            segment=unmatched_segments[0],\n         )\n     return True\n \n", "problem_statement": "\"Dropped elements in sequence matching\" when doubled semicolon\n## Expected Behaviour\r\nFrankly, I'm not sure whether it (doubled `;`) should be just ignored or rather some specific rule should be triggered.\r\n## Observed Behaviour\r\n```console\r\n(.venv) ?master ~/prod/_inne/sqlfluff> echo \"select id from tbl;;\" | sqlfluff lint -\r\nTraceback (most recent call last):\r\n  File \"/home/adam/prod/_inne/sqlfluff/.venv/bin/sqlfluff\", line 11, in <module>\r\n    load_entry_point('sqlfluff', 'console_scripts', 'sqlfluff')()\r\n  File \"/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py\", line 1137, in __call__\r\n    return self.main(*args, **kwargs)\r\n  File \"/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py\", line 1062, in main\r\n    rv = self.invoke(ctx)\r\n  File \"/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py\", line 1668, in invoke\r\n    return _process_result(sub_ctx.command.invoke(sub_ctx))\r\n  File \"/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py\", line 1404, in invoke\r\n    return ctx.invoke(self.callback, **ctx.params)\r\n  File \"/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py\", line 763, in invoke\r\n    return __callback(*args, **kwargs)\r\n  File \"/home/adam/prod/_inne/sqlfluff/src/sqlfluff/cli/commands.py\", line 347, in lint\r\n    result = lnt.lint_string_wrapped(sys.stdin.read(), fname=\"stdin\")\r\n  File \"/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py\", line 789, in lint_string_wrapped\r\n    linted_path.add(self.lint_string(string, fname=fname, fix=fix))\r\n  File \"/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py\", line 668, in lint_string\r\n    parsed = self.parse_string(in_str=in_str, fname=fname, config=config)\r\n  File \"/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py\", line 607, in parse_string\r\n    return self.parse_rendered(rendered, recurse=recurse)\r\n  File \"/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py\", line 313, in parse_rendered\r\n    parsed, pvs = cls._parse_tokens(\r\n  File \"/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py\", line 190, in _parse_tokens\r\n    parsed: Optional[BaseSegment] = parser.parse(\r\n  File \"/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/parser/parser.py\", line 32, in parse\r\n    parsed = root_segment.parse(parse_context=ctx)\r\n  File \"/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/parser/segments/base.py\", line 821, in parse\r\n    check_still_complete(segments, m.matched_segments, m.unmatched_segments)\r\n  File \"/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/parser/helpers.py\", line 30, in check_still_complete\r\n    raise RuntimeError(\r\nRuntimeError: Dropped elements in sequence matching! 'select id from tbl;;' != ';'\r\n\r\n```\r\n## Steps to Reproduce\r\nRun \r\n```console\r\necho \"select id from tbl;;\" | sqlfluff lint -\r\n```\r\n## Dialect\r\ndefault (ansi)\r\n## Version\r\n```\r\nsqlfluff, version 0.6.6\r\nPython 3.9.5\r\n```\r\n## Configuration\r\nNone\r\n\n", "repo": "sqlfluff/sqlfluff", "test_patch": "diff --git a/test/dialects/ansi_test.py b/test/dialects/ansi_test.py\n--- a/test/dialects/ansi_test.py\n+++ b/test/dialects/ansi_test.py\n@@ -3,7 +3,7 @@\n import pytest\n import logging\n \n-from sqlfluff.core import FluffConfig, Linter\n+from sqlfluff.core import FluffConfig, Linter, SQLParseError\n from sqlfluff.core.parser import Lexer\n \n \n@@ -214,3 +214,29 @@ def test__dialect__ansi_parse_indented_joins(sql_string, indented_joins, meta_lo\n         idx for idx, raw_seg in enumerate(parsed.tree.iter_raw_seg()) if raw_seg.is_meta\n     )\n     assert res_meta_locs == meta_loc\n+\n+\n+@pytest.mark.parametrize(\n+    \"raw,expected_message\",\n+    [\n+        (\";;\", \"Line 1, Position 1: Found unparsable section: ';;'\"),\n+        (\"select id from tbl;\", \"\"),\n+        (\"select id from tbl;;\", \"Could not parse: ;\"),\n+        (\"select id from tbl;;;;;;\", \"Could not parse: ;;;;;\"),\n+        (\"select id from tbl;select id2 from tbl2;\", \"\"),\n+        (\n+            \"select id from tbl;;select id2 from tbl2;\",\n+            \"Could not parse: ;select id2 from tbl2;\",\n+        ),\n+    ],\n+)\n+def test__dialect__ansi_multiple_semicolons(raw: str, expected_message: str) -> None:\n+    \"\"\"Multiple semicolons should be properly handled.\"\"\"\n+    lnt = Linter()\n+    parsed = lnt.parse_string(raw)\n+\n+    assert len(parsed.violations) == (1 if expected_message else 0)\n+    if expected_message:\n+        violation = parsed.violations[0]\n+        assert isinstance(violation, SQLParseError)\n+        assert violation.desc() == expected_message\n", "version": "0.6"}
parsed_commit_content: {"file_diffs":[{"old_file_content":"\"\"\"Helpers for the parser module.\"\"\"\n\nfrom typing import Tuple, List, Any, Iterator, TYPE_CHECKING\n\nfrom sqlfluff.core.string_helpers import curtail_string\n\nif TYPE_CHECKING:\n    from sqlfluff.core.parser.segments import BaseSegment  # pragma: no cover\n\n\ndef join_segments_raw(segments: Tuple[\"BaseSegment\", ...]) -> str:\n    \"\"\"Make a string from the joined `raw` attributes of an iterable of segments.\"\"\"\n    return \"\".join(s.raw for s in segments)\n\n\ndef join_segments_raw_curtailed(segments: Tuple[\"BaseSegment\", ...], length=20) -> str:\n    \"\"\"Make a string up to a certain length from an iterable of segments.\"\"\"\n    return curtail_string(join_segments_raw(segments), length=length)\n\n\ndef check_still_complete(\n    segments_in: Tuple[\"BaseSegment\", ...],\n    matched_segments: Tuple[\"BaseSegment\", ...],\n    unmatched_segments: Tuple[\"BaseSegment\", ...],\n) -> bool:\n    \"\"\"Check that the segments in are the same as the segments out.\"\"\"\n    initial_str = join_segments_raw(segments_in)\n    current_str = join_segments_raw(matched_segments + unmatched_segments)\n    if initial_str != current_str:  # pragma: no cover\n        raise RuntimeError(\n            \"Dropped elements in sequence matching! {!r} != {!r}\".format(\n                initial_str, current_str\n            )\n        )\n    return True\n\n\ndef trim_non_code_segments(\n    segments: Tuple[\"BaseSegment\", ...]\n) -> Tuple[\n    Tuple[\"BaseSegment\", ...], Tuple[\"BaseSegment\", ...], Tuple[\"BaseSegment\", ...]\n]:\n    \"\"\"Take segments and split off surrounding non-code segments as appropriate.\n\n    We use slices to avoid creating too many unnecessary tuples.\n    \"\"\"\n    pre_idx = 0\n    seg_len = len(segments)\n    post_idx = seg_len\n\n    if segments:\n        seg_len = len(segments)\n\n        # Trim the start\n        while pre_idx < seg_len and not segments[pre_idx].is_code:\n            pre_idx += 1\n\n        # Trim the end\n        while post_idx > pre_idx and not segments[post_idx - 1].is_code:\n            post_idx -= 1\n\n    return segments[:pre_idx], segments[pre_idx:post_idx], segments[post_idx:]\n\n\ndef iter_indices(seq: List, val: Any) -> Iterator[int]:\n    \"\"\"Iterate all indices in a list that val occurs at.\n\n    Args:\n        seq (list): A list to look for indices in.\n        val: What to look for.\n\n    Yields:\n        int: The index of val in seq.\n\n    Examples:\n        The function works like str.index() but iterates all\n        the results rather than returning the first.\n\n        >>> print([i for i in iter_indices([1, 0, 2, 3, 2], 2)])\n        [2, 4]\n    \"\"\"\n    for idx, el in enumerate(seq):\n        if el == val:\n            yield idx\n","new_file_content":"\"\"\"Helpers for the parser module.\"\"\"\n\nfrom typing import Tuple, List, Any, Iterator, TYPE_CHECKING\n\nfrom sqlfluff.core.errors import SQLParseError\nfrom sqlfluff.core.string_helpers import curtail_string\n\nif TYPE_CHECKING:\n    from sqlfluff.core.parser.segments import BaseSegment  # pragma: no cover\n\n\ndef join_segments_raw(segments: Tuple[\"BaseSegment\", ...]) -> str:\n    \"\"\"Make a string from the joined `raw` attributes of an iterable of segments.\"\"\"\n    return \"\".join(s.raw for s in segments)\n\n\ndef join_segments_raw_curtailed(segments: Tuple[\"BaseSegment\", ...], length=20) -> str:\n    \"\"\"Make a string up to a certain length from an iterable of segments.\"\"\"\n    return curtail_string(join_segments_raw(segments), length=length)\n\n\ndef check_still_complete(\n    segments_in: Tuple[\"BaseSegment\", ...],\n    matched_segments: Tuple[\"BaseSegment\", ...],\n    unmatched_segments: Tuple[\"BaseSegment\", ...],\n) -> bool:\n    \"\"\"Check that the segments in are the same as the segments out.\"\"\"\n    initial_str = join_segments_raw(segments_in)\n    current_str = join_segments_raw(matched_segments + unmatched_segments)\n\n    if initial_str != current_str:\n        raise SQLParseError(\n            f\"Could not parse: {current_str}\",\n            segment=unmatched_segments[0],\n        )\n    return True\n\n\ndef trim_non_code_segments(\n    segments: Tuple[\"BaseSegment\", ...]\n) -> Tuple[\n    Tuple[\"BaseSegment\", ...], Tuple[\"BaseSegment\", ...], Tuple[\"BaseSegment\", ...]\n]:\n    \"\"\"Take segments and split off surrounding non-code segments as appropriate.\n\n    We use slices to avoid creating too many unnecessary tuples.\n    \"\"\"\n    pre_idx = 0\n    seg_len = len(segments)\n    post_idx = seg_len\n\n    if segments:\n        seg_len = len(segments)\n\n        # Trim the start\n        while pre_idx < seg_len and not segments[pre_idx].is_code:\n            pre_idx += 1\n\n        # Trim the end\n        while post_idx > pre_idx and not segments[post_idx - 1].is_code:\n            post_idx -= 1\n\n    return segments[:pre_idx], segments[pre_idx:post_idx], segments[post_idx:]\n\n\ndef iter_indices(seq: List, val: Any) -> Iterator[int]:\n    \"\"\"Iterate all indices in a list that val occurs at.\n\n    Args:\n        seq (list): A list to look for indices in.\n        val: What to look for.\n\n    Yields:\n        int: The index of val in seq.\n\n    Examples:\n        The function works like str.index() but iterates all\n        the results rather than returning the first.\n\n        >>> print([i for i in iter_indices([1, 0, 2, 3, 2], 2)])\n        [2, 4]\n    \"\"\"\n    for idx, el in enumerate(seq):\n        if el == val:\n            yield idx\n","header":{"file":{"path":"src/sqlfluff/core/parser/helpers.py"},"misc_line":null},"index_line":null,"is_binary_file":false,"binary_line":null,"minus_file":{"path":"a/src/sqlfluff/core/parser/helpers.py"},"plus_file":{"path":"b/src/sqlfluff/core/parser/helpers.py"},"hunks":[{"descriptor":{"old_range":{"start":2,"length":6},"new_range":{"start":2,"length":7},"section":""},"line_group":{"all_lines":[{"content":"","type":"context"},{"content":"from typing import Tuple, List, Any, Iterator, TYPE_CHECKING","type":"context"},{"content":"","type":"context"},{"content":"from sqlfluff.core.errors import SQLParseError","type":"added"},{"content":"from sqlfluff.core.string_helpers import curtail_string","type":"context"},{"content":"","type":"context"},{"content":"if TYPE_CHECKING:","type":"context"}]},"modified_entities":[],"added_entities":[],"deleted_entities":[]},{"descriptor":{"old_range":{"start":26,"length":11},"new_range":{"start":27,"length":11},"section":"def check_still_complete("},"line_group":{"all_lines":[{"content":"    \"\"\"Check that the segments in are the same as the segments out.\"\"\"","type":"context"},{"content":"    initial_str = join_segments_raw(segments_in)","type":"context"},{"content":"    current_str = join_segments_raw(matched_segments + unmatched_segments)","type":"context"},{"content":"    if initial_str != current_str:  # pragma: no cover","type":"deleted"},{"content":"        raise RuntimeError(","type":"deleted"},{"content":"            \"Dropped elements in sequence matching! {!r} != {!r}\".format(","type":"deleted"},{"content":"                initial_str, current_str","type":"deleted"},{"content":"            )","type":"deleted"},{"content":"","type":"added"},{"content":"    if initial_str != current_str:","type":"added"},{"content":"        raise SQLParseError(","type":"added"},{"content":"            f\"Could not parse: {current_str}\",","type":"added"},{"content":"            segment=unmatched_segments[0],","type":"added"},{"content":"        )","type":"context"},{"content":"    return True","type":"context"},{"content":"","type":"context"},{"content":"","type":"context"}]},"modified_entities":[],"added_entities":[],"deleted_entities":[]}]}],"old_commit_hash":"304a197829f98e7425a46d872ada73176137e5ae","new_commit_hash":"6650ae48954fa4c3df27e50c089d1bc7c9fac1ad","commit_message":"[issue_1512] SQLParseError imported from proper place","commit_date":"2021-10-08T12:09:06+02:00","metadata":{}}
problem_statement: "Dropped elements in sequence matching" when doubled semicolon
  ## Expected Behaviour
  Frankly, I'm not sure whether it (doubled `;`) should be just ignored or rather some specific rule should be triggered.
  ## Observed Behaviour
  ```console
  (.venv) ?master ~/prod/_inne/sqlfluff> echo "select id from tbl;;" | sqlfluff lint -
  Traceback (most recent call last):
    File "/home/adam/prod/_inne/sqlfluff/.venv/bin/sqlfluff", line 11, in <module>
      load_entry_point('sqlfluff', 'console_scripts', 'sqlfluff')()
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 1137, in __call__
      return self.main(*args, **kwargs)
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 1062, in main
      rv = self.invoke(ctx)
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 1668, in invoke
      return _process_result(sub_ctx.command.invoke(sub_ctx))
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 1404, in invoke
      return ctx.invoke(self.callback, **ctx.params)
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 763, in invoke
      return __callback(*args, **kwargs)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/cli/commands.py", line 347, in lint
      result = lnt.lint_string_wrapped(sys.stdin.read(), fname="stdin")
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 789, in lint_string_wrapped
      linted_path.add(self.lint_string(string, fname=fname, fix=fix))
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 668, in lint_string
      parsed = self.parse_string(in_str=in_str, fname=fname, config=config)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 607, in parse_string
      return self.parse_rendered(rendered, recurse=recurse)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 313, in parse_rendered
      parsed, pvs = cls._parse_tokens(
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 190, in _parse_tokens
      parsed: Optional[BaseSegment] = parser.parse(
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/parser/parser.py", line 32, in parse
      parsed = root_segment.parse(parse_context=ctx)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/parser/segments/base.py", line 821, in parse
      check_still_complete(segments, m.matched_segments, m.unmatched_segments)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/parser/helpers.py", line 30, in check_still_complete
      raise RuntimeError(
  RuntimeError: Dropped elements in sequence matching! 'select id from tbl;;' != ';'
  
  ```
  ## Steps to Reproduce
  Run 
  ```console
  echo "select id from tbl;;" | sqlfluff lint -
  ```
  ## Dialect
  default (ansi)
  ## Version
  ```
  sqlfluff, version 0.6.6
  Python 3.9.5
  ```
  ## Configuration
  None
  
  
patch: diff --git a/src/sqlfluff/core/parser/helpers.py b/src/sqlfluff/core/parser/helpers.py
  --- a/src/sqlfluff/core/parser/helpers.py
  +++ b/src/sqlfluff/core/parser/helpers.py
  @@ -2,6 +2,7 @@
   
   from typing import Tuple, List, Any, Iterator, TYPE_CHECKING
   
  +from sqlfluff.core.errors import SQLParseError
   from sqlfluff.core.string_helpers import curtail_string
   
   if TYPE_CHECKING:
  @@ -26,11 +27,11 @@ def check_still_complete(
       """Check that the segments in are the same as the segments out."""
       initial_str = join_segments_raw(segments_in)
       current_str = join_segments_raw(matched_segments + unmatched_segments)
  -    if initial_str != current_str:  # pragma: no cover
  -        raise RuntimeError(
  -            "Dropped elements in sequence matching! {!r} != {!r}".format(
  -                initial_str, current_str
  -            )
  +
  +    if initial_str != current_str:
  +        raise SQLParseError(
  +            f"Could not parse: {current_str}",
  +            segment=unmatched_segments[0],
           )
       return True
   
   
  
file_context: {"src/sqlfluff/core/parser/helpers.py": "\"\"\"Helpers for the parser module.\"\"\"\n\nfrom typing import Tuple, List, Any, Iterator, TYPE_CHECKING\n\nfrom sqlfluff.core.string_helpers import curtail_string\n\nif TYPE_CHECKING:\n    from sqlfluff.core.parser.segments import BaseSegment  # pragma: no cover\n\n\ndef join_segments_raw(segments: Tuple[\"BaseSegment\", ...]) -> str:\n    \"\"\"Make a string from the joined `raw` attributes of an iterable of segments.\"\"\"\n    return \"\".join(s.raw for s in segments)\n\n\ndef join_segments_raw_curtailed(segments: Tuple[\"BaseSegment\", ...], length=20) -> str:\n    \"\"\"Make a string up to a certain length from an iterable of segments.\"\"\"\n    return curtail_string(join_segments_raw(segments), length=length)\n\n\ndef check_still_complete(\n    segments_in: Tuple[\"BaseSegment\", ...],\n    matched_segments: Tuple[\"BaseSegment\", ...],\n    unmatched_segments: Tuple[\"BaseSegment\", ...],\n) -> bool:\n    \"\"\"Check that the segments in are the same as the segments out.\"\"\"\n    initial_str = join_segments_raw(segments_in)\n    current_str = join_segments_raw(matched_segments + unmatched_segments)\n    if initial_str != current_str:  # pragma: no cover\n        raise RuntimeError(\n            \"Dropped elements in sequence matching! {!r} != {!r}\".format(\n                initial_str, current_str\n            )\n        )\n    return True\n\n\ndef trim_non_code_segments(\n    segments: Tuple[\"BaseSegment\", ...]\n) -> Tuple[\n    Tuple[\"BaseSegment\", ...], Tuple[\"BaseSegment\", ...], Tuple[\"BaseSegment\", ...]\n]:\n    \"\"\"Take segments and split off surrounding non-code segments as appropriate.\n\n    We use slices to avoid creating too many unnecessary tuples.\n    \"\"\"\n    pre_idx = 0\n    seg_len = len(segments)\n    post_idx = seg_len\n\n    if segments:\n        seg_len = len(segments)\n\n        # Trim the start\n        while pre_idx < seg_len and not segments[pre_idx].is_code:\n            pre_idx += 1\n\n        # Trim the end\n        while post_idx > pre_idx and not segments[post_idx - 1].is_code:\n            post_idx -= 1\n\n    return segments[:pre_idx], segments[pre_idx:post_idx], segments[post_idx:]\n\n\ndef iter_indices(seq: List, val: Any) -> Iterator[int]:\n    \"\"\"Iterate all indices in a list that val occurs at.\n\n    Args:\n        seq (list): A list to look for indices in.\n        val: What to look for.\n\n    Yields:\n        int: The index of val in seq.\n\n    Examples:\n        The function works like str.index() but iterates all\n        the results rather than returning the first.\n\n        >>> print([i for i in iter_indices([1, 0, 2, 3, 2], 2)])\n        [2, 4]\n    \"\"\"\n    for idx, el in enumerate(seq):\n        if el == val:\n            yield idx\n"}
filelevel_patches: {"src/sqlfluff/core/parser/helpers.py": "@@ -2,6 +2,7 @@\n \n from typing import Tuple, List, Any, Iterator, TYPE_CHECKING\n \n+from sqlfluff.core.errors import SQLParseError\n from sqlfluff.core.string_helpers import curtail_string\n \n if TYPE_CHECKING:\n@@ -26,11 +27,11 @@ def check_still_complete(\n     \"\"\"Check that the segments in are the same as the segments out.\"\"\"\n     initial_str = join_segments_raw(segments_in)\n     current_str = join_segments_raw(matched_segments + unmatched_segments)\n-    if initial_str != current_str:  # pragma: no cover\n-        raise RuntimeError(\n-            \"Dropped elements in sequence matching! {!r} != {!r}\".format(\n-                initial_str, current_str\n-            )\n+\n+    if initial_str != current_str:\n+        raise SQLParseError(\n+            f\"Could not parse: {current_str}\",\n+            segment=unmatched_segments[0],\n         )\n     return True"}
messages.content: 
  We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  "Dropped elements in sequence matching" when doubled semicolon
  ## Expected Behaviour
  Frankly, I'm not sure whether it (doubled `;`) should be just ignored or rather some specific rule should be triggered.
  ## Observed Behaviour
  ```console
  (.venv) ?master ~/prod/_inne/sqlfluff> echo "select id from tbl;;" | sqlfluff lint -
  Traceback (most recent call last):
    File "/home/adam/prod/_inne/sqlfluff/.venv/bin/sqlfluff", line 11, in <module>
      load_entry_point('sqlfluff', 'console_scripts', 'sqlfluff')()
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 1137, in __call__
      return self.main(*args, **kwargs)
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 1062, in main
      rv = self.invoke(ctx)
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 1668, in invoke
      return _process_result(sub_ctx.command.invoke(sub_ctx))
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 1404, in invoke
      return ctx.invoke(self.callback, **ctx.params)
    File "/home/adam/prod/_inne/sqlfluff/.venv/lib/python3.9/site-packages/click/core.py", line 763, in invoke
      return __callback(*args, **kwargs)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/cli/commands.py", line 347, in lint
      result = lnt.lint_string_wrapped(sys.stdin.read(), fname="stdin")
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 789, in lint_string_wrapped
      linted_path.add(self.lint_string(string, fname=fname, fix=fix))
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 668, in lint_string
      parsed = self.parse_string(in_str=in_str, fname=fname, config=config)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 607, in parse_string
      return self.parse_rendered(rendered, recurse=recurse)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 313, in parse_rendered
      parsed, pvs = cls._parse_tokens(
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/linter/linter.py", line 190, in _parse_tokens
      parsed: Optional[BaseSegment] = parser.parse(
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/parser/parser.py", line 32, in parse
      parsed = root_segment.parse(parse_context=ctx)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/parser/segments/base.py", line 821, in parse
      check_still_complete(segments, m.matched_segments, m.unmatched_segments)
    File "/home/adam/prod/_inne/sqlfluff/src/sqlfluff/core/parser/helpers.py", line 30, in check_still_complete
      raise RuntimeError(
  RuntimeError: Dropped elements in sequence matching! 'select id from tbl;;' != ';'
  
  ```
  ## Steps to Reproduce
  Run 
  ```console
  echo "select id from tbl;;" | sqlfluff lint -
  ```
  ## Dialect
  default (ansi)
  ## Version
  ```
  sqlfluff, version 0.6.6
  Python 3.9.5
  ```
  ## Configuration
  None
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  
  --- BEGIN FILE ---
  ```
  ### src/sqlfluff/core/parser/helpers.py
  """Helpers for the parser module."""
  
  from typing import Tuple, List, Any, Iterator, TYPE_CHECKING
  
  from sqlfluff.core.string_helpers import curtail_string
  
  if TYPE_CHECKING:
      from sqlfluff.core.parser.segments import BaseSegment  # pragma: no cover
  
  
  def join_segments_raw(segments: Tuple["BaseSegment", ...]) -> str:
      """Make a string from the joined `raw` attributes of an iterable of segments."""
      return "".join(s.raw for s in segments)
  
  
  def join_segments_raw_curtailed(segments: Tuple["BaseSegment", ...], length=20) -> str:
      """Make a string up to a certain length from an iterable of segments."""
      return curtail_string(join_segments_raw(segments), length=length)
  
  
  def check_still_complete(
      segments_in: Tuple["BaseSegment", ...],
      matched_segments: Tuple["BaseSegment", ...],
      unmatched_segments: Tuple["BaseSegment", ...],
  ) -> bool:
      """Check that the segments in are the same as the segments out."""
      initial_str = join_segments_raw(segments_in)
      current_str = join_segments_raw(matched_segments + unmatched_segments)
      if initial_str != current_str:  # pragma: no cover
          raise RuntimeError(
              "Dropped elements in sequence matching! {!r} != {!r}".format(
                  initial_str, current_str
              )
          )
      return True
  
  
  def trim_non_code_segments(
      segments: Tuple["BaseSegment", ...]
  ) -> Tuple[
      Tuple["BaseSegment", ...], Tuple["BaseSegment", ...], Tuple["BaseSegment", ...]
  ]:
      """Take segments and split off surrounding non-code segments as appropriate.
  
      We use slices to avoid creating too many unnecessary tuples.
      """
      pre_idx = 0
      seg_len = len(segments)
      post_idx = seg_len
  
      if segments:
          seg_len = len(segments)
  
          # Trim the start
          while pre_idx < seg_len and not segments[pre_idx].is_code:
              pre_idx += 1
  
          # Trim the end
          while post_idx > pre_idx and not segments[post_idx - 1].is_code:
              post_idx -= 1
  
      return segments[:pre_idx], segments[pre_idx:post_idx], segments[post_idx:]
  
  
  def iter_indices(seq: List, val: Any) -> Iterator[int]:
      """Iterate all indices in a list that val occurs at.
  
      Args:
          seq (list): A list to look for indices in.
          val: What to look for.
  
      Yields:
          int: The index of val in seq.
  
      Examples:
          The function works like str.index() but iterates all
          the results rather than returning the first.
  
          >>> print([i for i in iter_indices([1, 0, 2, 3, 2], 2)])
          [2, 4]
      """
      for idx, el in enumerate(seq):
          if el == val:
              yield idx
  
  ```
  --- END FILE ---
  
  Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.
  
  Every *SEARCH/REPLACE* edit must use this format:
  1. The file path
  2. The start of search block: <<<<<<< SEARCH
  3. A contiguous chunk of lines to search for in the existing source code
  4. The dividing line: =======
  5. The lines to replace into the source code
  6. The end of the replace block: >>>>>>> REPLACE
  
  Here is an example:
  
  ```python
  ### mathweb/flask/app.py
  <<<<<<< SEARCH
  from flask import Flask
  =======
  import math
  from flask import Flask
  >>>>>>> REPLACE
  ```
  
  Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
  Wrap the *SEARCH/REPLACE* edit in blocks ```python...```.
  
messages.role: user
verification_info: {"file_context": {"src/sqlfluff/core/parser/helpers.py": "\"\"\"Helpers for the parser module.\"\"\"\n\nfrom typing import Tuple, List, Any, Iterator, TYPE_CHECKING\n\nfrom sqlfluff.core.string_helpers import curtail_string\n\nif TYPE_CHECKING:\n    from sqlfluff.core.parser.segments import BaseSegment  # pragma: no cover\n\n\ndef join_segments_raw(segments: Tuple[\"BaseSegment\", ...]) -> str:\n    \"\"\"Make a string from the joined `raw` attributes of an iterable of segments.\"\"\"\n    return \"\".join(s.raw for s in segments)\n\n\ndef join_segments_raw_curtailed(segments: Tuple[\"BaseSegment\", ...], length=20) -> str:\n    \"\"\"Make a string up to a certain length from an iterable of segments.\"\"\"\n    return curtail_string(join_segments_raw(segments), length=length)\n\n\ndef check_still_complete(\n    segments_in: Tuple[\"BaseSegment\", ...],\n    matched_segments: Tuple[\"BaseSegment\", ...],\n    unmatched_segments: Tuple[\"BaseSegment\", ...],\n) -> bool:\n    \"\"\"Check that the segments in are the same as the segments out.\"\"\"\n    initial_str = join_segments_raw(segments_in)\n    current_str = join_segments_raw(matched_segments + unmatched_segments)\n    if initial_str != current_str:  # pragma: no cover\n        raise RuntimeError(\n            \"Dropped elements in sequence matching! {!r} != {!r}\".format(\n                initial_str, current_str\n            )\n        )\n    return True\n\n\ndef trim_non_code_segments(\n    segments: Tuple[\"BaseSegment\", ...]\n) -> Tuple[\n    Tuple[\"BaseSegment\", ...], Tuple[\"BaseSegment\", ...], Tuple[\"BaseSegment\", ...]\n]:\n    \"\"\"Take segments and split off surrounding non-code segments as appropriate.\n\n    We use slices to avoid creating too many unnecessary tuples.\n    \"\"\"\n    pre_idx = 0\n    seg_len = len(segments)\n    post_idx = seg_len\n\n    if segments:\n        seg_len = len(segments)\n\n        # Trim the start\n        while pre_idx < seg_len and not segments[pre_idx].is_code:\n            pre_idx += 1\n\n        # Trim the end\n        while post_idx > pre_idx and not segments[post_idx - 1].is_code:\n            post_idx -= 1\n\n    return segments[:pre_idx], segments[pre_idx:post_idx], segments[post_idx:]\n\n\ndef iter_indices(seq: List, val: Any) -> Iterator[int]:\n    \"\"\"Iterate all indices in a list that val occurs at.\n\n    Args:\n        seq (list): A list to look for indices in.\n        val: What to look for.\n\n    Yields:\n        int: The index of val in seq.\n\n    Examples:\n        The function works like str.index() but iterates all\n        the results rather than returning the first.\n\n        >>> print([i for i in iter_indices([1, 0, 2, 3, 2], 2)])\n        [2, 4]\n    \"\"\"\n    for idx, el in enumerate(seq):\n        if el == val:\n            yield idx\n"}, "filelevel_patches": {"src/sqlfluff/core/parser/helpers.py": "@@ -2,6 +2,7 @@\n \n from typing import Tuple, List, Any, Iterator, TYPE_CHECKING\n \n+from sqlfluff.core.errors import SQLParseError\n from sqlfluff.core.string_helpers import curtail_string\n \n if TYPE_CHECKING:\n@@ -26,11 +27,11 @@ def check_still_complete(\n     \"\"\"Check that the segments in are the same as the segments out.\"\"\"\n     initial_str = join_segments_raw(segments_in)\n     current_str = join_segments_raw(matched_segments + unmatched_segments)\n-    if initial_str != current_str:  # pragma: no cover\n-        raise RuntimeError(\n-            \"Dropped elements in sequence matching! {!r} != {!r}\".format(\n-                initial_str, current_str\n-            )\n+\n+    if initial_str != current_str:\n+        raise SQLParseError(\n+            f\"Could not parse: {current_str}\",\n+            segment=unmatched_segments[0],\n         )\n     return True"}}