Repository navigation
fix(scripting): accept double-quoted string literals in script expressions - #42
Merged
griswaldbrooks merged 2 commits intoOct 15, 2026
Merged
Conversation
The 4.9 tokenizer only recognized single quotes, so existing Script and precondition expressions failed on their opening double quote. Recognize both delimiters and require the closing quote to match the opening one. Cover the reported Objective expressions, quote parity and malformed strings, and XML Script/precondition attributes using ". Refs PickNikRobotics/moveit_pro#23851
dv-picknik
approved these changes
Oct 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Fix moveit_pro issue https://github.com/PickNikRobotics/moveit_pro/issues/23851 in PickNik's BehaviorTree.CPP fork, so double-quoted string literals in BT Script and precondition expressions parse again and customer behavior trees keep working on upgrade to MoveIt Pro 10.2.
Context: MoveIt Pro 10.2.0-rc4 pins ros-jazzy-behaviortree-cpp-picknik 4.9.0 (10.1 shipped 4.7.2). Under 4.9.0, any expression with a double-quoted string fails at tree creation with
Invalid token '"' at position N, for exampleviz_marker_name:="place_pose_"..viz_idx,mask_label:="mask "..index,tool_object_name!="",execute_trajectories == "true",header := "SAM3 prompt="..prompt. The same expressions with single quotes parse. The 4.7.2-line grammar accepted both quote styles (include/behaviortree_cpp/scripting/any_types.hpp, StringLiteral with single_quoted and quoted, around lines 129-133 at a109849). Eleven shipped example Objectives in moveit_pro_example_ws (lab_sim Pick All Pill Bottles, nine factory_sim entries, hangar_sim Calibrate SAM3 Mask Areas) fail this way.Deliverable: a fork PR restoring double-quoted string literal support.
What Changed
src/script_tokenizer.cpp) treats"as a string-literal delimiter again, alongside'. The closing quote must match the opening one, so'say "hello"'and"it's ready"both parse, and"abc'/'abc"are still rejected as unterminated. This restores what the 4.7.2 grammar accepted: expressions likeviz_marker_name:="place_pose_"..viz_idxandtool_object_name!=""no longer fail at tree creation withInvalid token '"'.tests/script_parser_test.cpp:StringLiteralQuotescovers both quote styles: empty strings, a quote of the other style inside a literal, backslashes, newlines, concatenating a single-quoted literal with a double-quoted one, and unterminated or mismatched literals.DoubleQuotedObjectiveExpressionsruns the expressions reported from the MoveIt Pro example Objectives.DoubleQuotedXmlScriptAndPreconditionsbuilds a tree from XML that uses"strings in<Script code>,_failureIf, and_successIf.CLAUDE.md.🤖 Generated with Claude Code
Risk Assessment
✅ Low: A 3-line change to the one shared tokenizer that every Script, ValidateScript and precondition path goes through. A bare
"was always an Error token before, so no expression that parsed before can now parse differently. It also matches the 4.7.2 lexy grammar (single_quoted | quotedon ascii characters): the closing quote must match the opener, there is no escape processing, and newlines inside strings are allowed.Testing
I built the base and fixed library versions inside the workspace and drove both through real
BehaviorTreeFactoryconsumers, using the issue's expressions and the actual v10.2 moveit_pro_example_ws Objective XMLs. On base, all 7 distinct double-quoted shipped expressions and 19 Objective trees fail with the issue's exactInvalid token '"'error. With the fix, all 79 shipped expressions parse, all 178 Objective trees in lab_sim, factory_sim and hangar_sim create without error, and the expressions evaluate to the right values (place_pose_3,mask 2,SAM3 prompt=bottles threshold=0.5 returned 4 masks...). Single-quoted strings, quotes of the other kind nested inside a literal, and rejection of mismatched or unterminated quotes all still behave correctly. The new parser tests fail on base and pass with the fix, and the existing pre/postcondition tests pass. Real MoveIt Pro Behaviors were stand-in stubs, because the MoveIt Pro runtime is not available here. Script parsing itself always ran through the real library. This is a C++ library change with no UI, so there are no screenshots. Build outputs and the downloaded workspace snapshot have been removed from the worktree.TREE CREATION FAILED: Invalid token '"' at position 17. Fixed gives status SUCCESS with viz_marker_name="place_pose_3", mask_label="mask 2", header="SAM3 prompt=bot…_failureIf='name == ""'fails for an empty nameInvalid token '"mask '..index' at position 9andError in the script "tool_object_name != "" Invalid token '"' at position 20, exit 2Evidence: Consumer app transcript: issue expressions and adversarial XML trees, base vs fixed
Evidence: Shipped example_ws v10.2 expressions: ParseScript base vs fixed summary
base: parsed=72 failed=7 (each: Invalid token '"' at position N, e.g. viz_marker_name:="place_pose_"..viz_idx -> position 17) fixed: parsed=79 failed=0Evidence: Shipped double-quoted expressions executed in a tree (fixed build)
Evidence: Real Objective createTree results, fixed build (lab_sim)
Evidence: Real Objective createTree results, fixed build (factory_sim)
Evidence: Real Objective createTree results, fixed build (hangar_sim)
Evidence: Real Objective createTree results, base build (factory_sim: 17 Invalid token failures)
Evidence: Objective createTree summary, base vs fixed
Evidence: ParserTest results on base (3 new tests fail)
Evidence: ParserTest results on fixed build (all pass)
~/.no-mistakes/evidence/01M50FZ038TKQZCP30Y8FYFE7E/harness)Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
TREE CREATION FAILED: Invalid token '"' at position 17. Fixed gives status SUCCESS with viz_marker_name="place_pose_3", mask_label="mask 2", header="SAM3 prompt=bot…_failureIf='name == ""'fails for an empty nameInvalid token '"mask '..index' at position 9andError in the script "tool_object_name != "" Invalid token '"' at position 20, exit 2Builtlibbehaviortree_cpp_picknik.so.4.9.0at the base (f8a8fe7) and fixed (70b4988) commits, plus googletest v1.14 built inside the workspace. GTest, SQLite and ZeroMQ are not installed on the host.script_parser_test --gtest_filter='ParserTest.*'compiled against the fixed lib (21/21 pass) and against the base lib (the 3 new tests StringLiteralQuotes, DoubleQuotedObjectiveExpressions and DoubleQuotedXmlScriptAndPreconditions fail, which reproduces the bug)bt_run <tree.xml> key=type:value...: a consumer app that loads an XML file withBehaviorTreeFactory::createTreeFromFile, ticks it and prints the blackboard. Ran 9 cases on base and fixed: the issue's expressions across Script, ScriptCondition, Precondition if, _skipIf, _onSuccess and _successIf; raw"inside a single-quoted XML attribute; mixed quote styles; mismatched and unterminated quotes; a single-quoted control casebt_validate(BT::ParseScript) on all 79 unique script/precondition expressions pulled from moveit_pro_example_ws v10.2 Objective XMLs (commit f11fc2a), base vs fixedbt_run example_ws_dq_expressions_tree.xml: ran the shipped double-quoted expressions with seeded values and checked the resulting stringsbt_load_objectives: registered every Objective XML in the lab_sim, factory_sim and hangar_sim objectives/ dirs, with generated stand-in nodes for MoveIt Pro Behaviors (built-in Script, ScriptCondition and Precondition nodes stay real), then calledcreateTree()on every Objective, base vs fixedgtest_preconditions.cpp+gtest_postconditions.cppcompiled against the fixed lib (16/16 pass), as a regression check of other script-condition parsing✅ **Document** - passed
✅ No issues found.
src/script_tokenizer.cpp- The clang-tidy pre-commit hook skipped itself because clangd-21 is not installed and there is no build/compile_commands.json, so the changed files (src/script_tokenizer.cpp, tests/script_parser_test.cpp) got no static analysis. clang-format, codespell and the standard hooks all passed. To cover this, run ./run_clang_tidy.sh in an environment that has clang-tidy-21 and a configured build.✅ **Push** - passed
✅ No issues found.