Mirin webspace

Nejbohatší život má ten, kdo žije s minimem nároků

25. 1. 2008 PHP

Napiš si své texy - část 2

Než se vrhnu na pokračování popisu tvorby vlastního značkovacího jazyka, nejdřív omluva všem, kteří čtou blog přes RSS čtečky. Včera jsem změnil v nadpisech několika článků počáteční písmena na velká a ejhle, v RSS čtečce (používám Operu) se objevily tyto články a jejich komentáře znovu, i když už jsem je již dříve ve čtečce označil za přečtené. Čtečka evidentně sleduje změny a pokud se objeví změna v obsahu, který už byl označen jako přečtený, tak ho označí za nový. Tak a teď už zpět k Handleru.

Handler

Handler je třída, která se stará o převod tokenů od Lexeru na instrukce, které pak ukládá sekvenčně do pole. To si pak přečte Renderer a podle nich vykreslí výsledný dokument. Handler implementuje metody, jejichž název odpovídá módům, které Lexer prostřednictvím Parseru registruje.

$Parser->addMode('preformatted',new WikiText_Parser_Mode_Preformatted());

Handler pak implementuje metodu preformatted.

class WikiText_Handler
{
 
/**
 * @param string match contains the text that was matched
 * @param int state - the type of match made
 * @param int pos - byte index where match was made
 */
public function preformatted($match, $state, $pos)
{
 //build instruction and save it into array of calls
 return true;
}
 
#END CLASS
}

Do parametrů se předává text tokenu, stav lexeru a pozice tokenu ve vstupním textu. Stav lexeru jsou konstaty, které určují, jakým způsobem se porovnal token s reg. výrazem pro daný mód.

  1. WikiText_Lexer::ENTER token odpovídá reg. výrazu pro vstup do módu, registrovanému přes addEntryPattern()
  2. WikiText_Lexer::MATCHED token uvnitř módu, token odpovídá výrazu registrovanému přes addPattern()
  3. WikiText_Lexer::UNMATCHED token uvnitř módu, token neodpovídá žádnému reg. výrazu registrovanému přes addPattern()
  4. WikiText_Lexer::EXIT ukončovací token módu, odpovídá reg. výrazu registrovanému přes addExitPattern()
  5. WikiText_Lexer::SPECIAL speciální token (např. pro smajlíky), odpovídá reg. výrazu registrovanému přes addSpecialPattern()

Handlery pro složitější módy

K handleru patří ještě další třídy, je to CallWriter, který se stará o zápis instrukcí do pole a handlery pro složitější módy jako třeba List Handler pro seznamy, Table Handler pro tabulky atd. Tyto mají podobné chování, které využívá právě CallWriteru. Jako příklad si ukážeme třeba použití List Handleru. Hlavní WikiText_Handler má pro obsluhu tokenů list módu následující metodu

class WikiText_Handler {
 
//...
 
//===============================================================
/** listblock handler
 * @return boolean
 */
public function listblock($match, $state, $pos)
{
 switch ( $state ) {
  case WikiText_Lexer::ENTER:
   //makes new nested level of list
   $ReWriter = new WikiText_Handler_List($this->_callWriter);
   $this->_callWriter = $ReWriter;
   $this->_addCall('list_open', array($match), $pos);
   break;
  case WikiText_Lexer::LEXIT:
   $this->_addCall('list_close', array(), $pos);
   $this->_callWriter->process();
   //end of the current levet, repair old callWriter
   $ReWriter = $this->_callWriter;
   $this->_callWriter = $ReWriter->callWriter;
   break;
  case WikiText_Lexer::MATCHED:
   $this->_addCall('list_item', array($match), $pos);
   break;
  case WikiText_Lexer::UNMATCHED:
   $this->_addCall('cdata', array($match), $pos);
  break;
 }
 return true;
}
 
//...
 
#END CLASS
}

Na začátku listu se uloží aktuální CallWriter do instance nové třídy WikiText_Handler_List, která sama o sobě funguje jako CallWriter. Instrukce pro obsah listu jsou pak zapisovány do pole v instanci WikiText_Handler_List. Až se dojde ke konci listu, obsah do té doby zpracovávaného listu se přesype metodou process() do uložené instance a ta se následně vrátí zpět do hlavní třídy WikiText_Handler jako CallWriter.

Originální dokuwiki implementace Handleru není téměř vůbec ve stylu PHP5, zatím jsem moc nepřišel na to, jak to zlepšit. No uvidíme, navíc obsahuje dost hacků a věcí označených jako "need to be rewritten" apod.

Tak na příště už zbývá jen Renderer a je hotovo. Rozchodil jsem si subversion, takže si klidně kód můžete prohlédnout buď přes bohatý webSVN interface, nebo přímo přes webdav svn modul, tam můžete i checkoutovat.


Komentáře (0)

Komentáře jsou uzavřeny.