For reasons that I imagine were performance-oriented, the original design of PARSE did not use PATH!s. So instead of INSERT/ONLY the sequence of INSERT ONLY was two keywords. This resulted in a kind of variadic behavior (which is more awkward for the UPARSE combinators, because of the consistency of their patterns in argument gathering).
With UPARSE, I didn't see any real reason why a combinator couldn't have refinements. So I went ahead and threw an /ONLY on.
>> uparse [[a b] [c d]] [ collect [some [ keep/only ([keeping a block]) keep/only block! ]] ] == [[keeping a block] [a b] [keeping a block] [c d]]
But /ONLY is on its way out. The concept is you quote things, using a new "arsenal of quoting mechanics".
So what can you do?
I'd already had it so that ^[rule] would act just like [rule] but literalize the result.
>> uparse [a] [^[word!]] == 'a
But I was using ^word, ^pa/th, ^tu.p.le, and ^(gr o up) to mean "match the literal thing".
>> pattern: [some integer!] >> did uparse [[some integer!] [some integer!]] [some '[some integer!]] == #[true] >> did uparse [[some integer!] [some integer!]] [some ^pattern] == #[true]
If you squint, it sort of lines up. There's quoting involved; but it adds a level to the rule, not the synthesized result.
But it would be a waste to have the careted ^[a block] mean literally match [a block], since that's already what the quoted '[a block] means. So I'd gone with this other meaning.
Going back to our example, it forces us to use blocks around the rules in order to get the caret benefit:
>> uparse [[a b] [c d]] [ collect [some [ keep ^[([keeping a block])] keep ^[block!] ]] ] == [[keeping a block] [a b] [keeping a block] [c d]]
That's obnoxious. So I changed it to where ^ always means to quote the synthesized rule product.
>> uparse [[a b] [c d]] [ collect [some [ keep ^([keeping a block]) keep ^block! ]] ] == [[keeping a block] [a b] [keeping a block] [c d]]
Due to the ability to use plain ACTION!s as combinators by ending in /, you have that option...as well as to put your quotes inside a GROUP! if you're running code:
>> uparse [[a b] [c d]] [ collect [some [ keep (quote [keeping a block]) keep quote/ block! ]] ] == [[keeping a block] [a b] [keeping a block] [c d]]
And we can always make QUOTE a combinator so the / isn't needed, if we think that's worthwhile.
(While we're on the subject, doesn't it really seem like keep quote block! makes more sense than keep only block!? It's like it means what it says, and the mechanics all tie it together.)
We'll Need Something Else for Lookup and Match Exactly
I still think the @ variants seem palatable for the purpose:
>> pattern: [some integer!] >> did uparse [[some integer!] [some integer!]] [some @pattern] == #[true]
It could be a named combinator like EXACT, but the issue there is it would need to either quote its argument or it becomes inconvenient:
>> did uparse [[some integer!] [some integer!]] [some exact (pattern)] == #[true]
This is one of the nice things about using the datatype as a combinator, in that it can break outside the rhythm of what plain expressions do and seem to justify it. It's not that we can't take the arguments literally and fetch a variable without a GROUP!, but explaining that some exact pattern and some exact [pattern] aren't identical becomes a tax. :-/
What makes me nervous about this is if @[...] is used for datatypes, and I wouldn't like the overlap there. It may be that datatypes really just use something else, not yet designed. I dunno.
Seems Like Clearly the Right Adjustment
Having all of the ^ family of operators act consistently and give the quoting really makes it nice for living in a post-ONLY world.
The way I've done it is neat because it's dynamic and inherits whatever the base is. So if you change the combinator for BLOCK! or WORD!, the ^[...] and ^xxx combinators will change to quote whatever they do. But you can also override these combinators if you want as well.