in src/lexer/PhutilLexer.php [104:227]
protected function getRules() {
$class = get_class($this);
$raw_rules = $this->getRawRules();
if (!is_array($raw_rules)) {
$type = gettype($raw_rules);
throw new UnexpectedValueException(
pht(
'Expected %s to return array, got %s.',
$class.'->getRawRules()',
$type));
}
if (empty($raw_rules['start'])) {
throw new UnexpectedValueException(
pht(
"Expected %s rules to define rules for state '%s'.",
$class,
'start'));
}
$processed_rules = array();
foreach ($raw_rules as $state => $rules) {
if (!is_array($rules)) {
$type = gettype($rules);
throw new UnexpectedValueException(
pht(
"Expected list of rules for state '%s' in %s, got %s.",
$state,
$class,
$type));
}
foreach ($rules as $key => $rule) {
$n = count($rule);
if ($n < 2 || $n > 4) {
throw new UnexpectedValueException(
pht(
"Expected rule '%s' in state '%s' in %s to have 2-4 elements ".
"(regex, token, [next state], [options]), got %d.",
$key,
$state,
$class,
$n));
}
$rule = array_values($rule);
if (count($rule) == 2) {
$rule[] = null;
}
if (count($rule) == 3) {
$rule[] = array();
}
foreach ($rule[3] as $option => $value) {
switch ($option) {
case 'context':
if ($value !== 'push' &&
$value !== 'pop' &&
$value !== 'discard' &&
$value !== null) {
throw new UnexpectedValueException(
pht(
"Rule '%s' in state '%s' in %s has unknown ".
"context rule '%s', expected '%s', '%s' or '%s'.",
$key,
$state,
$class,
$value,
'push',
'pop',
'discard'));
}
break;
default:
throw new UnexpectedValueException(
pht(
"Rule '%s' in state '%s' in %s has unknown option '%s'.",
$key,
$state,
$class,
$option));
}
}
$flags = 'sS';
// NOTE: The "\G" assertion is an offset-aware version of "^".
$rule[0] = '(\\G'.$rule[0].')'.$flags;
if (@preg_match($rule[0], '') === false) {
$error = error_get_last();
throw new UnexpectedValueException(
pht(
"Rule '%s' in state '%s' in %s defines an ".
"invalid regular expression ('%s'): %s",
$key,
$state,
$class,
$rule[0],
idx($error, 'message')));
}
$next_state = $rule[2];
if ($next_state !== null && $next_state !== '!pop') {
if (empty($raw_rules[$next_state])) {
throw new UnexpectedValueException(
pht(
"Rule '%s' in state '%s' in %s transitions to ".
"state '%s', but there are no rules for that state.",
$key,
$state,
$class,
$next_state));
}
}
$processed_rules[$state][] = $rule;
}
}
return $processed_rules;
}