Pattern: a(?(?
Input: a b c
Desription: Condition should match space, if lookbehind is not a space.
It ma
In addition to @revo's answer:
Not only conditional construct with an explicit zero-width assertion as its expression are affected. In fact almost all conditional constructs where condition expressions are parenthesized regexes (grouping, conditional, other special) used without extra parenthesis are affected.
There are four types of (mis)behaviour in such cases:
Capture group array gets mangled (as pointed out by the OP), namely the capture group immediately following the conditional construct is lost the other groups are shifted left leaving the last capture group undefined.
In the following examples the expected capture allocation is
$1="a", $2="b", $3="c"
while the actual result is
$1="a", $2="c", $3="" (the latter is empty string)
Applies to:
Throws ArgumentException at run time when the regex is parsed. This actually makes sense since this explicitly warns us of some potential regex error rather than playing funny tricks with captures as in the previous case.
Applies to:
(a)(?(?.) )(b) (c) , (a)(?(?'n'.) )(b) (c) - named groups - exception message: "Alternation conditions do not capture and cannot be named"(a)(?(?'-n' .) )(b) (c), (?a)(?(?.) )(b) (c) - balancing groups - exception message: "Alternation conditions do not capture and cannot be named"(a)(?(?# comment) )(b) (c) - inline comment - exception message: "Alternation conditions cannot be comments"Throws OutOfMemoryException during pattern match.
This is clearly a bug, as of my belief.
Applies to:
(a)(?(?i) )(b) (c) - inline options (not to be confused with group options)[Surprisingly] works as expected but this is rather too artificial example:
All these regexes may be fixed by enclosing the condition expression into explicit parenthesis (i.e. extra ones if the expression itself already contains parenthesis). Here are the fixed versions (in the order of appearance):
(a)(?((?=.)) )(b) (c)
(a)(?((?!z)) )(b) (c)
(a)(?((?<=.)) )(b) (c)
(a)(?((?.)) )(b) (c)
(a)(?((?(1).)) )(b) (c)
((?a))(?((?(n).)) )(b)(c)
(a)(?((?(?:.).)) )(b) (c)
(a)(?((?.)) )(b) (c)
(a)(?((?'n'.)) )(b) (c)
(a)(?((?'-n' .)) )(b) (c)
(?a)(?((?.)) )(b) (c)
(a)(?((?# comment)) )(b) (c)
(a)(?((?i)) )(b) (c)
(a)(?((?(.).)) )(b) (c)
Sample code to check all these expressions: https://ideone.com/KHbqMI