packages/bison-parser/tests/Unit/Scanner/CursorTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Scanner;
6
7use BisonParser\Ast\Location;
8use BisonParser\Scanner\Cursor;
9use PHPUnit\Framework\Attributes\CoversClass;
10use PHPUnit\Framework\Attributes\Small;
11use PHPUnit\Framework\Attributes\UsesClass;
12use PHPUnit\Framework\TestCase;
13
14#[CoversClass(Cursor::class)]
15#[UsesClass(Location::class)]
16#[Small]
17final class CursorTest extends TestCase
18{
19 public function testEof(): void
20 {
21 $cursor = new Cursor('ab');
22
23 self::assertFalse($cursor->eof());
24 $cursor->take(2);
25 self::assertTrue($cursor->eof());
26 self::assertTrue((new Cursor(''))->eof());
27 }
28
29 public function testPeek(): void
30 {
31 $cursor = new Cursor('abc');
32
33 self::assertSame('a', $cursor->peek());
34 self::assertSame('c', $cursor->peek(2));
35 self::assertSame('', $cursor->peek(3));
36 }
37
38 public function testOffset(): void
39 {
40 $cursor = new Cursor("a\nbc");
41
42 self::assertSame(0, $cursor->offset());
43 $cursor->take(3);
44 self::assertSame(3, $cursor->offset());
45 }
46
47 public function testLocation(): void
48 {
49 $cursor = new Cursor("ab\ncd\n\nef");
50
51 self::assertSame('1:1', (string) $cursor->location());
52 $cursor->take(1);
53 self::assertSame('1:2', (string) $cursor->location());
54 $cursor->take(3);
55 self::assertSame('2:2', (string) $cursor->location());
56 $cursor->take(4);
57 self::assertSame('4:2', (string) $cursor->location());
58 }
59
60 public function testStartsWith(): void
61 {
62 $cursor = new Cursor('%%rest');
63
64 self::assertTrue($cursor->startsWith('%%'));
65 self::assertFalse($cursor->startsWith('%{'));
66 $cursor->take(2);
67 self::assertTrue($cursor->startsWith('rest'));
68 self::assertFalse($cursor->startsWith('rest and more'));
69 }
70
71 public function testTake(): void
72 {
73 $cursor = new Cursor('abc');
74
75 self::assertSame('ab', $cursor->take(2));
76 self::assertSame('c', $cursor->take(5));
77 self::assertSame('', $cursor->take(1));
78 self::assertSame(3, $cursor->offset());
79 }
80
81 public function testMatch(): void
82 {
83 $cursor = new Cursor('foo~bar 12');
84
85 self::assertNull($cursor->match('[0-9]+'));
86 self::assertSame('foo~bar', $cursor->match('[a-z]+~[a-z]+'));
87 self::assertSame(7, $cursor->offset());
88 self::assertSame(' ', $cursor->take(1));
89 self::assertSame('12', $cursor->match('[0-9]+'));
90 }
91
92 public function testLookingAt(): void
93 {
94 $cursor = new Cursor('ab12');
95
96 self::assertTrue($cursor->lookingAt('[a-z]{2}'));
97 self::assertFalse($cursor->lookingAt('[0-9]'));
98 self::assertSame(0, $cursor->offset());
99 self::assertTrue((new Cursor('a~b'))->lookingAt('a~b'));
100 }
101
102 public function testTakeUntil(): void
103 {
104 $cursor = new Cursor("/* a\nb */ tail");
105
106 self::assertSame('/* a', $cursor->takeUntil("\n"));
107 self::assertSame('b ', $cursor->takeUntil('*/'));
108 self::assertSame('2:5', (string) $cursor->location());
109 self::assertNull($cursor->takeUntil('*/'));
110 self::assertSame(' tail', $cursor->take(5));
111 }
112}
113