in src/core/Node.hack [634:703]
private function validateChildrenExpression(
ReflectionXHPChildrenExpression $expr,
int $index,
): (bool, int) {
switch ($expr->getType()) {
case XHPChildrenExpressionType::SINGLE:
// Exactly once -- :fb_thing
return $this->validateChildrenRule($expr, $index);
case XHPChildrenExpressionType::ANY_NUMBER:
// Zero or more times -- :fb_thing*
do {
list($ret, $index) = $this->validateChildrenRule($expr, $index);
} while ($ret);
return tuple(true, $index);
case XHPChildrenExpressionType::ZERO_OR_ONE:
// Zero or one times -- :fb_thing?
list($_, $index) = $this->validateChildrenRule($expr, $index);
return tuple(true, $index);
case XHPChildrenExpressionType::ONE_OR_MORE:
// One or more times -- :fb_thing+
list($ret, $index) = $this->validateChildrenRule($expr, $index);
if (!$ret) {
return tuple(false, $index);
}
do {
list($ret, $index) = $this->validateChildrenRule($expr, $index);
} while ($ret);
return tuple(true, $index);
case XHPChildrenExpressionType::SUB_EXPR_SEQUENCE:
// Specific order -- :fb_thing, :fb_other_thing
$oindex = $index;
list($sub_expr_1, $sub_expr_2) = $expr->getSubExpressions();
list($ret, $index) = $this->validateChildrenExpression(
$sub_expr_1,
$index,
);
if ($ret) {
list($ret, $index) = $this->validateChildrenExpression(
$sub_expr_2,
$index,
);
}
if ($ret) {
return tuple(true, $index);
}
return tuple(false, $oindex);
case XHPChildrenExpressionType::SUB_EXPR_DISJUNCTION:
// Either or -- :fb_thing | :fb_other_thing
$oindex = $index;
list($sub_expr_1, $sub_expr_2) = $expr->getSubExpressions();
list($ret, $index) = $this->validateChildrenExpression(
$sub_expr_1,
$index,
);
if (!$ret) {
list($ret, $index) = $this->validateChildrenExpression(
$sub_expr_2,
$index,
);
}
if ($ret) {
return tuple(true, $index);
}
return tuple(false, $oindex);
}
}