Red's REMOVE [OPT N rule] vs. REMOVE [OPT [N rule]]

I was doing some comparative behavior testing while looking at the UPARSE conversion of TRIM.

As I mention in that post, the comparisons are now more-often-than-not pointing out bugs and inconsistencies in R3-Alpha and Red. UPARSE is the new gold standard. !

Here's a good example of R3-Alpha and Red being broken in their various ways, that will happen indefinitely... until the PARSE methodology changes from being ad-hoc to being architecturally sane. :-/

red>> parse s: "aab" [remove [opt 3 "a"] thru "b"]
== true

red>> s
== "b"

Why did it think there was 3 "a" to remove? I'd guess there are "repeat min-counts" and "repeat max-counts" and "optionality flags" being thrown about. So it confused itself and put the optional flag on the "a", winding up interpreting the rule as:

[remove [3 opt "a"] thru "b"]

How do you keep it from getting its flags crossed? Throw in a block, because then it likely starts a genuine parse recursion and the flags won't mix:

red>> parse s: "aab" [remove [opt [3 "a"]] thru "b"]
== true

red>> s
== "aab"

That's correct...and if you use a BLOCK! like that R3-Alpha also does the right thing:

r3-alpha>> parse s: "aab" [remove [opt [3 "a"]] thru "b"]
== true

r3-alpha>> s
== "aab"

But predictably...without the block, you get an entirely different failure mode; the parse fails altogether:

r3-alpha>> parse s: "aab" [remove [opt 3 "a"] thru "b"]
== false

r3-alpha>> s
== "aab"

Unless you explicitly try to make your combinators look literally at the items in the block--this category of distinction cannot exist in UPARSE. [try repeat 3 "a"] and [try [repeat 3 "a"]] are equivalent in a correct-by-construction sense, and all the combinators that will ever be written get this benefit.

2 Likes