robrix / Madness

Recursive Descent Into Madness
MIT License
291 stars 17 forks source link

“Not” combinator #51

Closed robrix closed 8 years ago

robrix commented 9 years ago

Matches any character not matched by the argument parser.

davidcairns commented 9 years ago

What’s the implication of noting a multi-character pattern? (I am a dumb hairless ape).

robrix commented 9 years ago

@davidcairns: TL;DR: Makes no different how many characters the pattern matches (zero, one, n), it’s whether it returns nil or not.

!a would match a single character iff a does not match; so it doesn’t matter if a would consume input because we don’t care how much it consumes, we just care whether it matches or fails.

My current thinking is that it’d be better to do zero-width negative lookahead instead. In that model, ?!a would never consume any input, but would succeed iff a does not match. Then you’d do ?!a ++ b to allow b to parse when a cannot.

This works because parser combinators return (/*parseTree: */ T, /*restOfInput:*/ String)?, so they can return the input unmodified in the tuple to do this. And they indicate failure by returning nil, so we can unambiguously determine whether they matched zero characters or failed.

Here’s an example using ?! to recover the behaviour described at top (parsing any single character not matched by its argument):

let quote = ignore("\"")
let string = quote ++ (?!quote ++ any)* ++ quote
davidcairns commented 9 years ago

OHHHHHHHHHH I get it now.

bencochran commented 8 years ago

Given the less-regex-y API direction in #110 (removal of postfix * and +). Any opinions on what operator/name this should have? /cc @joshvera

joshvera commented 8 years ago

@bencochran I’ve been stealing names from Parsec and Lightyear, so I’m a fan of not or notFollowedBy. I think this might be Parsec’s notFollowedBy.

bencochran commented 8 years ago

Added in #111