/** * @inheritdoc */ public function parse(array $tokens) { $ast = new AbstractSyntaxTree(); /** @var Token $token */ foreach ($tokens as $token) { switch ($token->getType()) { case TokenTypes::T_EXPRESSION: $ast->getCurrentNode()->addChild(new ExpressionNode($token->getValue())); break; case TokenTypes::T_DIRECTIVE_OPEN: if (!$ast->getCurrentNode()->isRoot()) { $this->throwImproperlyNestedNodeException($token); } $childNode = new DirectiveNode(); $ast->getCurrentNode()->addChild($childNode); $ast->setCurrentNode($childNode); break; case TokenTypes::T_DIRECTIVE_CLOSE: if (!$ast->getCurrentNode()->isDirective()) { $this->throwUnopenedDelimiterException($token); } $ast->setCurrentNode($ast->getCurrentNode()->getParent()); break; case TokenTypes::T_DIRECTIVE_NAME: $ast->getCurrentNode()->addChild(new DirectiveNameNode($token->getValue())); break; case TokenTypes::T_SANITIZED_TAG_OPEN: if (!$ast->getCurrentNode()->isRoot()) { $this->throwImproperlyNestedNodeException($token); } $childNode = new SanitizedTagNode(); $ast->getCurrentNode()->addChild($childNode); $ast->setCurrentNode($childNode); break; case TokenTypes::T_SANITIZED_TAG_CLOSE: if (!$ast->getCurrentNode()->isSanitizedTag()) { $this->throwUnopenedDelimiterException($token); } $ast->setCurrentNode($ast->getCurrentNode()->getParent()); break; case TokenTypes::T_UNSANITIZED_TAG_OPEN: if (!$ast->getCurrentNode()->isRoot()) { $this->throwImproperlyNestedNodeException($token); } $childNode = new UnsanitizedTagNode(); $ast->getCurrentNode()->addChild($childNode); $ast->setCurrentNode($childNode); break; case TokenTypes::T_UNSANITIZED_TAG_CLOSE: if (!$ast->getCurrentNode()->isUnsanitizedTag()) { $this->throwUnopenedDelimiterException($token); } $ast->setCurrentNode($ast->getCurrentNode()->getParent()); break; case TokenTypes::T_COMMENT_OPEN: if (!$ast->getCurrentNode()->isRoot()) { $this->throwImproperlyNestedNodeException($token); } $childNode = new CommentNode(); $ast->getCurrentNode()->addChild($childNode); $ast->setCurrentNode($childNode); break; case TokenTypes::T_COMMENT_CLOSE: if (!$ast->getCurrentNode()->isComment()) { $this->throwUnopenedDelimiterException($token); } $ast->setCurrentNode($ast->getCurrentNode()->getParent()); break; case TokenTypes::T_PHP_TAG_OPEN: $ast->getCurrentNode()->addChild(new ExpressionNode($token->getValue())); break; case TokenTypes::T_PHP_TAG_CLOSE: $ast->getCurrentNode()->addChild(new ExpressionNode($token->getValue())); break; default: throw new RuntimeException(sprintf('Unknown token type "%s" with value "%s" near line %d', $token->getType(), $token->getValue(), $token->getLine())); } } if (!$ast->getCurrentNode()->isRoot()) { throw new RuntimeException(sprintf("Expected close delimiter, found %s", $ast->getCurrentNode()->getValue())); } return $ast; }