Skip to content

Decode && / || boolean operators when re-emitting from BNG-XML#76

Open
wshlavacek wants to merge 1 commit intoRuleWorld:mainfrom
wshlavacek:modelapi-decode-xml-boolean-ops
Open

Decode && / || boolean operators when re-emitting from BNG-XML#76
wshlavacek wants to merge 1 commit intoRuleWorld:mainfrom
wshlavacek:modelapi-decode-xml-boolean-ops

Conversation

@wshlavacek
Copy link
Copy Markdown

Summary

BNG2.pl's <Expression> serializer rewrites the binary operators && and || as the function-call-shaped strings (L)and(R) and (L)or(R) (see Perl2/Expression.pm: '&&' => 'and'). When bionetgen.modelapi reads <Expression> verbatim and re-emits the function body into a regenerated .bngl, BNG2.pl's BNGL parser sees and(...) as a function call and aborts:

Missing end parentheses ... at and(t>=0))

This breaks any round-trip workflow (parse a BNGL → regenerate it → re-run with BNG2.pl) for models that use boolean operators inside function bodies. Smallest repro is a function like:

toggle = if((plusBafA1==1) && (t>=0), 0, 1)

After XML round-trip this becomes if((plusBafA1==1)and(t>=0), 0, 1) which BNG2.pl rejects.

Fix

In bionetgen/modelapi/xmlparsers.py, add a regex pass that maps )and() && ( and )or() || ( before storing the function expression. The match is intentionally anchored on the close-paren of the left operand because BNG2.pl always wraps both operands in parens for these forms — so )and( / )or( only ever appear as the boolean-operator encoding and never as the tail of a user-defined identifier (e.g. random(x)) or a literal function call.

Test plan

  • Existing CI passes
  • Round-trip a model with && / || in a function body: parse → write_model → BNG2.pl simulate
  • Verify random(x) + myop(y) is preserved verbatim (no spurious rewrites of )and(-shaped substrings that aren't actually boolean ops — there shouldn't be any, but worth checking)

BNG2.pl's <Expression> serializer rewrites the binary operators ``&&`` and
``||`` as the function-call-shaped strings ``(L)and(R)`` and ``(L)or(R)``
(see Perl2/Expression.pm: '&&' => 'and'). Reading <Expression> verbatim
and re-emitting it into a regenerated .bngl file confuses BNG2.pl's BNGL
parser, which sees ``and(...)`` as a function call and aborts with
"Missing end parentheses ... at and(...)".

Fix: in xmlparsers, run a regex pass that maps ``)and(`` → ``) && (`` and
``)or(`` → ``) || (`` before storing the function expression. The match
is anchored on the close-paren of the left operand because BNG2.pl always
wraps both operands in parens for these forms — so ``)and(`` / ``)or(``
only ever appear as the boolean-operator encoding and never as the
suffix of a user identifier or a literal function call.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant