/** * @param \Carrooi\Tokenizer\Parsing\Lexer $lexer * @return bool|array|null */ public function match(Lexer $lexer) { $result = []; $pos = $lexer->position; $delimiter = null; while ($pos < count($lexer->tokens)) { if ($delimiter !== null) { $pos += count(Helpers::flattenTokens($delimiter)); } $subLexer = $this->createLexer($lexer->tokens, $pos); $match = $this->matchTokens($subLexer, $this->tokens); if (!$match) { break; } if ($delimiter !== null) { $result = $this->mergeMatchToResult($result, $delimiter); } $result = $this->mergeMatchToResult($result, $match); $delimiter = null; if ($match) { $pos += count(Helpers::flattenTokens($match)); } $subLexer = $this->createLexer($lexer->tokens, $pos); $match = $this->matchTokens($subLexer, $this->delimiter); if (!$match) { break; } $delimiter = $match; } return count($result) ? $result : false; }
/** * @return \Carrooi\Tokenizer\Matching\Matcher */ public function classDeclaration() { $typeMatcher = new Matcher(); $typeMatcher->select($typeMatcher->expr()->anyOf(Lexer::T_FINAL, Lexer::T_ABSTRACT), Lexer::T_WHITESPACE); $extendsMatcher = new Matcher(); $extendsMatcher->select(Lexer::T_WHITESPACE, Lexer::T_EXTENDS, Lexer::T_WHITESPACE, $this->className()); $implementsDelimiterMatcher = new Matcher(); $implementsDelimiterMatcher->select($implementsDelimiterMatcher->expr()->notRequired(Lexer::T_WHITESPACE), Lexer::T_COMMA, $implementsDelimiterMatcher->expr()->notRequired(Lexer::T_WHITESPACE)); $implementsMatcher = new Matcher(); $implementsMatcher->select(Lexer::T_WHITESPACE, Lexer::T_IMPLEMENTS, Lexer::T_WHITESPACE, $implementsMatcher->expr()->listOf($implementsDelimiterMatcher, $this->className())); $matcher = new Matcher(); $matcher->select($matcher->expr()->notRequired($typeMatcher), Lexer::T_CLASS, Lexer::T_WHITESPACE, Lexer::T_STRING, $matcher->expr()->notRequired($extendsMatcher), $matcher->expr()->notRequired($implementsMatcher)); $matcher->map(new ResultMapping(function (array $tokens) { $class = new ClassDeclaration(Helpers::flattenTokens($tokens), $tokens[3]['value']); if ($tokens[0]) { if ($tokens[0][0]['type'] === Lexer::T_FINAL) { $class->final = true; } if ($tokens[0][0]['type'] === Lexer::T_ABSTRACT) { $class->abstract = true; } } if ($tokens[4] && $tokens[4][3]) { $class->extends = $tokens[4][3]; } if ($tokens[5]) { $implements = array_slice($tokens[5], 3); $implements = array_filter($implements, function ($token) { return $token instanceof ClassNameExpression; }); $class->implements = array_values($implements); } return $class; })); return $matcher; }