From 36c739cbcdac7d44e47ae708a6691a543bb6a03b Mon Sep 17 00:00:00 2001 From: Alexey Kopytko Date: Sun, 5 Apr 2020 23:30:08 +0900 Subject: [PATCH 1/5] Use forked version of Hoa\Compiler Fixes #1182 --- composer.json | 2 +- src/Type/Parser.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 62282bf7d..39692cc36 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "jms/metadata": "^2.0", "doctrine/annotations": "^1.0", "doctrine/instantiator": "^1.0.3", - "hoa/compiler": "^3.17.08.08" + "sanmai/hoa-compiler": "^0.1" }, "suggest": { "symfony/yaml": "Required if you'd like to use the YAML metadata format.", diff --git a/src/Type/Parser.php b/src/Type/Parser.php index de5a7c3a7..704cba59d 100644 --- a/src/Type/Parser.php +++ b/src/Type/Parser.php @@ -4,7 +4,7 @@ namespace JMS\Serializer\Type; -use Hoa\Exception\Exception; +use Hoa\Compiler\Exception; use Hoa\Visitor\Visit; use JMS\Serializer\Type\Exception\SyntaxError; From 821c749026704fbd7d140b37f6017fe1f6ed451c Mon Sep 17 00:00:00 2001 From: Alexey Kopytko Date: Mon, 13 Apr 2020 04:05:58 +0900 Subject: [PATCH 2/5] Integrate hoa/compiler base files in the package To update namespace use: find src/Type/ -type f | xargs sed -i 's:Hoa\\Compiler:JMS\\Serializer\\Type\\Compiler:g' --- composer.json | 3 +- src/Type/Compiler/Exception.php | 53 ++ src/Type/Compiler/Exception/Exception.php | 46 + .../Exception/FinalStateHasNotBeenReached.php | 51 ++ src/Type/Compiler/Exception/InternalError.php | 48 ++ src/Type/Compiler/Exception/Lexer.php | 51 ++ src/Type/Compiler/Exception/Rule.php | 51 ++ .../Compiler/Exception/UnexpectedToken.php | 51 ++ .../Compiler/Exception/UnrecognizedToken.php | 88 ++ src/Type/Compiler/Llk/Lexer.php | 341 ++++++++ src/Type/Compiler/Llk/Llk.php | 46 + src/Type/Compiler/Llk/Llk.pp | 94 +++ src/Type/Compiler/Llk/Parser.php | 789 ++++++++++++++++++ src/Type/Compiler/Llk/Rule.php | 290 +++++++ src/Type/Compiler/Llk/Rule/Choice.php | 46 + src/Type/Compiler/Llk/Rule/Concatenation.php | 51 ++ src/Type/Compiler/Llk/Rule/Ekzit.php | 51 ++ src/Type/Compiler/Llk/Rule/Entry.php | 51 ++ src/Type/Compiler/Llk/Rule/Invocation.php | 173 ++++ src/Type/Compiler/Llk/Rule/Repetition.php | 128 +++ src/Type/Compiler/Llk/Rule/Rule.php | 46 + src/Type/Compiler/Llk/Rule/Token.php | 304 +++++++ src/Type/Compiler/Llk/TreeNode.php | 362 ++++++++ src/Type/InnerParser.php | 10 +- src/Type/Parser.php | 2 +- src/Type/TypeVisitor.php | 2 +- 26 files changed, 3220 insertions(+), 8 deletions(-) create mode 100644 src/Type/Compiler/Exception.php create mode 100644 src/Type/Compiler/Exception/Exception.php create mode 100644 src/Type/Compiler/Exception/FinalStateHasNotBeenReached.php create mode 100644 src/Type/Compiler/Exception/InternalError.php create mode 100644 src/Type/Compiler/Exception/Lexer.php create mode 100644 src/Type/Compiler/Exception/Rule.php create mode 100644 src/Type/Compiler/Exception/UnexpectedToken.php create mode 100644 src/Type/Compiler/Exception/UnrecognizedToken.php create mode 100644 src/Type/Compiler/Llk/Lexer.php create mode 100644 src/Type/Compiler/Llk/Llk.php create mode 100644 src/Type/Compiler/Llk/Llk.pp create mode 100644 src/Type/Compiler/Llk/Parser.php create mode 100644 src/Type/Compiler/Llk/Rule.php create mode 100644 src/Type/Compiler/Llk/Rule/Choice.php create mode 100644 src/Type/Compiler/Llk/Rule/Concatenation.php create mode 100644 src/Type/Compiler/Llk/Rule/Ekzit.php create mode 100644 src/Type/Compiler/Llk/Rule/Entry.php create mode 100644 src/Type/Compiler/Llk/Rule/Invocation.php create mode 100644 src/Type/Compiler/Llk/Rule/Repetition.php create mode 100644 src/Type/Compiler/Llk/Rule/Rule.php create mode 100644 src/Type/Compiler/Llk/Rule/Token.php create mode 100644 src/Type/Compiler/Llk/TreeNode.php diff --git a/composer.json b/composer.json index 39692cc36..d9f0dca82 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,8 @@ "jms/metadata": "^2.0", "doctrine/annotations": "^1.0", "doctrine/instantiator": "^1.0.3", - "sanmai/hoa-compiler": "^0.1" + "hoa/iterator": "^2.17", + "hoa/visitor": "^2.17" }, "suggest": { "symfony/yaml": "Required if you'd like to use the YAML metadata format.", diff --git a/src/Type/Compiler/Exception.php b/src/Type/Compiler/Exception.php new file mode 100644 index 000000000..a416f6358 --- /dev/null +++ b/src/Type/Compiler/Exception.php @@ -0,0 +1,53 @@ +line = $line; + $this->column = $column; + + return; + } + + /** + * Get column. + * + * @return int + */ + public function getColumn() + { + return $this->column; + } +} diff --git a/src/Type/Compiler/Llk/Lexer.php b/src/Type/Compiler/Llk/Lexer.php new file mode 100644 index 000000000..33ea5d40f --- /dev/null +++ b/src/Type/Compiler/Llk/Lexer.php @@ -0,0 +1,341 @@ +_pcreOptions .= 'u'; + } + + return; + } + + /** + * Text tokenizer: splits the text in parameter in an ordered array of + * tokens. + * + * @param string $text Text to tokenize. + * @param array[] $tokens Tokens to be returned. + * + * @return \Generator|array[] + * + * @throws \JMS\Serializer\Type\Compiler\Exception\UnrecognizedToken + * + * @psalm-return \Generator + */ + public function lexMe($text, array $tokens): \Generator + { + $this->validateInputInUnicodeMode($text); + + $this->_text = $text; + $this->_tokens = $tokens; + $this->_nsStack = null; + $offset = 0; + $maxOffset = strlen($this->_text); + $this->_lexerState = 'default'; + $stack = false; + + foreach ($this->_tokens as &$tokens) { + $_tokens = []; + + foreach ($tokens as $fullLexeme => $regex) { + if (false === strpos($fullLexeme, ':')) { + $_tokens[$fullLexeme] = [$regex, null]; + + continue; + } + + list($lexeme, $namespace) = explode(':', $fullLexeme, 2); + + $stack |= ('__shift__' === substr($namespace, 0, 9)); + + unset($tokens[$fullLexeme]); + $_tokens[$lexeme] = [$regex, $namespace]; + } + + $tokens = $_tokens; + } + + if (true == $stack) { + $this->_nsStack = new \SplStack(); + } + + while ($offset < $maxOffset) { + $nextToken = $this->nextToken($offset); + + if (null === $nextToken) { + throw new Compiler\Exception\UnrecognizedToken( + 'Unrecognized token "%s" at line 1 and column %d:' . + "\n" . '%s' . "\n" . + str_repeat(' ', mb_strlen(substr($text, 0, $offset))) . '↑', + 0, + [ + mb_substr(substr($text, $offset), 0, 1), + $offset + 1, + $text + ], + 1, + $offset + ); + } + + if (true === $nextToken['keep']) { + $nextToken['offset'] = $offset; + yield $nextToken; + } + + $offset += strlen($nextToken['value']); + } + + yield [ + 'token' => 'EOF', + 'value' => 'EOF', + 'length' => 0, + 'namespace' => 'default', + 'keep' => true, + 'offset' => $offset + ]; + } + + /** + * Compute the next token recognized at the beginning of the string. + * + * @param int $offset Offset. + * + * @return (array|bool|int|string)[]|array[]|null + * + * @throws \JMS\Serializer\Type\Compiler\Exception\Lexer + * + * @psalm-return array{token: string, value: string, length: int|false, namespace: array, keep: bool}|null + */ + protected function nextToken($offset) + { + $tokenArray = &$this->_tokens[$this->_lexerState]; + + $previousNamespace = null; + foreach ($tokenArray as $lexeme => $bucket) { + list($regex, $nextState) = $bucket; + + if (null === $nextState) { + $nextState = $this->_lexerState; + } + + $out = $this->matchLexeme($lexeme, $regex, $offset); + + if (null !== $out) { + $out['namespace'] = $this->_lexerState; + $out['keep'] = 'skip' !== $lexeme; + + if ($nextState !== $this->_lexerState) { + $shift = false; + + if (null !== $this->_nsStack && + 0 !== preg_match('#^__shift__(?:\s*\*\s*(\d+))?$#', $nextState, $matches)) { + $i = isset($matches[1]) ? intval($matches[1]) : 1; + + if ($i > ($c = count($this->_nsStack))) { + throw new Compiler\Exception\Lexer( + 'Cannot shift namespace %d-times, from token ' . + '%s in namespace %s, because the stack ' . + 'contains only %d namespaces.', + 1, + [ + $i, + $lexeme, + $this->_lexerState, + $c + ] + ); + } + + while (1 <= $i--) { + $previousNamespace = $this->_nsStack->pop(); + } + + $nextState = $previousNamespace; + $shift = true; + } + + if (!isset($this->_tokens[$nextState])) { + throw new Compiler\Exception\Lexer( + 'Namespace %s does not exist, called by token %s ' . + 'in namespace %s.', + 2, + [ + $nextState, + $lexeme, + $this->_lexerState + ] + ); + } + + if (null !== $this->_nsStack && false === $shift) { + $this->_nsStack[] = $this->_lexerState; + } + + $this->_lexerState = $nextState; + } + + return $out; + } + } + + return null; + } + + /** + * Check if a given lexeme is matched at the beginning of the text. + * + * @param string $lexeme Name of the lexeme. + * @param string $regex Regular expression describing the lexeme. + * @param int $offset Offset. + * + * @return (int|false|string)[]|null + * + * @throws \JMS\Serializer\Type\Compiler\Exception\Lexer + * + * @psalm-return array{token: string, value: string, length: int|false}|null + */ + protected function matchLexeme($lexeme, $regex, $offset) + { + $_regex = str_replace('#', '\#', $regex); + $preg = @preg_match( + '#\G(?|' . $_regex . ')#' . $this->_pcreOptions, + $this->_text, + $matches, + 0, + $offset + ); + + if (0 === $preg) { + return null; + } + + if (false === $preg) { + throw new Compiler\Exception\InternalError( + 'Lexer encountered a PCRE error on a lexeme "%s", full regex: "%s". Please report this issue to the maintainers.', + preg_last_error(), + [$lexeme, $_regex] + ); + } + + if ('' === $matches[0]) { + throw new Compiler\Exception\Lexer( + 'A lexeme must not match an empty value, which is the ' . + 'case of "%s" (%s).', + 3, + [$lexeme, $regex] + ); + } + + return [ + 'token' => $lexeme, + 'value' => $matches[0], + 'length' => mb_strlen($matches[0]) + ]; + } + + /** + * @param string $text + * @return bool + */ + private function validateInputInUnicodeMode($text) + { + if (strpos($this->_pcreOptions, 'u') !== false && preg_match('##u', $text) === false) { + throw new Compiler\Exception\Lexer( + 'Text is not valid utf-8 string, you probably need to switch "lexer.unicode" setting off.' + ); + } + } +} diff --git a/src/Type/Compiler/Llk/Llk.php b/src/Type/Compiler/Llk/Llk.php new file mode 100644 index 000000000..07338597a --- /dev/null +++ b/src/Type/Compiler/Llk/Llk.php @@ -0,0 +1,46 @@ + +%token named \(\) +%token node #[a-zA-Z_][a-zA-Z0-9_]*(:[mM])? + +%token capturing_ \( +%token _capturing \) +%token unification_ \[ +%token unification [0-9]+ +%token _unification \] + +#rule: + choice() + +choice: + concatenation() ( ::or:: concatenation() #choice )* + +concatenation: + repetition() ( repetition() #concatenation )* + +repetition: + simple() ( quantifier() #repetition )? ? + +simple: + ::capturing_:: choice() ::_capturing:: + | ::skipped:: ( ::unification_:: ::_unification:: )? + ::skipped:: #skipped + | ::kept_:: ( ::unification_:: ::_unification:: )? + ::_kept:: #kept + | ::named:: + +quantifier: + + | + | + | + | + | diff --git a/src/Type/Compiler/Llk/Parser.php b/src/Type/Compiler/Llk/Parser.php new file mode 100644 index 000000000..cfe497c8e --- /dev/null +++ b/src/Type/Compiler/Llk/Parser.php @@ -0,0 +1,789 @@ + token regex), to be defined in + * precedence order. + * + * @var array + */ + protected $_tokens = null; + + /** + * Rules, to be defined as associative array, name => Rule object. + * + * @var Rule[] + */ + protected $_rules = null; + + /** + * Lexer iterator. + * + * @var \Hoa\Iterator\Buffer + */ + protected $_tokenSequence = null; + + /** + * Possible token causing an error. + * + * @var array + */ + protected $_errorToken = null; + + /** + * Trace of activated rules. + * + * @var array + */ + protected $_trace = []; + + /** + * Stack of todo list. + * + * @var array + */ + protected $_todo = null; + + /** + * AST. + * + * @var \JMS\Serializer\Type\Compiler\Llk\TreeNode + */ + protected $_tree = null; + + /** + * Current depth while building the trace. + * + * @var int + */ + protected $_depth = -1; + + + + /** + * Construct the parser. + * + * @param array $tokens Tokens. + * @param array $rules Rules. + * @param array $pragmas Pragmas. + */ + public function __construct( + array $tokens = [], + array $rules = [], + array $pragmas = [] + ) { + $this->_tokens = $tokens; + $this->_rules = $rules; + $this->_pragmas = $pragmas; + + return; + } + + /** + * Parse :-). + * + * @param string $text Text to parse. + * @param string $rule The axiom, i.e. root rule. + * @param bool $tree Whether build tree or not. + * @return mixed + * @throws \JMS\Serializer\Type\Compiler\Exception\UnexpectedToken + */ + final public function parse(string $text, string $rule = null, bool $tree = true) + { + $k = 1024; + + if (isset($this->_pragmas['parser.lookahead'])) { + $k = max(0, intval($this->_pragmas['parser.lookahead'])); + } + + $lexer = new Lexer($this->_pragmas); + $this->_tokenSequence = new Iterator\Buffer( + $lexer->lexMe($text, $this->_tokens), + $k + ); + $this->_tokenSequence->rewind(); + + $this->_errorToken = null; + $this->_trace = []; + $this->_todo = []; + + if (false === array_key_exists($rule, $this->_rules)) { + $rule = $this->getRootRule(); + } + + $closeRule = new Rule\Ekzit($rule, 0); + $openRule = new Rule\Entry($rule, 0, [$closeRule]); + $this->_todo = [$closeRule, $openRule]; + + do { + $out = $this->unfold(); + + if (null !== $out && + 'EOF' === $this->_tokenSequence->current()['token']) { + break; + } + + if (false === $this->backtrack()) { + $token = $this->_errorToken; + + if (null === $this->_errorToken) { + $token = $this->_tokenSequence->current(); + } + + $offset = $token['offset']; + $line = 1; + $column = 1; + + if (!empty($text)) { + if (0 === $offset) { + $leftnl = 0; + } else { + $leftnl = strrpos($text, "\n", -(strlen($text) - $offset) - 1) ?: 0; + } + + $rightnl = strpos($text, "\n", $offset); + $line = substr_count($text, "\n", 0, $leftnl + 1) + 1; + $column = $offset - $leftnl + (0 === $leftnl); + + if (false !== $rightnl) { + $text = trim(substr($text, $leftnl, $rightnl - $leftnl), "\n"); + } + } + + throw new Compiler\Exception\UnexpectedToken( + 'Unexpected token "%s" (%s) at line %d and column %d:' . + "\n" . '%s' . "\n" . str_repeat(' ', $column - 1) . '↑', + 0, + [ + $token['value'], + $token['token'], + $line, + $column, + $text + ], + $line, + $column + ); + } + } while (true); + + if (false === $tree) { + return true; + } + + $tree = $this->_buildTree(); + + if (!($tree instanceof TreeNode)) { + throw new Compiler\Exception( + 'Parsing error: cannot build AST, the trace is corrupted.', + 1 + ); + } + + return $this->_tree = $tree; + } + + /** + * Unfold trace. + * + * @return mixed + */ + final protected function unfold() + { + while (0 < count($this->_todo)) { + $rule = array_pop($this->_todo); + + if ($rule instanceof Rule\Ekzit) { + $rule->setDepth($this->_depth); + $this->_trace[] = $rule; + + if (false === $rule->isTransitional()) { + --$this->_depth; + } + } else { + $ruleName = $rule->getRule(); + $next = $rule->getData(); + $zeRule = $this->_rules[$ruleName]; + $out = $this->_parse($zeRule, $next); + + if (false === $out && false === $this->backtrack()) { + return null; + } + } + } + + return true; + } + + /** + * Parse current rule. + * + * @param \JMS\Serializer\Type\Compiler\Llk\Rule $zeRule Current rule. + * @param int $next Next rule index. + * @return bool + */ + final protected function _parse(Rule $zeRule, $next) + { + $regex = null; + if ($zeRule instanceof Rule\Token) { + $name = $this->_tokenSequence->current()['token']; + + if ($zeRule->getTokenName() !== $name) { + return false; + } + + $value = $this->_tokenSequence->current()['value']; + + if (0 <= $unification = $zeRule->getUnificationIndex()) { + for ($skip = 0, $i = count($this->_trace) - 1; $i >= 0; --$i) { + $trace = $this->_trace[$i]; + + if ($trace instanceof Rule\Entry) { + if (false === $trace->isTransitional()) { + if ($trace->getDepth() <= $this->_depth) { + break; + } + + --$skip; + } + } elseif ($trace instanceof Rule\Ekzit && + false === $trace->isTransitional()) { + $skip += $trace->getDepth() > $this->_depth; + } + + if (0 < $skip) { + continue; + } + + if ($trace instanceof Rule\Token && + $unification === $trace->getUnificationIndex() && + $value !== $trace->getValue()) { + return false; + } + } + } + + $current = $this->_tokenSequence->current(); + + $namespace = $current['namespace']; + $offset = $current['offset']; + + $zzeRule = clone $zeRule; + $zzeRule->setValue($value); + $zzeRule->setOffset($offset); + $zzeRule->setNamespace($namespace); + + if (isset($this->_tokens[$namespace][$name])) { + $zzeRule->setRepresentation($this->_tokens[$namespace][$name]); + } else { + foreach ($this->_tokens[$namespace] as $_name => $regex) { + if (false === $pos = strpos($_name, ':')) { + continue; + } + + $_name = substr($_name, 0, $pos); + + if ($_name === $name) { + break; + } + } + + $zzeRule->setRepresentation($regex); + } + + array_pop($this->_todo); + $this->_trace[] = $zzeRule; + $this->_tokenSequence->next(); + $this->_errorToken = $this->_tokenSequence->current(); + + return true; + } elseif ($zeRule instanceof Rule\Concatenation) { + if (false === $zeRule->isTransitional()) { + ++$this->_depth; + } + + $this->_trace[] = new Rule\Entry( + $zeRule->getName(), + 0, + null, + $this->_depth + ); + $children = $zeRule->getChildren(); + + for ($i = count($children) - 1; $i >= 0; --$i) { + $nextRule = $children[$i]; + $this->_todo[] = new Rule\Ekzit($nextRule, 0); + $this->_todo[] = new Rule\Entry($nextRule, 0); + } + + return true; + } elseif ($zeRule instanceof Rule\Choice) { + $children = $zeRule->getChildren(); + + if ($next >= count($children)) { + return false; + } + + if (false === $zeRule->isTransitional()) { + ++$this->_depth; + } + + $this->_trace[] = new Rule\Entry( + $zeRule->getName(), + $next, + $this->_todo, + $this->_depth + ); + $nextRule = $children[$next]; + $this->_todo[] = new Rule\Ekzit($nextRule, 0); + $this->_todo[] = new Rule\Entry($nextRule, 0); + + return true; + } elseif ($zeRule instanceof Rule\Repetition) { + $nextRule = $zeRule->getChildren(); + + if (0 === $next) { + $name = $zeRule->getName(); + $min = $zeRule->getMin(); + + if (false === $zeRule->isTransitional()) { + ++$this->_depth; + } + + $this->_trace[] = new Rule\Entry( + $name, + $min, + null, + $this->_depth + ); + array_pop($this->_todo); + $this->_todo[] = new Rule\Ekzit( + $name, + $min, + $this->_todo + ); + + for ($i = 0; $i < $min; ++$i) { + $this->_todo[] = new Rule\Ekzit($nextRule, 0); + $this->_todo[] = new Rule\Entry($nextRule, 0); + } + + return true; + } else { + $max = $zeRule->getMax(); + + if (-1 != $max && $next > $max) { + return false; + } + + $this->_todo[] = new Rule\Ekzit( + $zeRule->getName(), + $next, + $this->_todo + ); + $this->_todo[] = new Rule\Ekzit($nextRule, 0); + $this->_todo[] = new Rule\Entry($nextRule, 0); + + return true; + } + } + + return false; + } + + /** + * Backtrack the trace. + * + * @return bool + */ + final protected function backtrack() + { + $found = false; + + do { + $last = array_pop($this->_trace); + + if ($last instanceof Rule\Entry) { + $zeRule = $this->_rules[$last->getRule()]; + $found = $zeRule instanceof Rule\Choice; + } elseif ($last instanceof Rule\Ekzit) { + $zeRule = $this->_rules[$last->getRule()]; + $found = $zeRule instanceof Rule\Repetition; + } elseif ($last instanceof Rule\Token) { + $this->_tokenSequence->previous(); + + if (false === $this->_tokenSequence->valid()) { + return false; + } + } + } while (0 < count($this->_trace) && false === $found); + + if (false === $found) { + return false; + } + + $rule = $last->getRule(); + $next = $last->getData() + 1; + $this->_depth = $last->getDepth(); + $this->_todo = $last->getTodo(); + $this->_todo[] = new Rule\Entry($rule, $next); + + return true; + } + + /** + * Build AST from trace. + * Walk through the trace iteratively and recursively. + * + * @param int $i Current trace index. + * @param array &$children Collected children. + * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode + */ + final protected function _buildTree($i = 0, &$children = []) + { + $max = count($this->_trace); + + while ($i < $max) { + $trace = $this->_trace[$i]; + + if ($trace instanceof Rule\Entry) { + $ruleName = $trace->getRule(); + $rule = $this->_rules[$ruleName]; + $isRule = false === $trace->isTransitional(); + $nextTrace = $this->_trace[$i + 1]; + $id = $rule->getNodeId(); + + // Optimization: Skip empty trace sequence. + if ($nextTrace instanceof Rule\Ekzit && + $ruleName == $nextTrace->getRule()) { + $i += 2; + + continue; + } + + if (true === $isRule) { + $children[] = $ruleName; + } + + if (null !== $id) { + $children[] = [ + 'id' => $id, + 'options' => $rule->getNodeOptions() + ]; + } + + $i = $this->_buildTree($i + 1, $children); + + if (false === $isRule) { + continue; + } + + $handle = []; + $cId = null; + $cOptions = []; + + do { + $pop = array_pop($children); + + if (true === is_object($pop)) { + $handle[] = $pop; + } elseif (true === is_array($pop) && null === $cId) { + $cId = $pop['id']; + $cOptions = $pop['options']; + } elseif ($ruleName == $pop) { + break; + } + } while (null !== $pop); + + if (null === $cId) { + $cId = $rule->getDefaultId(); + $cOptions = $rule->getDefaultOptions(); + } + + if (null === $cId) { + for ($j = count($handle) - 1; $j >= 0; --$j) { + $children[] = $handle[$j]; + } + + continue; + } + + if (true === in_array('M', $cOptions) && + true === $this->mergeTree($children, $handle, $cId)) { + continue; + } + + if (true === in_array('m', $cOptions) && + true === $this->mergeTree($children, $handle, $cId, true)) { + continue; + } + + $cTree = new TreeNode($id ?: $cId); + + foreach ($handle as $child) { + $child->setParent($cTree); + $cTree->prependChild($child); + } + + $children[] = $cTree; + } elseif ($trace instanceof Rule\Ekzit) { + return $i + 1; + } else { + if (false === $trace->isKept()) { + ++$i; + + continue; + } + + $child = new TreeNode('token', [ + 'token' => $trace->getTokenName(), + 'value' => $trace->getValue(), + 'namespace' => $trace->getNamespace(), + 'offset' => $trace->getOffset() + ]); + + $children[] = $child; + ++$i; + } + } + + return $children[0]; + } + + /** + * Try to merge directly children into an existing node. + * + * @param array &$children Current children being gathering. + * @param array &$handle Children of the new node. + * @param string $cId Node ID. + * @param bool $recursive Whether we should merge recursively or + * not. + * @return bool + */ + final protected function mergeTree( + &$children, + &$handle, + $cId, + $recursive = false + ) { + end($children); + $last = current($children); + + if (!is_object($last)) { + return false; + } + + if ($cId !== $last->getId()) { + return false; + } + + if (true === $recursive) { + foreach ($handle as $child) { + $this->mergeTreeRecursive($last, $child); + } + + return true; + } + + foreach ($handle as $child) { + $last->appendChild($child); + $child->setParent($last); + } + + return true; + } + + /** + * Merge recursively. + * Please, see self::mergeTree() to know the context. + * + * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $node Node that receives. + * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $newNode Node to merge. + * @return void + */ + final protected function mergeTreeRecursive(TreeNode $node, TreeNode $newNode) + { + $nNId = $newNode->getId(); + + if ('token' === $nNId) { + $node->appendChild($newNode); + $newNode->setParent($node); + + return; + } + + $children = $node->getChildren(); + end($children); + $last = current($children); + + if ($last->getId() !== $nNId) { + $node->appendChild($newNode); + $newNode->setParent($node); + + return; + } + + foreach ($newNode->getChildren() as $child) { + $this->mergeTreeRecursive($last, $child); + } + + return; + } + + /** + * Get AST. + * + * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode + */ + final public function getTree() + { + return $this->_tree; + } + + /** + * Get trace. + * + * @return array + */ + final public function getTrace() + { + return $this->_trace; + } + + /** + * Get pragmas. + * + * @return array + */ + final public function getPragmas() + { + return $this->_pragmas; + } + + /** + * Get tokens. + * + * @return array + */ + final public function getTokens() + { + return $this->_tokens; + } + + /** + * Get the lexer iterator. + * + * @return \Hoa\Iterator\Buffer + */ + final public function getTokenSequence() + { + return $this->_tokenSequence; + } + + /** + * Get rule by name. + * + * @param string $name Rule name. + * @return \JMS\Serializer\Type\Compiler\Llk\Rule + */ + final public function getRule($name) + { + if (!isset($this->_rules[$name])) { + return null; + } + + return $this->_rules[$name]; + } + + /** + * Get rules. + * + * @return Rule[] + */ + final public function getRules() + { + return $this->_rules; + } + + /** + * Get root rule. + * + * @return string + */ + final public function getRootRule() + { + \assert([] !== $this->_rules); + + foreach ($this->_rules as $rule => $_) { + if (!is_int($rule)) { + break; + } + } + + return $rule; + } +} diff --git a/src/Type/Compiler/Llk/Rule.php b/src/Type/Compiler/Llk/Rule.php new file mode 100644 index 000000000..50894b2ab --- /dev/null +++ b/src/Type/Compiler/Llk/Rule.php @@ -0,0 +1,290 @@ +setName($name); + $this->setChildren($children); + $this->setNodeId($nodeId); + + return; + } + + /** + * Set rule name. + * + * @param string $name Rule name. + * @return string + */ + public function setName($name) + { + $old = $this->_name; + $this->_name = $name; + + return $old; + } + + /** + * Get rule name. + * + * @return string + */ + public function getName() + { + return $this->_name; + } + + /** + * Set rule's children. + * + * @param mixed $children Children. + * @return mixed + */ + protected function setChildren($children) + { + $old = $this->_children; + $this->_children = $children; + + return $old; + } + + /** + * Get rule's children. + * + * @return mixed + */ + public function getChildren() + { + return $this->_children; + } + + /** + * Set node ID. + * + * @param string $nodeId Node ID. + * @return string + */ + public function setNodeId($nodeId) + { + $old = $this->_nodeId; + + if (false !== $pos = strpos($nodeId, ':')) { + $this->_nodeId = substr($nodeId, 0, $pos); + $this->_nodeOptions = str_split(substr($nodeId, $pos + 1)); + } else { + $this->_nodeId = $nodeId; + $this->_nodeOptions = []; + } + + return $old; + } + + /** + * Get node ID. + * + * @return string + */ + public function getNodeId() + { + return $this->_nodeId; + } + + /** + * Get node options. + * + * @return array + */ + public function getNodeOptions(): array + { + return $this->_nodeOptions; + } + + /** + * Set default ID. + * + * @param string $defaultId Default ID. + * @return string + */ + public function setDefaultId($defaultId) + { + $old = $this->_defaultId; + + if (false !== $pos = strpos($defaultId, ':')) { + $this->_defaultId = substr($defaultId, 0, $pos); + $this->_defaultOptions = str_split(substr($defaultId, $pos + 1)); + } else { + $this->_defaultId = $defaultId; + $this->_defaultOptions = []; + } + + return $old; + } + + /** + * Get default ID. + * + * @return string + */ + public function getDefaultId() + { + return $this->_defaultId; + } + + /** + * Get default options. + * + * @return array + */ + public function getDefaultOptions() + { + return $this->_defaultOptions; + } + + /** + * Set PP representation of the rule. + * + * @param string $pp PP representation. + * @return string + */ + public function setPPRepresentation($pp) + { + $old = $this->_pp; + $this->_pp = $pp; + $this->_transitional = false; + + return $old; + } + + /** + * Get PP representation of the rule. + * + * @return string + */ + public function getPPRepresentation() + { + return $this->_pp; + } + + /** + * Check whether the rule is transitional or not. + * + * @return bool + */ + public function isTransitional() + { + return $this->_transitional; + } +} diff --git a/src/Type/Compiler/Llk/Rule/Choice.php b/src/Type/Compiler/Llk/Rule/Choice.php new file mode 100644 index 000000000..3112ec6b1 --- /dev/null +++ b/src/Type/Compiler/Llk/Rule/Choice.php @@ -0,0 +1,46 @@ +_rule = $rule; + $this->_data = $data; + $this->_todo = $todo; + $this->_depth = $depth; + $this->_transitional = \is_int($rule); + + return; + } + + /** + * Get rule name. + * + * @return string + */ + public function getRule() + { + return $this->_rule; + } + + /** + * Get data. + * + * @return mixed + */ + public function getData() + { + return $this->_data; + } + + /** + * Get todo sequence. + * + * @return array + */ + public function getTodo() + { + return $this->_todo; + } + + /** + * Set depth in trace. + * + * @param int $depth Depth. + * @return int + */ + public function setDepth($depth) + { + $old = $this->_depth; + $this->_depth = $depth; + + return $old; + } + + /** + * Get depth in trace. + * + * @return int + */ + public function getDepth() + { + return $this->_depth; + } + + /** + * Check whether the rule is transitional or not. + * + * @return bool + */ + public function isTransitional() + { + return $this->_transitional; + } +} diff --git a/src/Type/Compiler/Llk/Rule/Repetition.php b/src/Type/Compiler/Llk/Rule/Repetition.php new file mode 100644 index 000000000..86edfe638 --- /dev/null +++ b/src/Type/Compiler/Llk/Rule/Repetition.php @@ -0,0 +1,128 @@ + $max) { + throw new Compiler\Exception\Rule( + 'Cannot repeat with a min (%d) greater than max (%d).', + 0, + [$min, $max] + ); + } + + $this->_min = $min; + $this->_max = $max; + + return; + } + + /** + * Get minimum bound. + * + * @return int + */ + public function getMin() + { + return $this->_min; + } + + /** + * Get maximum bound. + * + * @return int + */ + public function getMax() + { + return $this->_max; + } + + /** + * Check whether the maximum repetition is unbounded. + * + * @return bool + */ + public function isInfinite() + { + return -1 === $this->getMax(); + } +} diff --git a/src/Type/Compiler/Llk/Rule/Rule.php b/src/Type/Compiler/Llk/Rule/Rule.php new file mode 100644 index 000000000..3b5133b6e --- /dev/null +++ b/src/Type/Compiler/Llk/Rule/Rule.php @@ -0,0 +1,46 @@ +_tokenName = $tokenName; + $this->_unification = $unification; + $this->setKept($kept); + + return; + } + + /** + * Get token name. + * + * @return string|null + */ + public function getTokenName() + { + return $this->_tokenName; + } + + /** + * Set token namespace. + * + * @param string $namespace Namespace. + * @return string + */ + public function setNamespace($namespace) + { + $old = $this->_namespace; + $this->_namespace = $namespace; + + return $old; + } + + /** + * Get token namespace. + * + * @return string + */ + public function getNamespace() + { + return $this->_namespace; + } + + /** + * Set representation. + * + * @param string $regex Representation. + * @return string|null + */ + public function setRepresentation(string $regex) + { + $old = $this->_regex; + $this->_regex = $regex; + + return $old; + } + + /** + * Get token representation. + * + * @return string|null + */ + public function getRepresentation() + { + return $this->_regex; + } + + /** + * Get AST of the token representation. + * + * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode + */ + public function getAST() + { + if (null === static::$_regexCompiler) { + $stream = new File\Read('hoa://Library/Regex/Grammar.pp'); + $stream->rewind(); + + static::$_regexCompiler = Compiler\Llk::load($stream); + } + + if (null === $this->_ast) { + $this->_ast = static::$_regexCompiler->parse( + (string) $this->getRepresentation() + ); + } + + return $this->_ast; + } + + /** + * Set token value. + * + * @param string $value Value. + * @return string + */ + public function setValue(string $value) + { + $old = $this->_value; + $this->_value = $value; + + return $old; + } + + /** + * Get token value. + * + * @return string + */ + public function getValue(): string + { + return $this->_value; + } + + /** + * Set token offset. + * + * @param int $offset Offset. + * @return int + */ + public function setOffset($offset) + { + $old = $this->_offset; + $this->_offset = $offset; + + return $old; + } + + /** + * Get token offset. + * + * @return int + */ + public function getOffset() + { + return $this->_offset; + } + + /** + * Set whether the token is kept or not in the AST. + * + * @param bool $kept Kept. + * @return bool + */ + public function setKept($kept) + { + $old = $this->_kept; + $this->_kept = $kept; + + return $old; + } + + /** + * Check whether the token is kept in the AST or not. + * + * @return bool + */ + public function isKept() + { + return $this->_kept; + } + + /** + * Get unification index. + * + * @return int + */ + public function getUnificationIndex() + { + return $this->_unification; + } +} diff --git a/src/Type/Compiler/Llk/TreeNode.php b/src/Type/Compiler/Llk/TreeNode.php new file mode 100644 index 000000000..39baed732 --- /dev/null +++ b/src/Type/Compiler/Llk/TreeNode.php @@ -0,0 +1,362 @@ +setId($id); + + if (!empty($value)) { + $this->setValue($value); + } + + $this->setChildren($children); + + if (null !== $parent) { + $this->setParent($parent); + } + + return; + } + + /** + * Set ID. + * + * @param string $id ID. + * @return string + */ + public function setId(string $id) + { + $old = $this->_id; + $this->_id = $id; + + return $old; + } + + /** + * Get ID. + * + * @return string + */ + public function getId() + { + return $this->_id; + } + + /** + * Set value. + * + * @param array $value Value (token & value). + * @return array|null + */ + public function setValue(array $value) + { + $old = $this->_value; + $this->_value = $value; + + return $old; + } + + /** + * Get value. + * + * @return array|null + */ + public function getValue() + { + return $this->_value; + } + + /** + * Get value token. + * + * @return string + */ + public function getValueToken() + { + return + isset($this->_value['token']) + ? $this->_value['token'] + : null; + } + + /** + * Get value value. + * + * @return string + */ + public function getValueValue() + { + return + isset($this->_value['value']) + ? $this->_value['value'] + : null; + } + + /** + * Get token offset. + * + * @return int + */ + public function getOffset() + { + return + isset($this->_value['offset']) + ? $this->_value['offset'] + : 0; + } + + /** + * Check if the node represents a token or not. + * + * @return bool + */ + public function isToken() + { + return !empty($this->_value); + } + + /** + * Prepend a child. + * + * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $child Child. + * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode + */ + public function prependChild(self $child) + { + array_unshift($this->_children, $child); + + return $this; + } + + /** + * Append a child. + * + * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $child Child. + * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode + */ + public function appendChild(self $child) + { + $this->_children[] = $child; + + return $this; + } + + /** + * Set children. + * + * @param array $children Children. + * @return array + */ + public function setChildren(array $children) + { + $old = $this->_children; + $this->_children = $children; + + return $old; + } + + /** + * Get child. + * + * @param int $i Index. + * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode + */ + public function getChild($i) + { + return + true === $this->childExists($i) + ? $this->_children[$i] + : null; + } + + /** + * Get children. + * + * @return array + */ + public function getChildren() + { + return $this->_children; + } + + /** + * Get number of children. + * + * @return int + */ + public function getChildrenNumber() + { + return count($this->_children); + } + + /** + * Check if a child exists. + * + * @param int $i Index. + * @return bool + */ + public function childExists($i) + { + return array_key_exists($i, $this->_children); + } + + /** + * Set parent. + * + * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $parent Parent. + * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode|null + */ + public function setParent(self $parent) + { + $old = $this->_parent; + $this->_parent = $parent; + + return $old; + } + + /** + * Get parent. + * + * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode|null + */ + public function getParent() + { + return $this->_parent; + } + + /** + * Get data. + * + * @return array + */ + public function &getData() + { + return $this->_data; + } + + /** + * Accept a visitor. + * + * @param \Hoa\Visitor\Visit $visitor Visitor. + * @param mixed &$handle Handle (reference). + * @param mixed $eldnah Handle (no reference). + * @return mixed + */ + public function accept( + Visitor\Visit $visitor, + &$handle = null, + $eldnah = null + ) { + return $visitor->visit($this, $handle, $eldnah); + } + + /** + * Remove circular reference to the parent (help the garbage collector). + * + * @return void + */ + public function __destruct() + { + unset($this->_parent); + + return; + } +} diff --git a/src/Type/InnerParser.php b/src/Type/InnerParser.php index 736f52e42..081f71434 100644 --- a/src/Type/InnerParser.php +++ b/src/Type/InnerParser.php @@ -4,11 +4,11 @@ namespace JMS\Serializer\Type; -use Hoa\Compiler\Llk\Parser; -use Hoa\Compiler\Llk\Rule\Choice; -use Hoa\Compiler\Llk\Rule\Concatenation; -use Hoa\Compiler\Llk\Rule\Repetition; -use Hoa\Compiler\Llk\Rule\Token; +use JMS\Serializer\Type\Compiler\Llk\Parser; +use JMS\Serializer\Type\Compiler\Llk\Rule\Choice; +use JMS\Serializer\Type\Compiler\Llk\Rule\Concatenation; +use JMS\Serializer\Type\Compiler\Llk\Rule\Repetition; +use JMS\Serializer\Type\Compiler\Llk\Rule\Token; /** * @internal diff --git a/src/Type/Parser.php b/src/Type/Parser.php index 704cba59d..50793103c 100644 --- a/src/Type/Parser.php +++ b/src/Type/Parser.php @@ -4,7 +4,7 @@ namespace JMS\Serializer\Type; -use Hoa\Compiler\Exception; +use JMS\Serializer\Type\Compiler\Exception; use Hoa\Visitor\Visit; use JMS\Serializer\Type\Exception\SyntaxError; diff --git a/src/Type/TypeVisitor.php b/src/Type/TypeVisitor.php index ec140b100..c3b96bd52 100644 --- a/src/Type/TypeVisitor.php +++ b/src/Type/TypeVisitor.php @@ -4,7 +4,7 @@ namespace JMS\Serializer\Type; -use Hoa\Compiler\Llk\TreeNode; +use JMS\Serializer\Type\Compiler\Llk\TreeNode; use Hoa\Visitor\Element; use Hoa\Visitor\Visit; use JMS\Serializer\Type\Exception\InvalidNode; From 31e16d9865812f2e780af7fcf410d3817d4a79ba Mon Sep 17 00:00:00 2001 From: Alexey Kopytko Date: Mon, 13 Apr 2020 04:13:28 +0900 Subject: [PATCH 3/5] CS --- phpcs.xml.dist | 1 + src/Type/Parser.php | 2 +- src/Type/TypeVisitor.php | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 8771d3347..4737fea9e 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -12,6 +12,7 @@ src/ tests/ + src/Type/Compiler/* diff --git a/src/Type/Parser.php b/src/Type/Parser.php index 50793103c..159a193e2 100644 --- a/src/Type/Parser.php +++ b/src/Type/Parser.php @@ -4,8 +4,8 @@ namespace JMS\Serializer\Type; -use JMS\Serializer\Type\Compiler\Exception; use Hoa\Visitor\Visit; +use JMS\Serializer\Type\Compiler\Exception; use JMS\Serializer\Type\Exception\SyntaxError; final class Parser implements ParserInterface diff --git a/src/Type/TypeVisitor.php b/src/Type/TypeVisitor.php index c3b96bd52..44c561c16 100644 --- a/src/Type/TypeVisitor.php +++ b/src/Type/TypeVisitor.php @@ -4,9 +4,9 @@ namespace JMS\Serializer\Type; -use JMS\Serializer\Type\Compiler\Llk\TreeNode; use Hoa\Visitor\Element; use Hoa\Visitor\Visit; +use JMS\Serializer\Type\Compiler\Llk\TreeNode; use JMS\Serializer\Type\Exception\InvalidNode; use function strpos; From 5ad6063c641d33c463f28f147ed9e16156df8a96 Mon Sep 17 00:00:00 2001 From: Alexey Kopytko Date: Mon, 13 Apr 2020 04:32:00 +0900 Subject: [PATCH 4/5] CS --- phpcs.xml.dist | 1 - src/Type/Compiler/Exception.php | 9 +- src/Type/Compiler/Exception/Exception.php | 46 ------- .../Exception/FinalStateHasNotBeenReached.php | 11 +- src/Type/Compiler/Exception/InternalError.php | 8 +- src/Type/Compiler/Exception/Lexer.php | 11 +- src/Type/Compiler/Exception/Rule.php | 11 +- .../Compiler/Exception/UnexpectedToken.php | 9 +- .../Compiler/Exception/UnrecognizedToken.php | 27 ++-- src/Type/Compiler/Llk/Lexer.php | 55 ++++---- src/Type/Compiler/Llk/Llk.php | 10 +- src/Type/Compiler/Llk/Llk.pp | 94 ------------- src/Type/Compiler/Llk/Parser.php | 120 ++++++++--------- src/Type/Compiler/Llk/Rule.php | 60 ++++----- src/Type/Compiler/Llk/Rule/Choice.php | 8 +- src/Type/Compiler/Llk/Rule/Concatenation.php | 11 +- src/Type/Compiler/Llk/Rule/Ekzit.php | 9 +- src/Type/Compiler/Llk/Rule/Entry.php | 9 +- src/Type/Compiler/Llk/Rule/Invocation.php | 40 +++--- src/Type/Compiler/Llk/Rule/Repetition.php | 36 ++--- src/Type/Compiler/Llk/Rule/Rule.php | 46 ------- src/Type/Compiler/Llk/Rule/Token.php | 104 +++++---------- src/Type/Compiler/Llk/TreeNode.php | 125 +++++++----------- 23 files changed, 284 insertions(+), 576 deletions(-) delete mode 100644 src/Type/Compiler/Exception/Exception.php delete mode 100644 src/Type/Compiler/Llk/Llk.pp delete mode 100644 src/Type/Compiler/Llk/Rule/Rule.php diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 4737fea9e..8771d3347 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -12,7 +12,6 @@ src/ tests/ - src/Type/Compiler/* diff --git a/src/Type/Compiler/Exception.php b/src/Type/Compiler/Exception.php index a416f6358..7fbe2fe48 100644 --- a/src/Type/Compiler/Exception.php +++ b/src/Type/Compiler/Exception.php @@ -1,9 +1,12 @@ column; } diff --git a/src/Type/Compiler/Llk/Lexer.php b/src/Type/Compiler/Llk/Lexer.php index 33ea5d40f..3dcac205d 100644 --- a/src/Type/Compiler/Llk/Lexer.php +++ b/src/Type/Compiler/Llk/Lexer.php @@ -1,9 +1,12 @@ */ - public function lexMe($text, array $tokens): \Generator + public function lexMe(string $text, array $tokens): \Generator { $this->validateInputInUnicodeMode($text); @@ -136,7 +134,7 @@ public function lexMe($text, array $tokens): \Generator continue; } - list($lexeme, $namespace) = explode(':', $fullLexeme, 2); + [$lexeme, $namespace] = explode(':', $fullLexeme, 2); $stack |= ('__shift__' === substr($namespace, 0, 9)); @@ -147,7 +145,7 @@ public function lexMe($text, array $tokens): \Generator $tokens = $_tokens; } - if (true == $stack) { + if (true === $stack) { $this->_nsStack = new \SplStack(); } @@ -163,7 +161,7 @@ public function lexMe($text, array $tokens): \Generator [ mb_substr(substr($text, $offset), 0, 1), $offset + 1, - $text + $text, ], 1, $offset @@ -184,14 +182,14 @@ public function lexMe($text, array $tokens): \Generator 'length' => 0, 'namespace' => 'default', 'keep' => true, - 'offset' => $offset + 'offset' => $offset, ]; } /** * Compute the next token recognized at the beginning of the string. * - * @param int $offset Offset. + * @param int $offset Offset. * * @return (array|bool|int|string)[]|array[]|null * @@ -199,13 +197,13 @@ public function lexMe($text, array $tokens): \Generator * * @psalm-return array{token: string, value: string, length: int|false, namespace: array, keep: bool}|null */ - protected function nextToken($offset) + protected function nextToken(int $offset) { $tokenArray = &$this->_tokens[$this->_lexerState]; $previousNamespace = null; foreach ($tokenArray as $lexeme => $bucket) { - list($regex, $nextState) = $bucket; + [$regex, $nextState] = $bucket; if (null === $nextState) { $nextState = $this->_lexerState; @@ -234,7 +232,7 @@ protected function nextToken($offset) $i, $lexeme, $this->_lexerState, - $c + $c, ] ); } @@ -255,7 +253,7 @@ protected function nextToken($offset) [ $nextState, $lexeme, - $this->_lexerState + $this->_lexerState, ] ); } @@ -277,9 +275,9 @@ protected function nextToken($offset) /** * Check if a given lexeme is matched at the beginning of the text. * - * @param string $lexeme Name of the lexeme. - * @param string $regex Regular expression describing the lexeme. - * @param int $offset Offset. + * @param string $lexeme Name of the lexeme. + * @param string $regex Regular expression describing the lexeme. + * @param int $offset Offset. * * @return (int|false|string)[]|null * @@ -287,7 +285,7 @@ protected function nextToken($offset) * * @psalm-return array{token: string, value: string, length: int|false}|null */ - protected function matchLexeme($lexeme, $regex, $offset) + protected function matchLexeme(string $lexeme, string $regex, int $offset) { $_regex = str_replace('#', '\#', $regex); $preg = @preg_match( @@ -322,17 +320,16 @@ protected function matchLexeme($lexeme, $regex, $offset) return [ 'token' => $lexeme, 'value' => $matches[0], - 'length' => mb_strlen($matches[0]) + 'length' => mb_strlen($matches[0]), ]; } /** - * @param string $text * @return bool */ - private function validateInputInUnicodeMode($text) + private function validateInputInUnicodeMode(string $text) { - if (strpos($this->_pcreOptions, 'u') !== false && preg_match('##u', $text) === false) { + if (false !== strpos($this->_pcreOptions, 'u') && false === preg_match('##u', $text)) { throw new Compiler\Exception\Lexer( 'Text is not valid utf-8 string, you probably need to switch "lexer.unicode" setting off.' ); diff --git a/src/Type/Compiler/Llk/Llk.php b/src/Type/Compiler/Llk/Llk.php index 07338597a..daa040477 100644 --- a/src/Type/Compiler/Llk/Llk.php +++ b/src/Type/Compiler/Llk/Llk.php @@ -1,9 +1,12 @@ -%token named \(\) -%token node #[a-zA-Z_][a-zA-Z0-9_]*(:[mM])? - -%token capturing_ \( -%token _capturing \) -%token unification_ \[ -%token unification [0-9]+ -%token _unification \] - -#rule: - choice() - -choice: - concatenation() ( ::or:: concatenation() #choice )* - -concatenation: - repetition() ( repetition() #concatenation )* - -repetition: - simple() ( quantifier() #repetition )? ? - -simple: - ::capturing_:: choice() ::_capturing:: - | ::skipped:: ( ::unification_:: ::_unification:: )? - ::skipped:: #skipped - | ::kept_:: ( ::unification_:: ::_unification:: )? - ::_kept:: #kept - | ::named:: - -quantifier: - - | - | - | - | - | diff --git a/src/Type/Compiler/Llk/Parser.php b/src/Type/Compiler/Llk/Parser.php index cfe497c8e..57dfc0657 100644 --- a/src/Type/Compiler/Llk/Parser.php +++ b/src/Type/Compiler/Llk/Parser.php @@ -1,9 +1,12 @@ _tokens = $tokens; @@ -146,13 +147,15 @@ public function __construct( /** * Parse :-). * - * @param string $text Text to parse. - * @param string $rule The axiom, i.e. root rule. - * @param bool $tree Whether build tree or not. + * @param string $text Text to parse. + * @param string $rule The axiom, i.e. root rule. + * @param bool $tree Whether build tree or not. + * * @return mixed - * @throws \JMS\Serializer\Type\Compiler\Exception\UnexpectedToken + * + * @throws UnexpectedToken */ - final public function parse(string $text, string $rule = null, bool $tree = true) + final public function parse(string $text, ?string $rule = null, bool $tree = true) { $k = 1024; @@ -223,7 +226,7 @@ final public function parse(string $text, string $rule = null, bool $tree = true $token['token'], $line, $column, - $text + $text, ], $line, $column @@ -282,11 +285,10 @@ final protected function unfold() /** * Parse current rule. * - * @param \JMS\Serializer\Type\Compiler\Llk\Rule $zeRule Current rule. - * @param int $next Next rule index. - * @return bool + * @param Rule $zeRule Current rule. + * @param int $next Next rule index. */ - final protected function _parse(Rule $zeRule, $next) + final protected function _parse(Rule $zeRule, int $next): bool { $regex = null; if ($zeRule instanceof Rule\Token) { @@ -436,7 +438,7 @@ final protected function _parse(Rule $zeRule, $next) } else { $max = $zeRule->getMax(); - if (-1 != $max && $next > $max) { + if (-1 !== $max && $next > $max) { return false; } @@ -457,10 +459,8 @@ final protected function _parse(Rule $zeRule, $next) /** * Backtrack the trace. - * - * @return bool */ - final protected function backtrack() + final protected function backtrack(): bool { $found = false; @@ -499,11 +499,10 @@ final protected function backtrack() * Build AST from trace. * Walk through the trace iteratively and recursively. * - * @param int $i Current trace index. - * @param array &$children Collected children. - * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode + * @param int $i Current trace index. + * @param array &$children Collected children. */ - final protected function _buildTree($i = 0, &$children = []) + final protected function _buildTree(int $i = 0, array &$children = []) { $max = count($this->_trace); @@ -519,7 +518,7 @@ final protected function _buildTree($i = 0, &$children = []) // Optimization: Skip empty trace sequence. if ($nextTrace instanceof Rule\Ekzit && - $ruleName == $nextTrace->getRule()) { + $ruleName === $nextTrace->getRule()) { $i += 2; continue; @@ -532,7 +531,7 @@ final protected function _buildTree($i = 0, &$children = []) if (null !== $id) { $children[] = [ 'id' => $id, - 'options' => $rule->getNodeOptions() + 'options' => $rule->getNodeOptions(), ]; } @@ -554,7 +553,7 @@ final protected function _buildTree($i = 0, &$children = []) } elseif (true === is_array($pop) && null === $cId) { $cId = $pop['id']; $cOptions = $pop['options']; - } elseif ($ruleName == $pop) { + } elseif ($ruleName === $pop) { break; } } while (null !== $pop); @@ -603,7 +602,7 @@ final protected function _buildTree($i = 0, &$children = []) 'token' => $trace->getTokenName(), 'value' => $trace->getValue(), 'namespace' => $trace->getNamespace(), - 'offset' => $trace->getOffset() + 'offset' => $trace->getOffset(), ]); $children[] = $child; @@ -617,19 +616,18 @@ final protected function _buildTree($i = 0, &$children = []) /** * Try to merge directly children into an existing node. * - * @param array &$children Current children being gathering. - * @param array &$handle Children of the new node. - * @param string $cId Node ID. - * @param bool $recursive Whether we should merge recursively or - * not. - * @return bool + * @param array &$children Current children being gathering. + * @param array &$handle Children of the new node. + * @param string $cId Node ID. + * @param bool $recursive Whether we should merge recursively or + * not. */ final protected function mergeTree( - &$children, - &$handle, - $cId, - $recursive = false - ) { + array &$children, + array &$handle, + string $cId, + bool $recursive = false + ): bool { end($children); $last = current($children); @@ -661,11 +659,10 @@ final protected function mergeTree( * Merge recursively. * Please, see self::mergeTree() to know the context. * - * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $node Node that receives. - * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $newNode Node to merge. - * @return void + * @param TreeNode $node Node that receives. + * @param TreeNode $newNode Node to merge. */ - final protected function mergeTreeRecursive(TreeNode $node, TreeNode $newNode) + final protected function mergeTreeRecursive(TreeNode $node, TreeNode $newNode): void { $nNId = $newNode->getId(); @@ -696,10 +693,8 @@ final protected function mergeTreeRecursive(TreeNode $node, TreeNode $newNode) /** * Get AST. - * - * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode */ - final public function getTree() + final public function getTree(): TreeNode { return $this->_tree; } @@ -709,7 +704,7 @@ final public function getTree() * * @return array */ - final public function getTrace() + final public function getTrace(): array { return $this->_trace; } @@ -719,7 +714,7 @@ final public function getTrace() * * @return array */ - final public function getPragmas() + final public function getPragmas(): array { return $this->_pragmas; } @@ -729,17 +724,15 @@ final public function getPragmas() * * @return array */ - final public function getTokens() + final public function getTokens(): array { return $this->_tokens; } /** * Get the lexer iterator. - * - * @return \Hoa\Iterator\Buffer */ - final public function getTokenSequence() + final public function getTokenSequence(): Buffer { return $this->_tokenSequence; } @@ -747,10 +740,9 @@ final public function getTokenSequence() /** * Get rule by name. * - * @param string $name Rule name. - * @return \JMS\Serializer\Type\Compiler\Llk\Rule + * @param string $name Rule name. */ - final public function getRule($name) + final public function getRule(string $name): Rule { if (!isset($this->_rules[$name])) { return null; @@ -771,10 +763,8 @@ final public function getRules() /** * Get root rule. - * - * @return string */ - final public function getRootRule() + final public function getRootRule(): string { \assert([] !== $this->_rules); diff --git a/src/Type/Compiler/Llk/Rule.php b/src/Type/Compiler/Llk/Rule.php index 50894b2ab..58cc9e53e 100644 --- a/src/Type/Compiler/Llk/Rule.php +++ b/src/Type/Compiler/Llk/Rule.php @@ -1,9 +1,12 @@ _nodeId; - if (false !== $pos = strpos($nodeId, ':')) { + if (null !== $nodeId && false !== $pos = strpos($nodeId, ':')) { $this->_nodeId = substr($nodeId, 0, $pos); $this->_nodeOptions = str_split(substr($nodeId, $pos + 1)); } else { @@ -194,10 +190,8 @@ public function setNodeId($nodeId) /** * Get node ID. - * - * @return string */ - public function getNodeId() + public function getNodeId(): ?string { return $this->_nodeId; } @@ -215,10 +209,9 @@ public function getNodeOptions(): array /** * Set default ID. * - * @param string $defaultId Default ID. - * @return string + * @param string $defaultId Default ID. */ - public function setDefaultId($defaultId) + public function setDefaultId(string $defaultId): ?string { $old = $this->_defaultId; @@ -235,10 +228,8 @@ public function setDefaultId($defaultId) /** * Get default ID. - * - * @return string */ - public function getDefaultId() + public function getDefaultId(): ?string { return $this->_defaultId; } @@ -248,7 +239,7 @@ public function getDefaultId() * * @return array */ - public function getDefaultOptions() + public function getDefaultOptions(): array { return $this->_defaultOptions; } @@ -256,10 +247,9 @@ public function getDefaultOptions() /** * Set PP representation of the rule. * - * @param string $pp PP representation. - * @return string + * @param string $pp PP representation. */ - public function setPPRepresentation($pp) + public function setPPRepresentation(string $pp): ?string { $old = $this->_pp; $this->_pp = $pp; @@ -270,20 +260,16 @@ public function setPPRepresentation($pp) /** * Get PP representation of the rule. - * - * @return string */ - public function getPPRepresentation() + public function getPPRepresentation(): string { return $this->_pp; } /** * Check whether the rule is transitional or not. - * - * @return bool */ - public function isTransitional() + public function isTransitional(): bool { return $this->_transitional; } diff --git a/src/Type/Compiler/Llk/Rule/Choice.php b/src/Type/Compiler/Llk/Rule/Choice.php index 3112ec6b1..557266317 100644 --- a/src/Type/Compiler/Llk/Rule/Choice.php +++ b/src/Type/Compiler/Llk/Rule/Choice.php @@ -1,9 +1,12 @@ _rule = $rule; $this->_data = $data; @@ -110,7 +107,7 @@ public function __construct( /** * Get rule name. * - * @return string + * @return string|int */ public function getRule() { @@ -132,7 +129,7 @@ public function getData() * * @return array */ - public function getTodo() + public function getTodo(): array { return $this->_todo; } @@ -140,10 +137,9 @@ public function getTodo() /** * Set depth in trace. * - * @param int $depth Depth. - * @return int + * @param int $depth Depth. */ - public function setDepth($depth) + public function setDepth(int $depth): int { $old = $this->_depth; $this->_depth = $depth; @@ -153,20 +149,16 @@ public function setDepth($depth) /** * Get depth in trace. - * - * @return int */ - public function getDepth() + public function getDepth(): int { return $this->_depth; } /** * Check whether the rule is transitional or not. - * - * @return bool */ - public function isTransitional() + public function isTransitional(): bool { return $this->_transitional; } diff --git a/src/Type/Compiler/Llk/Rule/Repetition.php b/src/Type/Compiler/Llk/Rule/Repetition.php index 86edfe638..648f66a85 100644 --- a/src/Type/Compiler/Llk/Rule/Repetition.php +++ b/src/Type/Compiler/Llk/Rule/Repetition.php @@ -1,9 +1,12 @@ _min; } /** * Get maximum bound. - * - * @return int */ - public function getMax() + public function getMax(): int { return $this->_max; } /** * Check whether the maximum repetition is unbounded. - * - * @return bool */ - public function isInfinite() + public function isInfinite(): bool { return -1 === $this->getMax(); } diff --git a/src/Type/Compiler/Llk/Rule/Rule.php b/src/Type/Compiler/Llk/Rule/Rule.php deleted file mode 100644 index 3b5133b6e..000000000 --- a/src/Type/Compiler/Llk/Rule/Rule.php +++ /dev/null @@ -1,46 +0,0 @@ -_tokenName; } @@ -152,10 +148,9 @@ public function getTokenName() /** * Set token namespace. * - * @param string $namespace Namespace. - * @return string + * @param string $namespace Namespace. */ - public function setNamespace($namespace) + public function setNamespace(string $namespace): ?string { $old = $this->_namespace; $this->_namespace = $namespace; @@ -165,10 +160,8 @@ public function setNamespace($namespace) /** * Get token namespace. - * - * @return string */ - public function getNamespace() + public function getNamespace(): ?string { return $this->_namespace; } @@ -176,10 +169,9 @@ public function getNamespace() /** * Set representation. * - * @param string $regex Representation. - * @return string|null + * @param string $regex Representation. */ - public function setRepresentation(string $regex) + public function setRepresentation(string $regex): ?string { $old = $this->_regex; $this->_regex = $regex; @@ -189,44 +181,18 @@ public function setRepresentation(string $regex) /** * Get token representation. - * - * @return string|null */ - public function getRepresentation() + public function getRepresentation(): ?string { return $this->_regex; } - /** - * Get AST of the token representation. - * - * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode - */ - public function getAST() - { - if (null === static::$_regexCompiler) { - $stream = new File\Read('hoa://Library/Regex/Grammar.pp'); - $stream->rewind(); - - static::$_regexCompiler = Compiler\Llk::load($stream); - } - - if (null === $this->_ast) { - $this->_ast = static::$_regexCompiler->parse( - (string) $this->getRepresentation() - ); - } - - return $this->_ast; - } - /** * Set token value. * - * @param string $value Value. - * @return string + * @param ?string $value Value. */ - public function setValue(string $value) + public function setValue(string $value): ?string { $old = $this->_value; $this->_value = $value; @@ -236,8 +202,6 @@ public function setValue(string $value) /** * Get token value. - * - * @return string */ public function getValue(): string { @@ -247,10 +211,9 @@ public function getValue(): string /** * Set token offset. * - * @param int $offset Offset. - * @return int + * @param int $offset Offset. */ - public function setOffset($offset) + public function setOffset(int $offset): int { $old = $this->_offset; $this->_offset = $offset; @@ -260,10 +223,8 @@ public function setOffset($offset) /** * Get token offset. - * - * @return int */ - public function getOffset() + public function getOffset(): int { return $this->_offset; } @@ -271,10 +232,9 @@ public function getOffset() /** * Set whether the token is kept or not in the AST. * - * @param bool $kept Kept. - * @return bool + * @param bool $kept Kept. */ - public function setKept($kept) + public function setKept(bool $kept): bool { $old = $this->_kept; $this->_kept = $kept; @@ -284,20 +244,16 @@ public function setKept($kept) /** * Check whether the token is kept in the AST or not. - * - * @return bool */ - public function isKept() + public function isKept(): bool { return $this->_kept; } /** * Get unification index. - * - * @return int */ - public function getUnificationIndex() + public function getUnificationIndex(): int { return $this->_unification; } diff --git a/src/Type/Compiler/Llk/TreeNode.php b/src/Type/Compiler/Llk/TreeNode.php index 39baed732..7a0575b81 100644 --- a/src/Type/Compiler/Llk/TreeNode.php +++ b/src/Type/Compiler/Llk/TreeNode.php @@ -1,9 +1,12 @@ setId($id); @@ -119,10 +117,9 @@ public function __construct( /** * Set ID. * - * @param string $id ID. - * @return string + * @param string $id ID. */ - public function setId(string $id) + public function setId(string $id): string { $old = $this->_id; $this->_id = $id; @@ -132,10 +129,8 @@ public function setId(string $id) /** * Get ID. - * - * @return string */ - public function getId() + public function getId(): string { return $this->_id; } @@ -143,10 +138,11 @@ public function getId() /** * Set value. * - * @param array $value Value (token & value). + * @param array $value Value (token & value). + * * @return array|null */ - public function setValue(array $value) + public function setValue(array $value): ?array { $old = $this->_value; $this->_value = $value; @@ -159,56 +155,39 @@ public function setValue(array $value) * * @return array|null */ - public function getValue() + public function getValue(): ?array { return $this->_value; } /** * Get value token. - * - * @return string */ - public function getValueToken() + public function getValueToken(): string { - return - isset($this->_value['token']) - ? $this->_value['token'] - : null; + return $this->_value['token'] ?? null; } /** * Get value value. - * - * @return string */ - public function getValueValue() + public function getValueValue(): string { - return - isset($this->_value['value']) - ? $this->_value['value'] - : null; + return $this->_value['value'] ?? null; } /** * Get token offset. - * - * @return int */ - public function getOffset() + public function getOffset(): int { - return - isset($this->_value['offset']) - ? $this->_value['offset'] - : 0; + return $this->_value['offset'] ?? 0; } /** * Check if the node represents a token or not. - * - * @return bool */ - public function isToken() + public function isToken(): bool { return !empty($this->_value); } @@ -216,10 +195,9 @@ public function isToken() /** * Prepend a child. * - * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $child Child. - * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode + * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $child Child. */ - public function prependChild(self $child) + public function prependChild(self $child): \JMS\Serializer\Type\Compiler\Llk\TreeNode { array_unshift($this->_children, $child); @@ -229,10 +207,9 @@ public function prependChild(self $child) /** * Append a child. * - * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $child Child. - * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode + * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $child Child. */ - public function appendChild(self $child) + public function appendChild(self $child): \JMS\Serializer\Type\Compiler\Llk\TreeNode { $this->_children[] = $child; @@ -242,10 +219,11 @@ public function appendChild(self $child) /** * Set children. * - * @param array $children Children. + * @param array $children Children. + * * @return array */ - public function setChildren(array $children) + public function setChildren(array $children): array { $old = $this->_children; $this->_children = $children; @@ -256,13 +234,11 @@ public function setChildren(array $children) /** * Get child. * - * @param int $i Index. - * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode + * @param int $i Index. */ - public function getChild($i) + public function getChild(int $i): \JMS\Serializer\Type\Compiler\Llk\TreeNode { - return - true === $this->childExists($i) + return true === $this->childExists($i) ? $this->_children[$i] : null; } @@ -272,17 +248,15 @@ public function getChild($i) * * @return array */ - public function getChildren() + public function getChildren(): array { return $this->_children; } /** * Get number of children. - * - * @return int */ - public function getChildrenNumber() + public function getChildrenNumber(): int { return count($this->_children); } @@ -290,10 +264,9 @@ public function getChildrenNumber() /** * Check if a child exists. * - * @param int $i Index. - * @return bool + * @param int $i Index. */ - public function childExists($i) + public function childExists(int $i): bool { return array_key_exists($i, $this->_children); } @@ -301,10 +274,9 @@ public function childExists($i) /** * Set parent. * - * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $parent Parent. - * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode|null + * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $parent Parent. */ - public function setParent(self $parent) + public function setParent(self $parent): ?\JMS\Serializer\Type\Compiler\Llk\TreeNode { $old = $this->_parent; $this->_parent = $parent; @@ -314,10 +286,8 @@ public function setParent(self $parent) /** * Get parent. - * - * @return \JMS\Serializer\Type\Compiler\Llk\TreeNode|null */ - public function getParent() + public function getParent(): ?\JMS\Serializer\Type\Compiler\Llk\TreeNode { return $this->_parent; } @@ -327,7 +297,7 @@ public function getParent() * * @return array */ - public function &getData() + public function &getData(): array { return $this->_data; } @@ -335,15 +305,16 @@ public function &getData() /** * Accept a visitor. * - * @param \Hoa\Visitor\Visit $visitor Visitor. - * @param mixed &$handle Handle (reference). - * @param mixed $eldnah Handle (no reference). + * @param Visit $visitor Visitor. + * @param mixed &$handle Handle (reference). + * @param mixed $eldnah Handle (no reference). + * * @return mixed */ public function accept( Visitor\Visit $visitor, &$handle = null, - $eldnah = null + $eldnah = null ) { return $visitor->visit($this, $handle, $eldnah); } From 5626ee1ca41196f99a27dfc3e0ea8b1ae4f1dc37 Mon Sep 17 00:00:00 2001 From: Alexey Kopytko Date: Mon, 13 Apr 2020 04:50:33 +0900 Subject: [PATCH 5/5] More CS --- src/Type/Compiler/Exception.php | 6 +++- src/Type/Compiler/Llk/Lexer.php | 9 ++---- src/Type/Compiler/Llk/Llk.php | 50 ------------------------------ src/Type/Compiler/Llk/Parser.php | 4 ++- src/Type/Compiler/Llk/Rule.php | 4 ++- src/Type/Compiler/Llk/TreeNode.php | 20 ++++++------ 6 files changed, 24 insertions(+), 69 deletions(-) delete mode 100644 src/Type/Compiler/Llk/Llk.php diff --git a/src/Type/Compiler/Exception.php b/src/Type/Compiler/Exception.php index 7fbe2fe48..813555ae1 100644 --- a/src/Type/Compiler/Exception.php +++ b/src/Type/Compiler/Exception.php @@ -45,7 +45,11 @@ */ class Exception extends \Exception { - public function __construct($message, $code = 0, $arguments = []) + /** + * @param number $code + * @param array $arguments + */ + public function __construct(string $message, int $code = 0, array $arguments = []) { parent::__construct(vsprintf($message, (array) $arguments), $code); } diff --git a/src/Type/Compiler/Llk/Lexer.php b/src/Type/Compiler/Llk/Lexer.php index 3dcac205d..02d7a806d 100644 --- a/src/Type/Compiler/Llk/Lexer.php +++ b/src/Type/Compiler/Llk/Lexer.php @@ -193,7 +193,7 @@ public function lexMe(string $text, array $tokens): \Generator * * @return (array|bool|int|string)[]|array[]|null * - * @throws \JMS\Serializer\Type\Compiler\Exception\Lexer + * @throws Compiler\Exception\Lexer * * @psalm-return array{token: string, value: string, length: int|false, namespace: array, keep: bool}|null */ @@ -281,7 +281,7 @@ protected function nextToken(int $offset) * * @return (int|false|string)[]|null * - * @throws \JMS\Serializer\Type\Compiler\Exception\Lexer + * @throws Compiler\Exception\Lexer * * @psalm-return array{token: string, value: string, length: int|false}|null */ @@ -324,10 +324,7 @@ protected function matchLexeme(string $lexeme, string $regex, int $offset) ]; } - /** - * @return bool - */ - private function validateInputInUnicodeMode(string $text) + private function validateInputInUnicodeMode(string $text): void { if (false !== strpos($this->_pcreOptions, 'u') && false === preg_match('##u', $text)) { throw new Compiler\Exception\Lexer( diff --git a/src/Type/Compiler/Llk/Llk.php b/src/Type/Compiler/Llk/Llk.php deleted file mode 100644 index daa040477..000000000 --- a/src/Type/Compiler/Llk/Llk.php +++ /dev/null @@ -1,50 +0,0 @@ -_rules; } diff --git a/src/Type/Compiler/Llk/Rule.php b/src/Type/Compiler/Llk/Rule.php index 58cc9e53e..434c20f62 100644 --- a/src/Type/Compiler/Llk/Rule.php +++ b/src/Type/Compiler/Llk/Rule.php @@ -123,7 +123,9 @@ public function __construct($name, $children, $nodeId = null) /** * Set rule name. * - * @param string|int|null $name Rule name. + * @param string|int|null $name Rule name. + * + * @return string|int|null */ public function setName($name) { diff --git a/src/Type/Compiler/Llk/TreeNode.php b/src/Type/Compiler/Llk/TreeNode.php index 7a0575b81..c9ed5da00 100644 --- a/src/Type/Compiler/Llk/TreeNode.php +++ b/src/Type/Compiler/Llk/TreeNode.php @@ -74,7 +74,7 @@ final class TreeNode implements Visitor\Element /** * Parent. * - * @var \JMS\Serializer\Type\Compiler\Llk\TreeNode|null + * @var TreeNode|null */ protected $_parent = null; @@ -91,7 +91,7 @@ final class TreeNode implements Visitor\Element * @param string $id ID. * @param array $value Value. * @param array $children Children. - * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $parent Parent. + * @param TreeNode $parent Parent. */ public function __construct( string $id, @@ -195,9 +195,9 @@ public function isToken(): bool /** * Prepend a child. * - * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $child Child. + * @param TreeNode $child Child. */ - public function prependChild(self $child): \JMS\Serializer\Type\Compiler\Llk\TreeNode + public function prependChild(self $child): TreeNode { array_unshift($this->_children, $child); @@ -207,9 +207,9 @@ public function prependChild(self $child): \JMS\Serializer\Type\Compiler\Llk\Tre /** * Append a child. * - * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $child Child. + * @param TreeNode $child Child. */ - public function appendChild(self $child): \JMS\Serializer\Type\Compiler\Llk\TreeNode + public function appendChild(self $child): TreeNode { $this->_children[] = $child; @@ -236,7 +236,7 @@ public function setChildren(array $children): array * * @param int $i Index. */ - public function getChild(int $i): \JMS\Serializer\Type\Compiler\Llk\TreeNode + public function getChild(int $i): TreeNode { return true === $this->childExists($i) ? $this->_children[$i] @@ -274,9 +274,9 @@ public function childExists(int $i): bool /** * Set parent. * - * @param \JMS\Serializer\Type\Compiler\Llk\TreeNode $parent Parent. + * @param TreeNode $parent Parent. */ - public function setParent(self $parent): ?\JMS\Serializer\Type\Compiler\Llk\TreeNode + public function setParent(self $parent): ?TreeNode { $old = $this->_parent; $this->_parent = $parent; @@ -287,7 +287,7 @@ public function setParent(self $parent): ?\JMS\Serializer\Type\Compiler\Llk\Tree /** * Get parent. */ - public function getParent(): ?\JMS\Serializer\Type\Compiler\Llk\TreeNode + public function getParent(): ?TreeNode { return $this->_parent; }