I was reading some code using NOT that was like some [not space, one].
Hence effectively this is some [not ahead space, one] e.g. some number of times look ahead to see a thing isn't a space, then consume one item (whatever the not space thing was).
This made me a bit disgruntled that I couldn't write some not space, which on the surface seems like a coherent thought... vs. something that acts like an some not ahead space e.g. an infinite loop.
In practice any input-consuming combinator has a bit of a coherence problem... because while the letter "A" is not a space, neither is reaching the end of input. So to stop the infinite loop problem you'd have to at the very least omit a test against end.
I'm not even sure what (4) would mean...?
Maybe it means we're missing a concept like negatable combinators, which you can call as parser:not instead of just parser. Then NOT would call the parser negatedly (maybe it's the only combinator that would do so, or maybe there would be others?)
e.g. AHEAD could be a negatable combinator, producing a negatable parser. And maybe a single character, single byte, or single value combinator would be willing to be negated--with the negated rule being any single value that's not that. We could also negate character sets in the same way.
So a string combinator when matching in a BLOCK! could be negated, and matching the end would not count:
>> parse ["alpha"] [not "beta"]
== "alpha"
>> parse [] [not "beta"] ; behave same as e.g. `parse [] ["alpha"]`
** Error: PARSE BLOCK! combinator did not match input
But when matching in a string, it couldn't
>> parse "alpha" [not "beta"]
** Error: TEXT! combinator not negatable when parsing TEXT!
So there'd be a narrow interpretation of cases where it was clear how much a combinator intended to test and consume. If you could say how much it intended to consume... and make a reasoned argument it could consume an equal amount in the negated case. (Any combinator that consumed no input could thus be negatable.)
This strikes me as valuable, as it would give meaning to things like some not space that people would want, and dismiss with the confusion over NOT being implicitly NOT AHEAD.
It may mean that some not space would work, and some not " " would be different in string parsing, e.g. characters would be treated differently than strings of length 1. Or perhaps a NOT of a string that didn't match would always advance one character? :-/
Observation: NOT could itself be a negatable combinator, making NOT NOT work. It just would notice when it was called with :NOT and then use that as a signal to call its combinated parser parameter plainly, vs. using :NOT.