xref: /dokuwiki/inc/parser/parser.php (revision 36dc94bb8b05aaaff6fdcf55dd6af80ca30d22b1)
10cecf9d5Sandi<?php
2*36dc94bbSAndreas Gohr
3*36dc94bbSAndreas Gohruse dokuwiki\ParserMode\Base;
4*36dc94bbSAndreas Gohruse dokuwiki\ParserMode\ModeInterface;
5*36dc94bbSAndreas Gohr
6ee20e7d1Sandi/**
7ee20e7d1Sandi * Define various types of modes used by the parser - they are used to
8ee20e7d1Sandi * populate the list of modes another mode accepts
9ee20e7d1Sandi */
10ee20e7d1Sandiglobal $PARSER_MODES;
11ee20e7d1Sandi$PARSER_MODES = array(
12ee20e7d1Sandi    // containers are complex modes that can contain many other modes
13ee20e7d1Sandi    // hr breaks the principle but they shouldn't be used in tables / lists
14ee20e7d1Sandi    // so they are put here
15ee20e7d1Sandi    'container'    => array('listblock','table','quote','hr'),
16ee20e7d1Sandi
17ee20e7d1Sandi    // some mode are allowed inside the base mode only
18ee20e7d1Sandi    'baseonly'     => array('header'),
19ee20e7d1Sandi
20ee20e7d1Sandi    // modes for styling text -- footnote behaves similar to styling
21ee20e7d1Sandi    'formatting'   => array('strong', 'emphasis', 'underline', 'monospace',
22ee20e7d1Sandi                            'subscript', 'superscript', 'deleted', 'footnote'),
23ee20e7d1Sandi
24ee20e7d1Sandi    // modes where the token is simply replaced - they can not contain any
25ee20e7d1Sandi    // other modes
26ee20e7d1Sandi    'substition'   => array('acronym','smiley','wordblock','entity',
27ee20e7d1Sandi                            'camelcaselink', 'internallink','media',
28ee20e7d1Sandi                            'externallink','linebreak','emaillink',
29ee20e7d1Sandi                            'windowssharelink','filelink','notoc',
30ee20e7d1Sandi                            'nocache','multiplyentity','quotes','rss'),
31ee20e7d1Sandi
32ee20e7d1Sandi    // modes which have a start and end token but inside which
33ee20e7d1Sandi    // no other modes should be applied
3407f89c3cSAnika Henke    'protected'    => array('preformatted','code','file','php','html','htmlblock','phpblock'),
35ee20e7d1Sandi
36ee20e7d1Sandi    // inside this mode no wiki markup should be applied but lineendings
37ee20e7d1Sandi    // and whitespace isn't preserved
38ee20e7d1Sandi    'disabled'     => array('unformatted'),
39ee20e7d1Sandi
40ee20e7d1Sandi    // used to mark paragraph boundaries
41ee20e7d1Sandi    'paragraphs'   => array('eol')
42ee20e7d1Sandi);
43ee20e7d1Sandi
440cecf9d5Sandi//-------------------------------------------------------------------
450cecf9d5Sandi
460cecf9d5Sandi/**
470cecf9d5Sandi * Sets up the Lexer with modes and points it to the Handler
480cecf9d5Sandi * For an intro to the Lexer see: wiki:parser
490cecf9d5Sandi */
500cecf9d5Sandiclass Doku_Parser {
510cecf9d5Sandi
520cecf9d5Sandi    var $Handler;
530cecf9d5Sandi
54e3ab6fc5SMichael Hamann    /**
55e3ab6fc5SMichael Hamann     * @var Doku_Lexer $Lexer
56e3ab6fc5SMichael Hamann     */
570cecf9d5Sandi    var $Lexer;
580cecf9d5Sandi
590cecf9d5Sandi    var $modes = array();
600cecf9d5Sandi
6144881bd0Shenning.noren    var $connected = false;
620cecf9d5Sandi
63276820f7SScrutinizer Auto-Fixer    /**
64*36dc94bbSAndreas Gohr     * @param Base $BaseMode
65276820f7SScrutinizer Auto-Fixer     */
6645e8987eSChristopher Smith    function addBaseMode($BaseMode) {
6745e8987eSChristopher Smith        $this->modes['base'] = $BaseMode;
680cecf9d5Sandi        if ( !$this->Lexer ) {
6967f9913dSAndreas Gohr            $this->Lexer = new Doku_Lexer($this->Handler,'base', true);
700cecf9d5Sandi        }
7145e8987eSChristopher Smith        $this->modes['base']->Lexer = $this->Lexer;
720cecf9d5Sandi    }
730cecf9d5Sandi
740cecf9d5Sandi    /**
750cecf9d5Sandi     * PHP preserves order of associative elements
760cecf9d5Sandi     * Mode sequence is important
77f50a239bSTakamura     *
78f50a239bSTakamura     * @param string $name
79*36dc94bbSAndreas Gohr     * @param ModeInterface $Mode
800cecf9d5Sandi     */
81*36dc94bbSAndreas Gohr    function addMode($name, ModeInterface $Mode) {
820cecf9d5Sandi        if ( !isset($this->modes['base']) ) {
83*36dc94bbSAndreas Gohr            $this->addBaseMode(new Base());
840cecf9d5Sandi        }
8545e8987eSChristopher Smith        $Mode->Lexer = $this->Lexer;
8645e8987eSChristopher Smith        $this->modes[$name] = $Mode;
870cecf9d5Sandi    }
880cecf9d5Sandi
890cecf9d5Sandi    function connectModes() {
900cecf9d5Sandi
910cecf9d5Sandi        if ( $this->connected ) {
920cecf9d5Sandi            return;
930cecf9d5Sandi        }
940cecf9d5Sandi
950cecf9d5Sandi        foreach ( array_keys($this->modes) as $mode ) {
960cecf9d5Sandi
970cecf9d5Sandi            // Base isn't connected to anything
980cecf9d5Sandi            if ( $mode == 'base' ) {
990cecf9d5Sandi                continue;
1000cecf9d5Sandi            }
1010cecf9d5Sandi            $this->modes[$mode]->preConnect();
1020cecf9d5Sandi
1030cecf9d5Sandi            foreach ( array_keys($this->modes) as $cm ) {
1040cecf9d5Sandi
1050cecf9d5Sandi                if ( $this->modes[$cm]->accepts($mode) ) {
1060cecf9d5Sandi                    $this->modes[$mode]->connectTo($cm);
1070cecf9d5Sandi                }
1080cecf9d5Sandi
1090cecf9d5Sandi            }
1100cecf9d5Sandi
1110cecf9d5Sandi            $this->modes[$mode]->postConnect();
1120cecf9d5Sandi        }
1130cecf9d5Sandi
11444881bd0Shenning.noren        $this->connected = true;
1150cecf9d5Sandi    }
1160cecf9d5Sandi
1170cecf9d5Sandi    function parse($doc) {
1180cecf9d5Sandi        if ( $this->Lexer ) {
1190cecf9d5Sandi            $this->connectModes();
1200cecf9d5Sandi            // Normalize CRs and pad doc
1210cecf9d5Sandi            $doc = "\n".str_replace("\r\n","\n",$doc)."\n";
1220cecf9d5Sandi            $this->Lexer->parse($doc);
123433bef32Sandi            $this->Handler->_finalize();
1240cecf9d5Sandi            return $this->Handler->calls;
1250cecf9d5Sandi        } else {
12644881bd0Shenning.noren            return false;
1270cecf9d5Sandi        }
1280cecf9d5Sandi    }
1290cecf9d5Sandi
1300cecf9d5Sandi}
1310cecf9d5Sandi
132340756e4Sandi
133e3776c06SMichael Hamann//Setup VIM: ex: et ts=4 :
134