function __construct($parser, $lines)
{
$this->parser = $parser;
$this->lines = $lines;
// Find the first line (if any) that's an attached function definition. Can skip first line (unless this block is malformed)
for ($i = 1; $i < count($lines); $i++) {
if (preg_match(self::$function_rx, $lines[$i])) {
break;
}
}
// Then split into the two parts
$spec = array_slice($lines, 0, $i);
$funcs = array_slice($lines, $i);
// Parse out the spec
$spec = implode("\n", $spec);
if (!preg_match(self::$rule_rx, $spec, $specmatch)) {
user_error('Malformed rule spec ' . $spec, E_USER_ERROR);
}
$this->name = $specmatch['name'];
if ($specmatch['extends']) {
$this->extends = $this->parser->rules[$specmatch['extends']];
if (!$this->extends) {
user_error('Extended rule ' . $specmatch['extends'] . ' is not defined before being extended', E_USER_ERROR);
}
}
$this->arguments = array();
if ($specmatch['arguments']) {
preg_match_all(self::$argument_rx, $specmatch['arguments'], $arguments, PREG_SET_ORDER);
foreach ($arguments as $argument) {
$this->arguments[trim($argument[1])] = trim($argument[2]);
}
}
$this->mode = $specmatch['matchmark'] ? 'rule' : 'replace';
if ($this->mode == 'rule') {
$this->rule = $specmatch['rule'];
$this->parse_rule();
} else {
if (!$this->extends) {
user_error('Replace matcher, but not on an extends rule', E_USER_ERROR);
}
$this->replacements = array();
preg_match_all(self::$replacement_rx, $specmatch['rule'], $replacements, PREG_SET_ORDER);
$rule = $this->extends->rule;
foreach ($replacements as $replacement) {
$search = trim($replacement[1]);
$replace = trim($replacement[3]);
if ($replace == "''" || $replace == '""') {
$replace = "";
}
$rule = str_replace($search, ' ' . $replace . ' ', $rule);
}
$this->rule = $rule;
$this->parse_rule();
}
// Parse out the functions
$this->functions = array();
$active_function = NULL;
foreach ($funcs as $line) {
/* Handle function definitions */
if (preg_match(self::$function_rx, $line, $func_match, 0)) {
$active_function = $func_match[1];
$this->functions[$active_function] = $func_match[2] . PHP_EOL;
} else {
$this->functions[$active_function] .= $line . PHP_EOL;
}
}
}