The Cool New Repurposing of WHILE in PARSE

Historical Redbol PARSE had some cognitive dissonance over its "looping constructs".

One weird point was that WHILE was an arity-1 construct...a peculiar variant of a "looping ANY" which dropped the requirement of a need to make progress. :confused:

Just as ANY could be improved by making it do something more "obvious", I think the obvious solution for WHILE is also the better one:

So now, default PARSE has WHILE and it's arity-2 !

These two things are synonyms:

 while rule1 rule2   <=>  opt some [rule1 rule2]

One very common application is WHILE [NOT <END>] [...]

This is such a clear case it's bizarre that no one seemed to go to bat for it before.

It would make it cleaner to pair up code in a GROUP! with a rule:

GROUP! rules always run their side effect and succeed. So:

opt some [rule (code to run on each match)]

Could instead be written as:

while rule (code to run on each match)

I would use this frequently!

It helps pscyhologically divide a process into two parts: trigger and response

You can of course write things as:

opt some [
     thing1 thing2 [
        thing3 thing4
     |  thing5 thing6
     ]
]

Or:

opt some [thing1 thing2 [
    thing3 thing4
        |
   thing5 thing6
]]

But I think the WHILE structuring into a control half and response half helps you see this better:

while [thing1 thing2] [
    thing3 thing4
        |
    thing5 thing6
]
3 Likes

I like WHILE as described here and the improved consistency of ANY and ALL.

1 Like

So there's something actually a little bit unfortunate here, in that there are two possible intents for WHILE's interpretation of the condition:

  1. WHILE rule1 has a successful match

  2. WHILE rule1 creates a non-null product

Since it's a PARSE construct, it's formulated as [1].

This means it's a little sad that if you have a logic condition and you want to use it, you have to write:

 while [when (true? flag)] ...

Though you don't need the brackets if you don't want them.

 while when (true? flag) ...

Prior to Flexible Logic, you could use a GET-GROUP! and say:

 while :(flag) ...

But now, you can't do that... if your flag is a boolean or similar, you need to test it and produce OKAY or NULL. Then because splicing semantics consider NULL too potentially an error. So if you wanted a GET-GROUP! it would look like:

 while :(maybe true? flag) ...

It's not terrible, but GET-GROUP! may be going away, at which point this would be:

 while reparse (maybe true? flag) ...

At which point you should have just done while when (true? flag)

Could WHILE Do Both? (stop on no match or null product)

Nope.

>> parse "aabcabaaabc" [while [x: [some "a" "b" opt "c"]] (probe x)]
"c"
~null~  ; anti
"c"

NULL-producing rules are valid for WHILE, they can't stop the iteration.

Could You Drive It With The /WHILE Action Combinator?

No, that wouldn't do what you wanted. Calling the /WHILE combinator really just gives the WHILE native a condition block and body block, and has no interaction with PARSE again until that code is finished.

Could You Use GET-GROUP! With Flag As ~okay~ vs [BYPASS]?

Yes, you can do that. For the "just keep going" case you can use ~okay~ antiform, ~void~ antiform, an empty rule block... anything of that sort.

I would suggest not calling it "flag" if you do that, but calling it some term related to "guard", because you're saying it's a parse rule.

Then it just becomes as simple as while guard ... I think OKAY is the best choice of the passing options, as it gives you a reasonably literate way to talk about it in imperative code: if okay? guard to ask if the guard will continue the parse.

This is probably a good fit if you're in control of the flag state. If it's coming from somewhere else and not under your purview, guess it's best to use while when (...).

It is a little bit sad that UPARSE won't let you just say guard: 'bypass and treat that as a rule, making you use guard: [bypass]. Maybe for the case of single-arity combinators, that should be allowed (definitely not allowed for multi-arity combinators). I'll think about it.