From a46c75d59cca1da9516d13cb8baaefe7585bc884 Mon Sep 17 00:00:00 2001 From: Aaron Zuspan <50475791+aazuspan@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:05:42 -0700 Subject: [PATCH] Fix parsing of partial float literals (#33) --- src/spinasm_lsp/parser.py | 14 ++++++++++---- tests/test_parser.py | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/spinasm_lsp/parser.py b/src/spinasm_lsp/parser.py index 2540b94..9fbbc4c 100644 --- a/src/spinasm_lsp/parser.py +++ b/src/spinasm_lsp/parser.py @@ -2,6 +2,8 @@ from __future__ import annotations +import contextlib + import lsprotocol.types as lsp from asfv1 import fv1parse @@ -64,10 +66,14 @@ def __next__(self) -> None: current_line_txt = self._source[self._current_line] current_symbol = self.parsed_symbol.txt - # Start at the current column to skip previous duplicates of the symbol - self._current_character = current_line_txt.index( - current_symbol, self._current_character - ) + # Update the current parsed character. This can fail under rare circumstances, + # in which case we'll leave _current_character unchanged. + # See https://github.com/aazuspan/spinasm-lsp/issues/31 + with contextlib.suppress(ValueError): + # Start at the current column to skip previous duplicates of the symbol + self._current_character = current_line_txt.index( + current_symbol, self._current_character + ) class SPINAsmDiagnosticParser(SPINAsmPositionParser): diff --git a/tests/test_parser.py b/tests/test_parser.py index cdbce3c..bf4cc3c 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -46,3 +46,26 @@ def test_example_patches(patch, data_regression): encoded = serialize_parser_output(parser) data_regression.check(encoded) + + +def test_parsing_as_typed(): + """Test that the parser is fault tolerant for partially entered programs.""" + + # Example program from SPINAsm documentation. Iteratively parsing at each character + # is slow, so we use a small sample program here rather than parameterizing over the + # larger test patches. + source = """ + ; Example program from SPINAsm documentation + Attn EQU 0.5 + Tmp_Reg EQU 63 + Tmp_Del EQU $2000 + + sof 0,0 + rda Tmp_Del,Attn + wrax Tmp_Reg,1.0 + wrax DACL + """ + source_chars = list(source) + for i in range(len(source_chars)): + partial_source = "".join(source_chars[:i]) + assert SPINAsmParser(partial_source)