Passed
Push — master ( 4c697a...778310 )
by Kacper
02:53
created

Token::dump()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 6
Bugs 1 Features 0
Metric Value
c 6
b 1
f 0
dl 0
loc 16
rs 9.2
ccs 0
cts 0
cp 0
cc 4
eloc 10
nc 3
nop 1
crap 20
1
<?php
2
/**
3
 * Highlighter
4
 *
5
 * Copyright (C) 2015, Some right reserved.
6
 *
7
 * @author Kacper "Kadet" Donat <[email protected]>
8
 *
9
 * Contact with author:
10
 * Xmpp: [email protected]
11
 * E-mail: [email protected]
12
 *
13
 * From Kadet with love.
14
 */
15
16
namespace Kadet\Highlighter\Parser;
17
18
19
use Kadet\Highlighter\Language\Language;
20
use Kadet\Highlighter\Utils\Helper;
21
use Kadet\Highlighter\Utils\StringHelper;
22
23
class Token
24
{
25
    const NAME = null;
26
27
    protected static $_id = 0;
28
29
    public $pos;
30
    public $name;
31
    public $index = 1;
32
33
    /**
34
     * @var Token
35
     */
36
    protected $_end;
37
38
    /**
39
     * @var Token
40
     */
41
    protected $_start;
42
43
    /** @var Rule */
44
    protected $_rule;
45
46
    protected $_valid;
47
    protected $_length;
48
49
    public $id;
50
51
    /**
52
     * Token constructor.
53
     */
54 13
    public function __construct(array $options)
55
    {
56
        // Name
57 13
        if (isset($options[0])) {
58 11
            $this->name = $options[0];
59 11
        }
60
61 13
        if (isset($options['pos'])) {
62 10
            $this->pos = $options['pos'];
63 10
        }
64
65 13
        if (isset($options['index'])) {
66 1
            $this->index = $options['index'];
67 1
        }
68
69 13
        if (isset($options['start'])) {
70 5
            $this->setStart($options['start']);
71 5
        }
72
73 13
        if (isset($options['rule'])) {
74 6
            $this->setRule($options['rule']);
75 6
        }
76
77 13
        if (isset($options['end'])) {
78 2
            $this->setEnd($options['end']);
79 2
        }
80
81 13
        $this->id = ++self::$_id;
82
83 13
        if (isset($options['length'])) {
84 4
            new static([$this->name, 'pos' => $this->pos + $options['length'], 'start' => $this, 'rule' => $this->getRule()]);
85 4
        }
86 13
    }
87
88
    public static function compare(Token $a, Token $b)
89
    {
90
        if ($a->pos === $b->pos) {
91
            $multiplier = $a->isEnd() ? -1 : 1;
92
93
            if (($a->isStart() && $b->isEnd()) || ($a->isEnd() && $b->isStart())) {
94
                return $multiplier;
95
            } elseif (($rule = Helper::cmp($b->_rule->priority, $a->_rule->priority)) !== 0) {
96
                return $multiplier*$rule;
97
            } elseif (($rule = Helper::cmp($b->index, $a->index)) !== 0) {
98
                return $multiplier*$rule;
99
            } else {
100
                return $multiplier*($a->id < $b->id ? -1 : 1);
101
            }
102
        }
103
104
        return ($a->pos > $b->pos) ? 1 : -1;
105
    }
106
107 2
    public function isStart()
108
    {
109 2
        return $this->_start === null && !($this->_rule instanceof CloseRule);
110
    }
111
112 3
    public function isEnd()
113
    {
114 3
        return $this->_end === null && !($this->_rule instanceof OpenRule);
115
    }
116
117
    public function isValid(Language $language, $context = null)
118
    {
119
        if ($this->_valid === null) {
120
            $this->validate($language, $context);
121
        }
122
123
        return $this->_valid;
124
    }
125
126
    protected function validate(Language $language, $context)
127
    {
128
        $this->setValid(
129
            $language === $this->_rule->language &&
130
            $this->_rule->validateContext($context, $this->isEnd() ? [$this->name => Rule::CONTEXT_IN] : [])
131
        );
132
    }
133
134
    public function setValid($valid = true)
135
    {
136
        $this->_valid = $valid;
137
138
        if ($this->_end !== null) {
139
            $this->_end->_valid = $this->_valid;
140
        } elseif ($this->_start !== null) {
141
            $this->_start->_valid = $this->_valid;
142
        }
143
    }
144
145
    /**
146
     * @return mixed
147
     */
148 2
    public function getStart()
149
    {
150 2
        return $this->_start;
151
    }
152
153
    /**
154
     * @param Token $start
155
     */
156 5 View Code Duplication
    public function setStart(Token $start = null)
157
    {
158 5
        $this->_end = null;
159 5
        $this->_start = $start;
160
161 5
        if ($start !== null) {
162 5
            $this->_start->_end = $this;
163 5
        }
164 5
    }
165
166
    /**
167
     * @return Token|null
168
     */
169 3
    public function getEnd()
170
    {
171 3
        return $this->_end;
172
    }
173
174
    /**
175
     * @param Token $end
176
     */
177 3 View Code Duplication
    public function setEnd(Token $end = null)
178
    {
179 3
        $this->_start = null;
180 3
        $this->_end = $end;
181 3
        $this->_length = null;
182
183 3
        if ($end !== null) {
184 2
            $this->_end->_start = $this;
185 2
        }
186 3
    }
187
188
    /**
189
     * @return Rule
190
     */
191 6
    public function getRule()
192
    {
193 6
        return $this->_rule;
194
    }
195
196
    /**
197
     * @param Rule $rule
198
     */
199 6
    public function setRule(Rule $rule)
200
    {
201 6
        $this->_rule = $rule;
202 6
    }
203
204 1
    public function getLength()
205
    {
206 1
        if ($this->_length === null) {
207 1
            $this->_length = $this->_end === null ? 0 : $this->_end->pos - $this->pos;
208 1
        }
209
210 1
        return $this->_length;
211
    }
212
213
    /**
214
     * @codeCoverageIgnore
215
     */
216
    public function dump($text = null)
217
    {
218
        $pos = StringHelper::positionToLine($text, $this->pos);
219
        $pos = $pos['line'] . ':' . $pos['pos'];
220
221
        if ($this->isStart()) {
222
            $result = "Start ({$this->name}) $pos";
223
            if ($text !== null && $this->_end !== null) {
224
                $result .= "  \x02" . substr($text, $this->pos, $this->_end->pos - $this->pos) . "\x03";
225
            }
226
        } else {
227
            $result = "End ({$this->name}) $pos";
228
        }
229
230
        return $result;
231
    }
232
}