aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/inc/parser/parser.php
blob: feafc8f62d38041c78b70dcd90b165a9f835c030 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php

use dokuwiki\ParserMode\Base;
use dokuwiki\ParserMode\ModeInterface;

/**
 * Define various types of modes used by the parser - they are used to
 * populate the list of modes another mode accepts
 */
global $PARSER_MODES;
$PARSER_MODES = array(
    // containers are complex modes that can contain many other modes
    // hr breaks the principle but they shouldn't be used in tables / lists
    // so they are put here
    'container'    => array('listblock','table','quote','hr'),

    // some mode are allowed inside the base mode only
    'baseonly'     => array('header'),

    // modes for styling text -- footnote behaves similar to styling
    'formatting'   => array('strong', 'emphasis', 'underline', 'monospace',
                            'subscript', 'superscript', 'deleted', 'footnote'),

    // modes where the token is simply replaced - they can not contain any
    // other modes
    'substition'   => array('acronym','smiley','wordblock','entity',
                            'camelcaselink', 'internallink','media',
                            'externallink','linebreak','emaillink',
                            'windowssharelink','filelink','notoc',
                            'nocache','multiplyentity','quotes','rss'),

    // modes which have a start and end token but inside which
    // no other modes should be applied
    'protected'    => array('preformatted','code','file','php','html','htmlblock','phpblock'),

    // inside this mode no wiki markup should be applied but lineendings
    // and whitespace isn't preserved
    'disabled'     => array('unformatted'),

    // used to mark paragraph boundaries
    'paragraphs'   => array('eol')
);

//-------------------------------------------------------------------

/**
 * Sets up the Lexer with modes and points it to the Handler
 * For an intro to the Lexer see: wiki:parser
 */
class Doku_Parser {

    var $Handler;

    /**
     * @var Doku_Lexer $Lexer
     */
    var $Lexer;

    var $modes = array();

    var $connected = false;

    /**
     * @param Base $BaseMode
     */
    function addBaseMode($BaseMode) {
        $this->modes['base'] = $BaseMode;
        if ( !$this->Lexer ) {
            $this->Lexer = new Doku_Lexer($this->Handler,'base', true);
        }
        $this->modes['base']->Lexer = $this->Lexer;
    }

    /**
     * PHP preserves order of associative elements
     * Mode sequence is important
     *
     * @param string $name
     * @param ModeInterface $Mode
     */
    function addMode($name, ModeInterface $Mode) {
        if ( !isset($this->modes['base']) ) {
            $this->addBaseMode(new Base());
        }
        $Mode->Lexer = $this->Lexer;
        $this->modes[$name] = $Mode;
    }

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

    function parse($doc) {
        if ( $this->Lexer ) {
            $this->connectModes();
            // Normalize CRs and pad doc
            $doc = "\n".str_replace("\r\n","\n",$doc)."\n";
            $this->Lexer->parse($doc);
            $this->Handler->_finalize();
            return $this->Handler->calls;
        } else {
            return false;
        }
    }

}


//Setup VIM: ex: et ts=4 :