diff --git a/bionetgen/modelapi/bngparser.py b/bionetgen/modelapi/bngparser.py index 33fab560..6d3c3599 100644 --- a/bionetgen/modelapi/bngparser.py +++ b/bionetgen/modelapi/bngparser.py @@ -27,9 +27,43 @@ def _normalize_action_text(action: str) -> str: """ text = _strip_comment_outside_quotes(action) text = _collapse_unquoted_whitespace(text) + text = _strip_unquoted_backslashes(text) return text.strip() +def _strip_unquoted_backslashes(text: str) -> str: + """Drop ``\\`` characters that appear outside string literals.""" + return _filter_outside_quotes(text, lambda ch: ch != "\\") + + +def _filter_outside_quotes(text: str, keep) -> str: + out = [] + in_single = False + in_double = False + escaped = False + for ch in text: + if escaped: + out.append(ch) + escaped = False + continue + if ch == "\\" and (in_single or in_double): + out.append(ch) + escaped = True + continue + if ch == '"' and not in_single: + in_double = not in_double + out.append(ch) + continue + if ch == "'" and not in_double: + in_single = not in_single + out.append(ch) + continue + if not in_single and not in_double and not keep(ch): + continue + out.append(ch) + return "".join(out) + + def _strip_comment_outside_quotes(text: str) -> str: out = [] in_single = False diff --git a/tests/test_bng_parsing.py b/tests/test_bng_parsing.py index 23bd8966..b0d63e07 100644 --- a/tests/test_bng_parsing.py +++ b/tests/test_bng_parsing.py @@ -73,3 +73,20 @@ def test_pattern_canonicalization(): break # assert that everything matched up assert res is True + + +def test_action_normalization_drops_stray_backslashes_outside_quotes(): + from bionetgen.modelapi.bngparser import _normalize_action_text + + out = _normalize_action_text( + 'parameter_scan({n_scan_pts=>101,\\log_scale=>1,method=>"ode"})' + ) + assert "\\" not in out + assert "log_scale=>1" in out + + +def test_action_normalization_preserves_backslashes_inside_quotes(): + from bionetgen.modelapi.bngparser import _normalize_action_text + + out = _normalize_action_text('action({arg=>"a\\b"})') + assert '"a\\b"' in out