I want to transform
test: "bla bla %bla bla% bla bla bla bla %bla% bla"
into
test: "bla bla <bla bla> bla bla bla bla <bla> bla"
with this code, it doesn't work in red:
rules: [
(toggle: -1)
to "%" mark: (
(toggle: 0 - toggle)
either (toggle = 1) [change mark {<}][change mark {>}]
)
thru "%"
|
to end
]
parse test rules
Output is
>> test
== "bla bla <bla bla% bla bla bla bla %bla% bla"
Your rules need a little more care, especially when using the keywords
'to
and'thru
. The way your rule is written the replacement will occur once and thento end
will advance you to the end of the input -- not what you want.I'll step through it slowly.
The first rule, the
to "%"
, this advances the input to the first "%" character. It's a successful rule so your parens expression executes and modifies the input, i.e., changes the "%" to a "<". All good there: the first replacement is complete and the very next char in the input is now "<". BUT your next rule isthru "%"
. This advances the input past the next "%" character in the input-- a char you want changed to ">".The other key piece here (as HostileFork points out) is that your replacement rule is not repeating. Your parse rule runs once and then it's over. Your alternative rule
to end
then takes over and jumps the input all way to the end. In order to get a rule to scan repeatedly through the entire input you need to set up your rule with asome
,any
,while
orskip
.Here's a quick rework of your rule leaving most of your code in place but achieving the result I think you want.
There are other things in the code that I would probably change, such as the toggle, and you can see I got rid of unecessary parentheses, but for now I'm forcusing on the way
parse
works.Two solutions: one without parse
and one with parse
and one for fun
You don't have any iterative construct in your parse rule (SOME, ANY, WHILE, etc.) So it shouldn't be surprising it does one replacement and stops.
This will give you the desired output, and has a couple other changes for consideration (though just including the
any [... | skip]
modification would have fixed your code):(I'm not the biggest fan of using PICK with a LOGIC!...it gives you the first element if true and the second if false, but throwing it in here for fun.)