xref: /dokuwiki/_test/tests/inc/parser/lexer.test.php (revision 661d78e851c0ed5f6d0d6a0022010c9e95f30f85)
1<?php
2/**
3* @version $Id: lexer.todo.php,v 1.2 2005/03/25 21:00:22 harryf Exp $
4* @package Doku
5* @subpackage Tests
6*/
7
8use dokuwiki\Parsing\Lexer\Lexer;
9use dokuwiki\Parsing\Lexer\ParallelRegex;
10use dokuwiki\Parsing\Lexer\StateStack;
11
12/**
13* @package Doku
14* @subpackage Tests
15*/
16class TestOfLexerParallelRegex extends DokuWikiTest {
17
18    function testNoPatterns() {
19        $regex = new ParallelRegex(false);
20        $this->assertFalse($regex->match("Hello", $match));
21        $this->assertEquals($match, "");
22    }
23    function testNoSubject() {
24        $regex = new ParallelRegex(false);
25        $regex->addPattern(".*");
26        $this->assertTrue($regex->match("", $match));
27        $this->assertEquals($match, "");
28    }
29    function testMatchAll() {
30        $regex = new ParallelRegex(false);
31        $regex->addPattern(".*");
32        $this->assertTrue($regex->match("Hello", $match));
33        $this->assertEquals($match, "Hello");
34    }
35    function testCaseSensitive() {
36        $regex = new ParallelRegex(true);
37        $regex->addPattern("abc");
38        $this->assertTrue($regex->match("abcdef", $match));
39        $this->assertEquals($match, "abc");
40        $this->assertTrue($regex->match("AAABCabcdef", $match));
41        $this->assertEquals($match, "abc");
42    }
43    function testCaseInsensitive() {
44        $regex = new ParallelRegex(false);
45        $regex->addPattern("abc");
46        $this->assertTrue($regex->match("abcdef", $match));
47        $this->assertEquals($match, "abc");
48        $this->assertTrue($regex->match("AAABCabcdef", $match));
49        $this->assertEquals($match, "ABC");
50    }
51    function testMatchMultiple() {
52        $regex = new ParallelRegex(true);
53        $regex->addPattern("abc");
54        $regex->addPattern("ABC");
55        $this->assertTrue($regex->match("abcdef", $match));
56        $this->assertEquals($match, "abc");
57        $this->assertTrue($regex->match("AAABCabcdef", $match));
58        $this->assertEquals($match, "ABC");
59        $this->assertFalse($regex->match("Hello", $match));
60    }
61    function testPatternLabels() {
62        $regex = new ParallelRegex(false);
63        $regex->addPattern("abc", "letter");
64        $regex->addPattern("123", "number");
65        $this->assertEquals($regex->match("abcdef", $match), "letter");
66        $this->assertEquals($match, "abc");
67        $this->assertEquals($regex->match("0123456789", $match), "number");
68        $this->assertEquals($match, "123");
69    }
70    function testMatchMultipleWithLookaheadNot() {
71        $regex = new ParallelRegex(true);
72        $regex->addPattern("abc");
73        $regex->addPattern("ABC");
74        $regex->addPattern("a(?!\n).{1}");
75        $this->assertTrue($regex->match("abcdef", $match));
76        $this->assertEquals($match, "abc");
77        $this->assertTrue($regex->match("AAABCabcdef", $match));
78        $this->assertEquals($match, "ABC");
79        $this->assertTrue($regex->match("a\nab", $match));
80        $this->assertEquals($match, "ab");
81        $this->assertFalse($regex->match("Hello", $match));
82    }
83    function testMatchSetOptionCaseless() {
84        $regex = new ParallelRegex(true);
85        $regex->addPattern("a(?i)b(?i)c");
86        $this->assertTrue($regex->match("aBc", $match));
87        $this->assertEquals($match, "aBc");
88    }
89    function testMatchSetOptionUngreedy() {
90        $regex = new ParallelRegex(true);
91        $regex->addPattern("(?U)\w+");
92        $this->assertTrue($regex->match("aaaaaa", $match));
93        $this->assertEquals($match, "a");
94    }
95    function testMatchLookaheadEqual() {
96        $regex = new ParallelRegex(true);
97        $regex->addPattern("\w(?=c)");
98        $this->assertTrue($regex->match("xbyczd", $match));
99        $this->assertEquals($match, "y");
100    }
101    function testMatchLookaheadNot() {
102        $regex = new ParallelRegex(true);
103        $regex->addPattern("\w(?!b|c)");
104        $this->assertTrue($regex->match("xbyczd", $match));
105        $this->assertEquals($match, "b");
106    }
107    function testMatchLookbehindEqual() {
108        $regex = new ParallelRegex(true);
109        $regex->addPattern("(?<=c)\w");
110        $this->assertTrue($regex->match("xbyczd", $match));
111        $this->assertEquals($match, "z");
112    }
113    function testMatchLookbehindNot() {
114        $regex = new ParallelRegex(true);
115        $regex->addPattern("(?<!\A|x|b)\w");
116        $this->assertTrue($regex->match("xbyczd", $match));
117        $this->assertEquals($match, "c");
118    }
119}
120
121
122class TestOfLexerStateStack extends DokuWikiTest {
123    function testStartState() {
124        $stack = new StateStack("one");
125        $this->assertEquals($stack->getCurrent(), "one");
126    }
127    function testExhaustion() {
128        $stack = new StateStack("one");
129        $this->assertFalse($stack->leave());
130    }
131    function testStateMoves() {
132        $stack = new StateStack("one");
133        $stack->enter("two");
134        $this->assertEquals($stack->getCurrent(), "two");
135        $stack->enter("three");
136        $this->assertEquals($stack->getCurrent(), "three");
137        $this->assertTrue($stack->leave());
138        $this->assertEquals($stack->getCurrent(), "two");
139        $stack->enter("third");
140        $this->assertEquals($stack->getCurrent(), "third");
141        $this->assertTrue($stack->leave());
142        $this->assertTrue($stack->leave());
143        $this->assertEquals($stack->getCurrent(), "one");
144    }
145}
146
147class TestParser {
148    function __construct() {
149    }
150    function accept() {
151    }
152    function a() {
153    }
154    function b() {
155    }
156}
157
158class TestOfLexer extends DokuWikiTest {
159    function testNoPatterns() {
160        $handler = $this->createMock('TestParser');
161        $handler->expects($this->never())->method('accept');
162        $lexer = new Lexer($handler);
163        $this->assertFalse($lexer->parse("abcdef"));
164    }
165    function testEmptyPage() {
166        $handler = $this->createMock('TestParser');
167        $handler->expects($this->never())->method('accept');
168        $lexer = new Lexer($handler);
169        $lexer->addPattern("a+");
170        $this->assertTrue($lexer->parse(""));
171    }
172    function testSinglePattern() {
173        $handler = $this->createMock('TestParser');
174        $handler->expects($this->at(0))->method('accept')
175            ->with("aaa", DOKU_LEXER_MATCHED, 0)->will($this->returnValue(true));
176        $handler->expects($this->at(1))->method('accept')
177            ->with("x", DOKU_LEXER_UNMATCHED, 3)->will($this->returnValue(true));
178        $handler->expects($this->at(2))->method('accept')
179            ->with("a", DOKU_LEXER_MATCHED, 4)->will($this->returnValue(true));
180        $handler->expects($this->at(3))->method('accept')
181            ->with("yyy", DOKU_LEXER_UNMATCHED, 5)->will($this->returnValue(true));
182        $handler->expects($this->at(4))->method('accept')
183            ->with("a", DOKU_LEXER_MATCHED, 8)->will($this->returnValue(true));
184        $handler->expects($this->at(5))->method('accept')
185            ->with("x", DOKU_LEXER_UNMATCHED, 9)->will($this->returnValue(true));
186        $handler->expects($this->at(6))->method('accept')
187            ->with("aaa", DOKU_LEXER_MATCHED, 10)->will($this->returnValue(true));
188        $handler->expects($this->at(7))->method('accept')
189            ->with("z", DOKU_LEXER_UNMATCHED, 13)->will($this->returnValue(true));
190
191        $lexer = new Lexer($handler);
192        $lexer->addPattern("a+");
193        $this->assertTrue($lexer->parse("aaaxayyyaxaaaz"));
194    }
195    function testMultiplePattern() {
196        $handler = $this->createPartialMock('TestParser', array('accept'));
197        $target = array("a", "b", "a", "bb", "x", "b", "a", "xxxxxx", "a", "x");
198        $positions = array(0, 1, 2, 3, 5, 6, 7, 8, 14, 15);
199        for ($i = 0; $i < count($target); $i++) {
200            $handler->expects($this->at($i))->method('accept')
201                ->with($target[$i], $this->anything(), $positions[$i])->will($this->returnValue(true));
202        }
203        $lexer = new Lexer($handler);
204        $lexer->addPattern("a+");
205        $lexer->addPattern("b+");
206        $this->assertTrue($lexer->parse("ababbxbaxxxxxxax"));
207    }
208}
209
210class TestOfLexerModes extends DokuWikiTest {
211    function testIsolatedPattern() {
212        $handler = $this->createMock('TestParser');
213        $handler->expects($this->at(0))->method('a')
214            ->with("a", DOKU_LEXER_MATCHED,0)->will($this->returnValue(true));
215        $handler->expects($this->at(1))->method('a')
216            ->with("b", DOKU_LEXER_UNMATCHED,1)->will($this->returnValue(true));
217        $handler->expects($this->at(2))->method('a')
218            ->with("aa", DOKU_LEXER_MATCHED,2)->will($this->returnValue(true));
219        $handler->expects($this->at(3))->method('a')
220            ->with("bxb", DOKU_LEXER_UNMATCHED,4)->will($this->returnValue(true));
221        $handler->expects($this->at(4))->method('a')
222            ->with("aaa", DOKU_LEXER_MATCHED,7)->will($this->returnValue(true));
223        $handler->expects($this->at(5))->method('a')
224            ->with("x", DOKU_LEXER_UNMATCHED,10)->will($this->returnValue(true));
225        $handler->expects($this->at(6))->method('a')
226            ->with("aaaa", DOKU_LEXER_MATCHED,11)->will($this->returnValue(true));
227        $handler->expects($this->at(7))->method('a')
228            ->with("x", DOKU_LEXER_UNMATCHED,15)->will($this->returnValue(true));
229        $lexer = new Lexer($handler, "a");
230        $lexer->addPattern("a+", "a");
231        $lexer->addPattern("b+", "b");
232        $this->assertTrue($lexer->parse("abaabxbaaaxaaaax"));
233    }
234    function testModeChange() {
235        $handler = $this->createMock('TestParser');
236        $handler->expects($this->at(0))->method('a')
237            ->with("a", DOKU_LEXER_MATCHED,0)->will($this->returnValue(true));
238        $handler->expects($this->at(1))->method('a')
239            ->with("b", DOKU_LEXER_UNMATCHED,1)->will($this->returnValue(true));
240        $handler->expects($this->at(2))->method('a')
241            ->with("aa", DOKU_LEXER_MATCHED,2)->will($this->returnValue(true));
242        $handler->expects($this->at(3))->method('a')
243            ->with("b", DOKU_LEXER_UNMATCHED,4)->will($this->returnValue(true));
244        $handler->expects($this->at(4))->method('a')
245            ->with("aaa", DOKU_LEXER_MATCHED,5)->will($this->returnValue(true));
246        $handler->expects($this->at(5))->method('b')
247            ->with(":", DOKU_LEXER_ENTER,8)->will($this->returnValue(true));
248        $handler->expects($this->at(6))->method('b')
249            ->with("a", DOKU_LEXER_UNMATCHED,9)->will($this->returnValue(true));
250        $handler->expects($this->at(7))->method('b')
251            ->with("b", DOKU_LEXER_MATCHED, 10)->will($this->returnValue(true));
252        $handler->expects($this->at(8))->method('b')
253            ->with("a", DOKU_LEXER_UNMATCHED,11)->will($this->returnValue(true));
254        $handler->expects($this->at(9))->method('b')
255            ->with("bb", DOKU_LEXER_MATCHED,12)->will($this->returnValue(true));
256        $handler->expects($this->at(10))->method('b')
257            ->with("a", DOKU_LEXER_UNMATCHED,14)->will($this->returnValue(true));
258        $handler->expects($this->at(11))->method('b')
259            ->with("bbb", DOKU_LEXER_MATCHED,15)->will($this->returnValue(true));
260        $handler->expects($this->at(12))->method('b')
261            ->with("a", DOKU_LEXER_UNMATCHED,18)->will($this->returnValue(true));
262
263        $lexer = new Lexer($handler, "a");
264        $lexer->addPattern("a+", "a");
265        $lexer->addEntryPattern(":", "a", "b");
266        $lexer->addPattern("b+", "b");
267        $this->assertTrue($lexer->parse("abaabaaa:ababbabbba"));
268    }
269    function testNesting() {
270        $handler = $this->createMock('TestParser');
271        $handler->expects($this->at(0))->method('a')
272            ->with("aa", DOKU_LEXER_MATCHED,0)->will($this->returnValue(true));
273        $handler->expects($this->at(1))->method('a')
274            ->with("b", DOKU_LEXER_UNMATCHED,2)->will($this->returnValue(true));
275        $handler->expects($this->at(2))->method('a')
276            ->with("aa", DOKU_LEXER_MATCHED,3)->will($this->returnValue(true));
277        $handler->expects($this->at(3))->method('a')
278            ->with("b", DOKU_LEXER_UNMATCHED,5)->will($this->returnValue(true));
279        $handler->expects($this->at(4))->method('b')
280            ->with("(", DOKU_LEXER_ENTER,6)->will($this->returnValue(true));
281        $handler->expects($this->at(5))->method('b')
282            ->with("bb", DOKU_LEXER_MATCHED,7)->will($this->returnValue(true));
283        $handler->expects($this->at(6))->method('b')
284            ->with("a", DOKU_LEXER_UNMATCHED,9)->will($this->returnValue(true));
285        $handler->expects($this->at(7))->method('b')
286            ->with("bb", DOKU_LEXER_MATCHED,10)->will($this->returnValue(true));
287        $handler->expects($this->at(8))->method('b')
288            ->with(")", DOKU_LEXER_EXIT,12)->will($this->returnValue(true));
289        $handler->expects($this->at(9))->method('a')
290            ->with("aa", DOKU_LEXER_MATCHED,13)->will($this->returnValue(true));
291        $handler->expects($this->at(10))->method('a')
292            ->with("b", DOKU_LEXER_UNMATCHED,15)->will($this->returnValue(true));
293
294
295        $lexer = new Lexer($handler, "a");
296        $lexer->addPattern("a+", "a");
297        $lexer->addEntryPattern("(", "a", "b");
298        $lexer->addPattern("b+", "b");
299        $lexer->addExitPattern(")", "b");
300        $this->assertTrue($lexer->parse("aabaab(bbabb)aab"));
301    }
302    function testSingular() {
303        $handler = $this->createMock('TestParser');
304        $handler->expects($this->at(0))->method('a')
305            ->with("aa", DOKU_LEXER_MATCHED,0)->will($this->returnValue(true));
306        $handler->expects($this->at(1))->method('b')
307            ->with("b", DOKU_LEXER_SPECIAL,2)->will($this->returnValue(true));
308        $handler->expects($this->at(2))->method('a')
309            ->with("aa", DOKU_LEXER_MATCHED,3)->will($this->returnValue(true));
310        $handler->expects($this->at(3))->method('a')
311            ->with("xx", DOKU_LEXER_UNMATCHED,5)->will($this->returnValue(true));
312        $handler->expects($this->at(4))->method('b')
313            ->with("bbb", DOKU_LEXER_SPECIAL,7)->will($this->returnValue(true));
314        $handler->expects($this->at(5))->method('a')
315            ->with("xx", DOKU_LEXER_UNMATCHED,10)->will($this->returnValue(true));
316        $lexer = new Lexer($handler, "a");
317        $lexer->addPattern("a+", "a");
318        $lexer->addSpecialPattern("b+", "a", "b");
319        $this->assertTrue($lexer->parse("aabaaxxbbbxx"));
320    }
321    function testUnwindTooFar() {
322        $handler = $this->createMock('TestParser');
323        $handler->expects($this->at(0))->method('a')
324            ->with("aa", DOKU_LEXER_MATCHED,0)->will($this->returnValue(true));
325        $handler->expects($this->at(1))->method('a')
326            ->with(")", DOKU_LEXER_EXIT,2)->will($this->returnValue(true));
327
328        $lexer = new Lexer($handler, "a");
329        $lexer->addPattern("a+", "a");
330        $lexer->addExitPattern(")", "a");
331        $this->assertFalse($lexer->parse("aa)aa"));
332    }
333}
334
335class TestOfLexerHandlers extends DokuWikiTest {
336    function testModeMapping() {
337        $handler = $this->createMock('TestParser');
338        $handler->expects($this->at(0))->method('a')
339            ->with("aa", DOKU_LEXER_MATCHED,0)->will($this->returnValue(true));
340        $handler->expects($this->at(1))->method('a')
341            ->with("(", DOKU_LEXER_ENTER,2)->will($this->returnValue(true));
342        $handler->expects($this->at(2))->method('a')
343            ->with("bb", DOKU_LEXER_MATCHED,3)->will($this->returnValue(true));
344        $handler->expects($this->at(3))->method('a')
345            ->with("a", DOKU_LEXER_UNMATCHED,5)->will($this->returnValue(true));
346        $handler->expects($this->at(4))->method('a')
347            ->with("bb", DOKU_LEXER_MATCHED,6)->will($this->returnValue(true));
348        $handler->expects($this->at(5))->method('a')
349            ->with(")", DOKU_LEXER_EXIT,8)->will($this->returnValue(true));
350        $handler->expects($this->at(6))->method('a')
351            ->with("b", DOKU_LEXER_UNMATCHED,9)->will($this->returnValue(true));
352
353        $lexer = new Lexer($handler, "mode_a");
354        $lexer->addPattern("a+", "mode_a");
355        $lexer->addEntryPattern("(", "mode_a", "mode_b");
356        $lexer->addPattern("b+", "mode_b");
357        $lexer->addExitPattern(")", "mode_b");
358        $lexer->mapHandler("mode_a", "a");
359        $lexer->mapHandler("mode_b", "a");
360        $this->assertTrue($lexer->parse("aa(bbabb)b"));
361    }
362}
363
364class TestParserByteIndex {
365
366    function __construct() {}
367
368    function ignore() {}
369
370    function caught() {}
371}
372
373class TestOfLexerByteIndices extends DokuWikiTest {
374
375    function testIndex() {
376        $doc = "aaa<file>bcd</file>eee";
377
378        $handler = $this->createMock('TestParserByteIndex');
379        $handler->expects($this->any())->method('ignore')->will($this->returnValue(true));
380        $handler->expects($this->at(1))->method('caught')
381            ->with("<file>", DOKU_LEXER_ENTER, strpos($doc,'<file>'))->will($this->returnValue(true));
382        $handler->expects($this->at(2))->method('caught')
383            ->with("b", DOKU_LEXER_SPECIAL, strpos($doc,'b'))->will($this->returnValue(true));
384        $handler->expects($this->at(3))->method('caught')
385            ->with("c", DOKU_LEXER_MATCHED, strpos($doc,'c'))->will($this->returnValue(true));
386        $handler->expects($this->at(4))->method('caught')
387            ->with("d", DOKU_LEXER_UNMATCHED, strpos($doc,'d'))->will($this->returnValue(true));
388        $handler->expects($this->at(5))->method('caught')
389            ->with("</file>", DOKU_LEXER_EXIT, strpos($doc,'</file>'))->will($this->returnValue(true));
390
391        $lexer = new Lexer($handler, "ignore");
392        $lexer->addEntryPattern("<file>", "ignore", "caught");
393        $lexer->addExitPattern("</file>", "caught");
394        $lexer->addSpecialPattern('b','caught','special');
395        $lexer->mapHandler('special','caught');
396        $lexer->addPattern('c','caught');
397
398        $this->assertTrue($lexer->parse($doc));
399    }
400
401    function testIndexLookaheadEqual() {
402        $doc = "aaa<file>bcd</file>eee";
403
404        $handler = $this->createMock('TestParserByteIndex');
405        $handler->expects($this->any())->method('ignore')->will($this->returnValue(true));
406        $handler->expects($this->at(1))->method('caught')
407            ->with("<file>", DOKU_LEXER_ENTER, strpos($doc,'<file>'))->will($this->returnValue(true));
408        $handler->expects($this->at(2))->method('caught')
409            ->with("b", DOKU_LEXER_SPECIAL, strpos($doc,'b'))->will($this->returnValue(true));
410        $handler->expects($this->at(3))->method('caught')
411            ->with("c", DOKU_LEXER_MATCHED, strpos($doc,'c'))->will($this->returnValue(true));
412        $handler->expects($this->at(4))->method('caught')
413            ->with("d", DOKU_LEXER_UNMATCHED, strpos($doc,'d'))->will($this->returnValue(true));
414        $handler->expects($this->at(5))->method('caught')
415            ->with("</file>", DOKU_LEXER_EXIT, strpos($doc,'</file>'))->will($this->returnValue(true));
416
417        $lexer = new Lexer($handler, "ignore");
418        $lexer->addEntryPattern('<file>(?=.*</file>)', "ignore", "caught");
419        $lexer->addExitPattern("</file>", "caught");
420        $lexer->addSpecialPattern('b','caught','special');
421        $lexer->mapHandler('special','caught');
422        $lexer->addPattern('c','caught');
423
424        $this->assertTrue($lexer->parse($doc));
425    }
426
427    function testIndexLookaheadNotEqual() {
428        $doc = "aaa<file>bcd</file>eee";
429
430        $handler = $this->createMock('TestParserByteIndex');
431        $handler->expects($this->any())->method('ignore')->will($this->returnValue(true));
432        $handler->expects($this->at(1))->method('caught')
433            ->with("<file>", DOKU_LEXER_ENTER, strpos($doc,'<file>'))->will($this->returnValue(true));
434        $handler->expects($this->at(2))->method('caught')
435            ->with("b", DOKU_LEXER_SPECIAL, strpos($doc,'b'))->will($this->returnValue(true));
436        $handler->expects($this->at(3))->method('caught')
437            ->with("c", DOKU_LEXER_MATCHED, strpos($doc,'c'))->will($this->returnValue(true));
438        $handler->expects($this->at(4))->method('caught')
439            ->with("d", DOKU_LEXER_UNMATCHED, strpos($doc,'d'))->will($this->returnValue(true));
440        $handler->expects($this->at(5))->method('caught')
441            ->with("</file>", DOKU_LEXER_EXIT, strpos($doc,'</file>'))->will($this->returnValue(true));
442
443        $lexer = new Lexer($handler, "ignore");
444        $lexer->addEntryPattern('<file>(?!foo)', "ignore", "caught");
445        $lexer->addExitPattern("</file>", "caught");
446        $lexer->addSpecialPattern('b','caught','special');
447        $lexer->mapHandler('special','caught');
448        $lexer->addPattern('c','caught');
449
450        $this->assertTrue($lexer->parse($doc));
451    }
452
453    function testIndexLookbehindEqual() {
454        $doc = "aaa<file>bcd</file>eee";
455
456        $handler = $this->createMock('TestParserByteIndex');
457        $handler->expects($this->any())->method('ignore')->will($this->returnValue(true));
458        $handler->expects($this->at(1))->method('caught')
459            ->with("<file>", DOKU_LEXER_ENTER, strpos($doc,'<file>'))->will($this->returnValue(true));
460        $handler->expects($this->at(2))->method('caught')
461            ->with("b", DOKU_LEXER_SPECIAL, strpos($doc,'b'))->will($this->returnValue(true));
462        $handler->expects($this->at(3))->method('caught')
463            ->with("c", DOKU_LEXER_MATCHED, strpos($doc,'c'))->will($this->returnValue(true));
464        $handler->expects($this->at(4))->method('caught')
465            ->with("d", DOKU_LEXER_UNMATCHED, strpos($doc,'d'))->will($this->returnValue(true));
466        $handler->expects($this->at(5))->method('caught')
467            ->with("</file>", DOKU_LEXER_EXIT, strpos($doc,'</file>'))->will($this->returnValue(true));
468
469        $lexer = new Lexer($handler, "ignore");
470        $lexer->addEntryPattern('<file>', "ignore", "caught");
471        $lexer->addExitPattern("(?<=d)</file>", "caught");
472        $lexer->addSpecialPattern('b','caught','special');
473        $lexer->mapHandler('special','caught');
474        $lexer->addPattern('c','caught');
475
476        $this->assertTrue($lexer->parse($doc));
477    }
478
479    function testIndexLookbehindNotEqual() {
480        $doc = "aaa<file>bcd</file>eee";
481
482        $handler = $this->createMock('TestParserByteIndex');
483        $handler->expects($this->any())->method('ignore')->will($this->returnValue(true));
484        $handler->expects($this->at(1))->method('caught')
485            ->with("<file>", DOKU_LEXER_ENTER, strpos($doc,'<file>'))->will($this->returnValue(true));
486        $handler->expects($this->at(2))->method('caught')
487            ->with("b", DOKU_LEXER_SPECIAL, strpos($doc,'b'))->will($this->returnValue(true));
488        $handler->expects($this->at(3))->method('caught')
489            ->with("c", DOKU_LEXER_MATCHED, strpos($doc,'c'))->will($this->returnValue(true));
490        $handler->expects($this->at(4))->method('caught')
491            ->with("d", DOKU_LEXER_UNMATCHED, strpos($doc,'d'))->will($this->returnValue(true));
492        $handler->expects($this->at(5))->method('caught')
493            ->with("</file>", DOKU_LEXER_EXIT, strpos($doc,'</file>'))->will($this->returnValue(true));
494
495        $lexer = new Lexer($handler, 'ignore');
496        $lexer->addEntryPattern('<file>', 'ignore', 'caught');
497        $lexer->addExitPattern('(?<!c)</file>', 'caught');
498        $lexer->addSpecialPattern('b','caught','special');
499        $lexer->mapHandler('special','caught');
500        $lexer->addPattern('c','caught');
501
502        $this->assertTrue($lexer->parse($doc));
503    }
504
505    /**
506     * This test is primarily to ensure the correct match is chosen
507     * when there are non-captured elements in the pattern.
508     */
509    function testIndexSelectCorrectMatch() {
510        $doc = "ALL FOOLS ARE FOO";
511        $pattern = '\bFOO\b';
512
513        $handler = $this->createMock('TestParserByteIndex');
514        $handler->expects($this->any())->method('ignore')->will($this->returnValue(true));
515
516        $matches = array();
517        preg_match('/'.$pattern.'/',$doc,$matches,PREG_OFFSET_CAPTURE);
518
519        $handler->expects($this->once())->method('caught')
520            ->with("FOO", DOKU_LEXER_SPECIAL, $matches[0][1])->will($this->returnValue(true));
521
522        $lexer = new Lexer($handler, "ignore");
523        $lexer->addSpecialPattern($pattern,'ignore','caught');
524
525        $this->assertTrue($lexer->parse($doc));
526    }
527
528}
529