/** * Parse heredoc/nowdoc syntax * * @param StringReader $input * @return array|null */ protected function parseHeredoc(StringReader $input) { $startLine = $input->line; $startIndex = $input->i - 3; // detect nowdoc syntax if ('\'' === $input->char) { $isNowdoc = true; $input->eat(); } else { $isNowdoc = false; } // parse identifier $idt = ''; while (StringReader::CHAR_IDT === $input->charType()) { $idt .= $input->shift(); } if ('' === $idt) { return; } if ($isNowdoc) { if ('\'' !== $input->char) { return; } $input->eat(); } // determine end sequence $line = ''; if ("\r" === $input->char) { $line .= $input->shift(); } if ("\n" === $input->char) { $line .= $input->shift(); } if ('' === $line) { return; } $end = "{$line}{$idt}"; // find end $endLen = strlen($end); $endOffset = 0; while (!$input->end) { // end detection if ($input->char === $end[$endOffset]) { ++$endOffset; if ($endLen === $endOffset) { $input->eat(); // skip semicolon if (';' === $input->char) { $input->eat(); } // validate end of line for ($ii = 0; isset($line[$ii]); ++$ii) { if ($line[$ii] !== $input->char) { $ii = false; break; } $input->eat(); } // full end match? if (false !== $ii) { break; } else { $endOffset = 0; } } } elseif (0 !== $endOffset) { $endOffset = 0; continue; } $input->eat(); } // return token return $this->token($isNowdoc ? self::T_NOWDOC : self::T_HEREDOC, $startLine, substr($input->str, $startIndex, $input->i - $startIndex)); }
/** * Parse identifier * * Pre-offset: at idt char * Post-offset: at first non-idt char * * @param StringReader $input input * @return array */ protected function parseIdt(StringReader $input) { $line = $input->line; // gather identifier characters $buffer = ''; while (StringReader::CHAR_IDT === ($charType = $input->charType()) || StringReader::CHAR_NUM === $charType) { $buffer .= $input->shift(); } // determine token type if (isset($this->vars[$buffer[0]])) { $id = self::T_VARIABLE; } elseif (isset($this->keywords[$buffer])) { $id = self::T_KEYWORD; } else { $id = self::T_IDENTIFIER; } // return token return $this->token($id, $line, $buffer); }