public function decode($input)
{
if (!is_string($input)) {
throw new \InvalidArgumentException(sprintf('Argument must be a string, %s given.', gettype($input)));
} elseif (substr($input, 0, 3) === "") {
// BOM
$input = substr($input, 3);
}
$this->input = "\n" . str_replace("\r", '', $input);
// \n forces indent detection
$pattern = '~(' . implode(')|(', self::PATTERNS) . ')~Amix';
$this->tokens = preg_split($pattern, $this->input, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE | PREG_SPLIT_DELIM_CAPTURE);
$last = end($this->tokens);
if ($this->tokens && !preg_match($pattern, $last[0])) {
$this->pos = count($this->tokens) - 1;
$this->error();
}
$this->pos = 0;
$res = $this->parse(NULL);
while (isset($this->tokens[$this->pos])) {
if ($this->tokens[$this->pos][0][0] === "\n") {
$this->pos++;
} else {
$this->error();
}
}
return $res;
}