Пример #1
0
 /**
  * @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;
 }
Пример #2
0
 /**
  * Transpiles all nodes in an abstract syntax tree
  *
  * @param AbstractSyntaxTree $ast The abstract syntax tree to transpile
  * @return string The view with transpiled nodes
  * @throws RuntimeException Thrown if the nodes could not be transpiled
  */
 protected function transpileNodes(AbstractSyntaxTree $ast)
 {
     $transpiledView = "";
     $rootNode = $ast->getRootNode();
     $previousNodeWasExpression = false;
     foreach ($rootNode->getChildren() as $childNode) {
         switch (get_class($childNode)) {
             case DirectiveNode::class:
                 $transpiledView .= $this->transpileDirectiveNode($childNode);
                 $previousNodeWasExpression = false;
                 break;
             case SanitizedTagNode::class:
                 $transpiledView .= $this->transpileSanitizedTagNode($childNode);
                 $previousNodeWasExpression = false;
                 break;
             case UnsanitizedTagNode::class:
                 $transpiledView .= $this->transpileUnsanitizedTagNode($childNode);
                 $previousNodeWasExpression = false;
                 break;
             case CommentNode::class:
                 $transpiledView .= $this->transpileCommentNode($childNode);
                 $previousNodeWasExpression = false;
                 break;
             case ExpressionNode::class:
                 // To keep expressions from running against each other, we pad all expressions but the first
                 if ($previousNodeWasExpression) {
                     $transpiledView .= ' ';
                 }
                 $transpiledView .= $this->transpileExpressionNode($childNode);
                 $previousNodeWasExpression = true;
                 break;
             default:
                 throw new RuntimeException(sprintf("Unknown node class %s", get_class($childNode)));
         }
     }
     return $transpiledView;
 }