mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-27 00:56:20 +00:00
72 lines
2.5 KiB
PHP
72 lines
2.5 KiB
PHP
|
<?php
|
||
|
|
||
|
/**
|
||
|
* Converts a stream of HTMLPurifier_Token into an HTMLPurifier_Node,
|
||
|
* and back again.
|
||
|
*
|
||
|
* @note This transformation is not an equivalence. We mutate the input
|
||
|
* token stream to make it so; see all [MUT] markers in code.
|
||
|
*/
|
||
|
class HTMLPurifier_Arborize
|
||
|
{
|
||
|
public static function arborize($tokens, $config, $context) {
|
||
|
$definition = $config->getHTMLDefinition();
|
||
|
$parent = new HTMLPurifier_Token_Start($definition->info_parent);
|
||
|
$stack = array($parent->toNode());
|
||
|
foreach ($tokens as $token) {
|
||
|
$token->skip = null; // [MUT]
|
||
|
$token->carryover = null; // [MUT]
|
||
|
if ($token instanceof HTMLPurifier_Token_End) {
|
||
|
$token->start = null; // [MUT]
|
||
|
$r = array_pop($stack);
|
||
|
assert($r->name === $token->name);
|
||
|
assert(empty($token->attr));
|
||
|
$r->endCol = $token->col;
|
||
|
$r->endLine = $token->line;
|
||
|
$r->endArmor = $token->armor;
|
||
|
continue;
|
||
|
}
|
||
|
$node = $token->toNode();
|
||
|
$stack[count($stack)-1]->children[] = $node;
|
||
|
if ($token instanceof HTMLPurifier_Token_Start) {
|
||
|
$stack[] = $node;
|
||
|
}
|
||
|
}
|
||
|
assert(count($stack) == 1);
|
||
|
return $stack[0];
|
||
|
}
|
||
|
|
||
|
public static function flatten($node, $config, $context) {
|
||
|
$level = 0;
|
||
|
$nodes = array($level => new HTMLPurifier_Queue(array($node)));
|
||
|
$closingTokens = array();
|
||
|
$tokens = array();
|
||
|
do {
|
||
|
while (!$nodes[$level]->isEmpty()) {
|
||
|
$node = $nodes[$level]->shift(); // FIFO
|
||
|
list($start, $end) = $node->toTokenPair();
|
||
|
if ($level > 0) {
|
||
|
$tokens[] = $start;
|
||
|
}
|
||
|
if ($end !== NULL) {
|
||
|
$closingTokens[$level][] = $end;
|
||
|
}
|
||
|
if ($node instanceof HTMLPurifier_Node_Element) {
|
||
|
$level++;
|
||
|
$nodes[$level] = new HTMLPurifier_Queue();
|
||
|
foreach ($node->children as $childNode) {
|
||
|
$nodes[$level]->push($childNode);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
$level--;
|
||
|
if ($level && isset($closingTokens[$level])) {
|
||
|
while ($token = array_pop($closingTokens[$level])) {
|
||
|
$tokens[] = $token;
|
||
|
}
|
||
|
}
|
||
|
} while ($level > 0);
|
||
|
return $tokens;
|
||
|
}
|
||
|
}
|