129 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace dokuwiki\Parsing;
 | 
						|
 | 
						|
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 = array();
 | 
						|
 | 
						|
    /** @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 */
 | 
						|
 | 
						|
            \dokuwiki\Debug\DebugHelper::dbgCustomDeprecationEvent(
 | 
						|
                'finalize()',
 | 
						|
                get_class($this->handler) . '::_finalize()',
 | 
						|
                __METHOD__,
 | 
						|
                __FILE__,
 | 
						|
                __LINE__
 | 
						|
            );
 | 
						|
            $this->handler->_finalize();
 | 
						|
        } else {
 | 
						|
            $this->handler->finalize();
 | 
						|
        }
 | 
						|
        return $this->handler->calls;
 | 
						|
    }
 | 
						|
 | 
						|
}
 |