/**
  * @param mixed[] $tokens
  *   Tokens from token_get_all().
  * @param int $i
  *   Before: Position of the opening '{'.
  *   After (success): Position after the closing '}'.
  *   After (failure): Same as before.
  *
  * @return \Donquixote\HastyPhpAst\Ast\ClassLikeBody\AstClassLikeBodyInterface|false
  */
 function parse(array $tokens, &$i)
 {
     $iStart = $i;
     if ('{' !== $tokens[$i]) {
         # return FALSE;
         // Wrong usage of this parser. The calling code is responsible!
         throw new \InvalidArgumentException('Class body must begin with "{".');
     }
     ++$i;
     $memberNodes = array();
     while (TRUE) {
         $memberNode = $this->memberParser->parse($tokens, $i);
         if (FALSE === $memberNode) {
             $id = ParserUtil::nextSubstantialIncl($tokens, $i);
             if ('}' === $id) {
                 // End of class body.
                 ++$i;
                 break;
             }
             $i = $iStart;
             return FALSE;
         }
         if (NULL !== $memberNode) {
             $memberNodes[] = $memberNode;
         }
     }
     return new AstClassLikeBody($memberNodes);
 }
 /**
  * @return mixed[]
  */
 private function findMemberNodes()
 {
     $i = $this->iCurlyOpen;
     $body = $this->classBodyParser->parse($this->tokens, $i);
     if ($body instanceof AstClassLikeBodyInterface) {
         return $body->getMemberNodes();
     } elseif (FALSE === $body) {
         // Not sure what to do here..
         return array();
     } else {
         // Not sure what to do here..
         return array();
     }
 }
 /**
  * @param string $php
  *   PHP code read from a file.
  *
  * @return \Donquixote\HastyPhpAst\Ast\File\AstFileInterface|null
  */
 function phpGetAst($php)
 {
     $tokens = token_get_all($php);
     $tokens[] = '#';
     $i = 0;
     try {
         $fileAst = $this->parser->parse($tokens, $i);
     } catch (ParseError $e) {
         return NULL;
     }
     if (!$fileAst instanceof AstFileInterface) {
         return NULL;
     }
     return $fileAst;
 }
 /**
  * @param array $tokens
  * @param int $i
  *
  * @return \Donquixote\HastyPhpAst\Ast\File\AstFileInterface|false
  */
 function parse(array $tokens, &$i)
 {
     if (T_OPEN_TAG !== $tokens[$i][0]) {
         return FALSE;
     }
     ++$i;
     $nodes = array();
     while (TRUE) {
         $node = $this->parser->parse($tokens, $i);
         if (FALSE === $node) {
             $id = ParserUtil::nextSubstantialIncl($tokens, $i);
             if ('#' === $id) {
                 // End of file/stream.
                 break;
             }
             return FALSE;
         }
         if (NULL !== $node) {
             $nodes[] = $node;
         }
     }
     return new AstFile($nodes);
 }
 /**
  * @param array $tokens
  *   The tokens from token_get_all()
  * @param int $iParent
  *   Before: Position of the T_CLASS or T_INTERFACE or T_TRAIT.
  *   After, success: Position after the closing '}' or ';'.
  *   After, failure: Same as before.
  * @param true[] $modifiers
  *   E.g. array(T_ABSTRACT => true, T_INTERFACE => true, T_PRIVATE => true)
  * @param string $docComment
  *   Doc comment collected in calling code.
  *
  * @return mixed|false|null
  *   FALSE, if this parser does not match.
  *   NULL, if the parsed element can be skipped in the result.
  *   A parse subtree, otherwise.
  *
  * @throws ParseError
  *   If a syntax error is found in the code.
  *
  * @see token_get_all()
  */
 function parse(array $tokens, &$iParent, array $modifiers = array(), $docComment = NULL)
 {
     $i = $iParent;
     $id = ParserUtil::nextSubstantialExcl($tokens, $i);
     if (T_STRING !== $id) {
         return FALSE;
     }
     $shortName = $tokens[$i][1];
     $id = ParserUtil::nextSubstantialExcl($tokens, $i);
     $extendsAliases = array();
     if (T_EXTENDS === $id) {
         ++$i;
         $extendsAliases = ParserUtil::parseIdentifierList($tokens, $i);
         if (FALSE === $extendsAliases) {
             return FALSE;
         }
         $id = ParserUtil::nextSubstantialIncl($tokens, $i);
     }
     $implementsAliases = array();
     if (T_IMPLEMENTS === $id) {
         ++$i;
         $implementsAliases = ParserUtil::parseIdentifierList($tokens, $i);
         if (FALSE === $implementsAliases) {
             return FALSE;
         }
         $id = ParserUtil::nextSubstantialIncl($tokens, $i);
     }
     if ('{' !== $id) {
         return FALSE;
     }
     $body = $this->classBodyParser->parse($tokens, $i);
     if (FALSE === $body) {
         return FALSE;
     }
     $iParent = $i;
     return new AstClassLike($docComment, $modifiers, $shortName, $extendsAliases, $implementsAliases, $body);
 }