Backups Created:
/home/japatmex/public_html/wp-content/edit-wolf.php
Savvy
W
olf -
MANAGER
Edit File: Parser.php
<?php /** * This file is part of the Nette Framework (https://nette.org) * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ declare(strict_types=1); namespace Nette\Neon; /** @internal */ final class Parser { /** @var TokenStream */ private $tokens; /** @var int[] */ private $posToLine = []; public function parse(TokenStream $tokens): Node { $this->tokens = $tokens; $this->initLines(); while ($this->tokens->consume(Token::Newline)); $node = $this->parseBlock($this->tokens->getIndentation()); while ($this->tokens->consume(Token::Newline)); if ($this->tokens->isNext()) { $this->tokens->error(); } return $node; } private function parseBlock(string $indent, bool $onlyBullets = false): Node { $res = new Node\BlockArrayNode($indent); $this->injectPos($res); $keyCheck = []; loop: $item = new Node\ArrayItemNode; $this->injectPos($item); if ($this->tokens->consume('-')) { // continue } elseif (!$this->tokens->isNext() || $onlyBullets) { return $res->items ? $res : $this->injectPos(new Node\LiteralNode(null)); } else { $value = $this->parseValue(); if ($this->tokens->consume(':', '=')) { $this->checkArrayKey($value, $keyCheck); $item->key = $value; } else { if ($res->items) { $this->tokens->error(); } return $value; } } $res->items[] = $item; $item->value = new Node\LiteralNode(null); $this->injectPos($item->value); if ($this->tokens->consume(Token::Newline)) { while ($this->tokens->consume(Token::Newline)); $nextIndent = $this->tokens->getIndentation(); if (strncmp($nextIndent, $indent, min(strlen($nextIndent), strlen($indent)))) { $this->tokens->error('Invalid combination of tabs and spaces'); } elseif (strlen($nextIndent) > strlen($indent)) { // open new block $item->value = $this->parseBlock($nextIndent); } elseif (strlen($nextIndent) < strlen($indent)) { // close block return $res; } elseif ($item->key !== null && $this->tokens->isNext('-')) { // special dash subblock $item->value = $this->parseBlock($indent, true); } } elseif ($item->key === null) { $item->value = $this->parseBlock($indent . ' '); // open new block after dash } elseif ($this->tokens->isNext()) { $item->value = $this->parseValue(); if ($this->tokens->isNext() && !$this->tokens->isNext(Token::Newline)) { $this->tokens->error(); } } if ($item->value instanceof Node\BlockArrayNode) { $item->value->indentation = substr($item->value->indentation, strlen($indent)); } $this->injectPos($res, $res->startTokenPos, $item->value->endTokenPos); $this->injectPos($item, $item->startTokenPos, $item->value->endTokenPos); while ($this->tokens->consume(Token::Newline)); if (!$this->tokens->isNext()) { return $res; } $nextIndent = $this->tokens->getIndentation(); if (strncmp($nextIndent, $indent, min(strlen($nextIndent), strlen($indent)))) { $this->tokens->error('Invalid combination of tabs and spaces'); } elseif (strlen($nextIndent) > strlen($indent)) { $this->tokens->error('Bad indentation'); } elseif (strlen($nextIndent) < strlen($indent)) { // close block return $res; } goto loop; } private function parseValue(): Node { if ($token = $this->tokens->consume(Token::String)) { try { $node = new Node\StringNode(Node\StringNode::parse($token->value)); $this->injectPos($node, $this->tokens->getPos() - 1); } catch (Exception $e) { $this->tokens->error($e->getMessage(), $this->tokens->getPos() - 1); } } elseif ($token = $this->tokens->consume(Token::Literal)) { $pos = $this->tokens->getPos() - 1; $node = new Node\LiteralNode(Node\LiteralNode::parse($token->value, $this->tokens->isNext(':', '='))); $this->injectPos($node, $pos); } elseif ($this->tokens->isNext('[', '(', '{')) { $node = $this->parseBraces(); } else { $this->tokens->error(); } return $this->parseEntity($node); } private function parseEntity(Node $node): Node { if (!$this->tokens->isNext('(')) { return $node; } $attributes = $this->parseBraces(); $entities[] = $this->injectPos(new Node\EntityNode($node, $attributes->items), $node->startTokenPos, $attributes->endTokenPos); while ($token = $this->tokens->consume(Token::Literal)) { $valueNode = new Node\LiteralNode(Node\LiteralNode::parse($token->value)); $this->injectPos($valueNode, $this->tokens->getPos() - 1); if ($this->tokens->isNext('(')) { $attributes = $this->parseBraces(); $entities[] = $this->injectPos(new Node\EntityNode($valueNode, $attributes->items), $valueNode->startTokenPos, $attributes->endTokenPos); } else { $entities[] = $this->injectPos(new Node\EntityNode($valueNode), $valueNode->startTokenPos); break; } } return count($entities) === 1 ? $entities[0] : $this->injectPos(new Node\EntityChainNode($entities), $node->startTokenPos, end($entities)->endTokenPos); } private function parseBraces(): Node\InlineArrayNode { $token = $this->tokens->consume(); $endBrace = ['[' => ']', '{' => '}', '(' => ')'][$token->value]; $res = new Node\InlineArrayNode($token->value); $this->injectPos($res, $this->tokens->getPos() - 1); $keyCheck = []; loop: while ($this->tokens->consume(Token::Newline)); if ($this->tokens->consume($endBrace)) { $this->injectPos($res, $res->startTokenPos, $this->tokens->getPos() - 1); return $res; } $res->items[] = $item = new Node\ArrayItemNode; $this->injectPos($item, $this->tokens->getPos()); $value = $this->parseValue(); if ($this->tokens->consume(':', '=')) { $this->checkArrayKey($value, $keyCheck); $item->key = $value; $item->value = $this->tokens->isNext(Token::Newline, ',', $endBrace) ? $this->injectPos(new Node\LiteralNode(null), $this->tokens->getPos()) : $this->parseValue(); } else { $item->value = $value; } $this->injectPos($item, $item->startTokenPos, $item->value->endTokenPos); if ($this->tokens->consume(',', Token::Newline)) { goto loop; } while ($this->tokens->consume(Token::Newline)); if (!$this->tokens->isNext($endBrace)) { $this->tokens->error(); } goto loop; } /** @param true[] $arr */ private function checkArrayKey(Node $key, array &$arr): void { if ((!$key instanceof Node\StringNode && !$key instanceof Node\LiteralNode) || !is_scalar($key->value)) { $this->tokens->error('Unacceptable key', $key->startTokenPos); } $k = (string) $key->value; if (array_key_exists($k, $arr)) { $this->tokens->error("Duplicated key '$k'", $key->startTokenPos); } $arr[$k] = true; } private function injectPos(Node $node, int $start = null, int $end = null): Node { $node->startTokenPos = $start ?? $this->tokens->getPos(); $node->startLine = $this->posToLine[$node->startTokenPos]; $node->endTokenPos = $end ?? $node->startTokenPos; $node->endLine = $this->posToLine[$node->endTokenPos + 1] ?? end($this->posToLine); return $node; } private function initLines(): void { $this->posToLine = []; $line = 1; foreach ($this->tokens->getTokens() as $token) { $this->posToLine[] = $line; $line += substr_count($token->value, "\n"); } $this->posToLine[] = $line; } }