[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/Parsing/ -> Parser.php (source)

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