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;
 | |
|     }
 | |
| 
 | |
| }
 |