From: Suraj Kurapati Date: 2011-11-11T09:00:27+09:00 Subject: [ruby-core:40932] [ruby-trunk - Feature #5588] add negation flag (v) to Regexp Issue #5588 has been updated by Suraj Kurapati. Allow me to explain the current embedded negated regexp implementation. When parsing an embedded negated regexp (?v:r), we expand them into this: OP_NEGATE_START(?:r)?OP_NEGATE_END.*? Here, OP_NEGATE_START and OP_NEGATE_END are opcodes in compiled pattern. When the regexp engine (see match_at() in regexec.c) reaches OP_NEGATE_START, we store the current state of input (up to which character of the input string have we consumed/matched so far?) in the "snegate" variable. The regexp engine then continues onward and eventually reaches OP_NEGATE_END. At this point, I compare the current state of input with "snegate". This tells us if the original embedded negated regexp (?v:r) has matched anything. Now we perform the negation: If (?v:r) matched something, then treat this as a mismatch (prevent backtrack and goto fail). Otherwise, continue processing (the ".*?" after OP_NEGATE_END will take care of consuming any non-matching characters so that we can still proceed). assert_no_match(/a(?v:b)c/, "abc") assert_match(/a(?v:b)c/, "axc") assert_match(/a(?v:b)c/, "ac") assert_match(/a(?v:b)c/, "axbc") I hope this helps you understand my approach. Please correct me if I made a mistake. Thanks for your consideration. ---------------------------------------- Feature #5588: add negation flag (v) to Regexp http://redmine.ruby-lang.org/issues/5588 Author: Suraj Kurapati Status: Open Priority: Normal Assignee: Category: Target version: Please add a negation flag (v) to regexps which inverts them: "ruby" =~ /perl/v #=> true (turn on negation) "ruby" !~ /perl/v #=> false (turn on negation) "ruby" =~ /(?v:perl)/ #=> true (turn on negation) "ruby" !~ /(?v:perl)/ #=> false (turn on negation) "ruby" =~ /(?-v:perl)/ #=> false (turn off negation) "ruby" !~ /(?-v:perl)/ #=> true (turn off negation) The flag name "v" comes from the ex(1) command of the same name. This has beneficial applications where it is sometimes difficult to construct what you want to match but much easier to construct what you *do not* want to match. Having this negation built in the regexp itself would remove the need for us to change our Ruby code to process a regexp in a different way. For example, suppose that you are passing a regexp to the `--name` command-line option of MiniTest. This regexp tells MiniTest to only run those tests whose names match. If Ruby had a negation flag on its regexps, then it would be suddenly trivial to make MiniTest skip certain tests by negating the regexp we pass in. In this manner, we get a beneficial feature without ever changing our Ruby code (the codebase of MiniTest in this example). :-) Thanks for your consideration. -- http://redmine.ruby-lang.org