1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
<?php
namespace dokuwiki\Parsing;
use dokuwiki\Debug\DebugHelper;
use Doku_Handler;
use dokuwiki\Parsing\Lexer\Lexer;
use dokuwiki\Parsing\ParserMode\Base;
use dokuwiki\Parsing\ParserMode\ModeInterface;
/**
* Sets up the Lexer with modes and points it to the Handler
* For an intro to the Lexer see: wiki:parser
*/
class Parser
{
/** @var Doku_Handler */
protected $handler;
/** @var Lexer $lexer */
protected $lexer;
/** @var ModeInterface[] $modes */
protected $modes = [];
/** @var bool mode connections may only be set up once */
protected $connected = false;
/**
* dokuwiki\Parsing\Doku_Parser constructor.
*
* @param Doku_Handler $handler
*/
public function __construct(Doku_Handler $handler)
{
$this->handler = $handler;
}
/**
* Adds the base mode and initialized the lexer
*
* @param Base $BaseMode
*/
protected function addBaseMode($BaseMode)
{
$this->modes['base'] = $BaseMode;
if (!$this->lexer) {
$this->lexer = new Lexer($this->handler, 'base', true);
}
$this->modes['base']->Lexer = $this->lexer;
}
/**
* Add a new syntax element (mode) to the parser
*
* PHP preserves order of associative elements
* Mode sequence is important
*
* @param string $name
* @param ModeInterface $Mode
*/
public function addMode($name, ModeInterface $Mode)
{
if (!isset($this->modes['base'])) {
$this->addBaseMode(new Base());
}
$Mode->Lexer = $this->lexer; // FIXME should be done by setter
$this->modes[$name] = $Mode;
}
/**
* Connect all modes with each other
*
* This is the last step before actually parsing.
*/
protected function connectModes()
{
if ($this->connected) {
return;
}
foreach (array_keys($this->modes) as $mode) {
// Base isn't connected to anything
if ($mode == 'base') {
continue;
}
$this->modes[$mode]->preConnect();
foreach (array_keys($this->modes) as $cm) {
if ($this->modes[$cm]->accepts($mode)) {
$this->modes[$mode]->connectTo($cm);
}
}
$this->modes[$mode]->postConnect();
}
$this->connected = true;
}
/**
* Parses wiki syntax to instructions
*
* @param string $doc the wiki syntax text
* @return array instructions
*/
public function parse($doc)
{
$this->connectModes();
// Normalize CRs and pad doc
$doc = "\n" . str_replace("\r\n", "\n", $doc) . "\n";
$this->lexer->parse($doc);
if (!method_exists($this->handler, 'finalize')) {
/** @deprecated 2019-10 we have a legacy handler from a plugin, assume legacy _finalize exists */
DebugHelper::dbgCustomDeprecationEvent(
'finalize()',
get_class($this->handler) . '::_finalize()',
__METHOD__,
__FILE__,
__LINE__
);
$this->handler->_finalize();
} else {
$this->handler->finalize();
}
return $this->handler->calls;
}
}
|