Skip to content

Commit 3a63ff4

Browse files
yahocanalexzhang13
andauthored
fix: use greedy matching in FINAL pattern to handle nested parentheses (#75)
* fix: use greedy matching in FINAL pattern to handle nested parentheses * parsing on test --------- Co-authored-by: Alex Zhang <alex.lx.zhang@gmail.com>
1 parent b052ed1 commit 3a63ff4

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

‎rlm/utils/parsing.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ def find_final_answer(text: str, environment: "BaseEnv | None" = None) -> str |
5454
return None
5555

5656
# Check for FINAL pattern - must be at start of line
57-
final_pattern = r"^\s*FINAL\((.*?)\)"
57+
# Use greedy matching to capture content with nested parentheses
58+
final_pattern = r"^\s*FINAL\((.*)\)\s*$"
5859
match = re.search(final_pattern, text, re.MULTILINE | re.DOTALL)
5960
if match:
6061
return match.group(1).strip()

‎tests/test_parsing.py‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,33 @@ def test_final_with_whitespace(self):
128128
result = find_final_answer(text)
129129
assert result == "answer with spaces"
130130

131+
def test_final_with_nested_parentheses_greedy_matching(self):
132+
"""Test that greedy matching captures content with nested parentheses correctly.
133+
Greedy matching (.*) matches to the last closing parenthesis, correctly handling
134+
nested parentheses in FINAL() content. Non-greedy (.*?) would incorrectly stop
135+
at the first closing parenthesis, breaking functions, tuples, and nested structures.
136+
"""
137+
# Function call with nested parentheses
138+
text = "FINAL(func(arg1, arg2))"
139+
result = find_final_answer(text)
140+
assert result == "func(arg1, arg2)"
141+
142+
# List and tuple with multiple closing parentheses
143+
text = "FINAL([1, 2, 3], (4, 5))"
144+
result = find_final_answer(text)
145+
assert result == "[1, 2, 3], (4, 5)"
146+
147+
# Complex nested dictionary
148+
text = "FINAL({'key': 'value', 'nested': {'a': 1, 'b': 2}})"
149+
result = find_final_answer(text)
150+
assert "'key': 'value'" in result
151+
assert "'nested':" in result
152+
153+
# Multiple function calls with nested parentheses
154+
text = "FINAL(calculate(10, 20) + process(data))"
155+
result = find_final_answer(text)
156+
assert result == "calculate(10, 20) + process(data)"
157+
131158
def test_final_and_final_var_parsing(self):
132159
"""Test that both FINAL and FINAL_VAR patterns are parsed correctly."""
133160
# Test FINAL with various content types

0 commit comments

Comments
 (0)