From 1b32450baf0e5293b7f4ecae821896d1449fa911 Mon Sep 17 00:00:00 2001 From: MallardDuck Date: Tue, 15 Dec 2020 14:50:23 -0500 Subject: [PATCH] Add a file based example and tweak excel example to be reuseable --- tests/Examples/ExcelClasses.php | 57 ++++++++++++++ tests/Examples/ExcelTest.php | 54 +------------- tests/Examples/ExcelTextFileStreamTest.php | 86 ++++++++++++++++++++++ tests/stubs/example-excel-1.txt | 1 + tests/stubs/example-excel-2.txt | 1 + 5 files changed, 146 insertions(+), 53 deletions(-) create mode 100644 tests/Examples/ExcelClasses.php create mode 100644 tests/Examples/ExcelTextFileStreamTest.php create mode 100644 tests/stubs/example-excel-1.txt create mode 100644 tests/stubs/example-excel-2.txt diff --git a/tests/Examples/ExcelClasses.php b/tests/Examples/ExcelClasses.php new file mode 100644 index 0000000..1a656e8 --- /dev/null +++ b/tests/Examples/ExcelClasses.php @@ -0,0 +1,57 @@ +col = $col; + $this->row = $row; + } +} +class Range +{ + private Cell $from; + private Cell $to; + + function __construct(Cell $from, Cell $to) + { + $this->from = $from; + $this->to = $to; + } +} +class Intersection +{ + private Range $l; + private Range $r; + + function __construct(Range $l, Range $r) + { + $this->l = $l; + $this->r = $r; + } +} +class Sum +{ + private Intersection $intersection; + + function __construct(Intersection $intersection) + { + $this->intersection = $intersection; + } +} +class Ampersand +{ + private Cell $l; + private Cell $r; + + function __construct(Cell $l, Cell $r) + { + $this->l = $l; + $this->r = $r; + } +} diff --git a/tests/Examples/ExcelTest.php b/tests/Examples/ExcelTest.php index 8cea66e..1ae3e27 100644 --- a/tests/Examples/ExcelTest.php +++ b/tests/Examples/ExcelTest.php @@ -76,56 +76,4 @@ private function excelParser(): Parser } -class Cell -{ - private $col; - private $row; - - function __construct($col, $row) - { - $this->col = $col; - $this->row = $row; - } -} -class Range -{ - private Cell $from; - private Cell $to; - - function __construct(Cell $from, Cell $to) - { - $this->from = $from; - $this->to = $to; - } -} -class Intersection -{ - private Range $l; - private Range $r; - - function __construct(Range $l, Range $r) - { - $this->l = $l; - $this->r = $r; - } -} -class Sum -{ - private Intersection $intersection; - - function __construct(Intersection $intersection) - { - $this->intersection = $intersection; - } -} -class Ampersand -{ - private Cell $l; - private Cell $r; - - function __construct(Cell $l, Cell $r) - { - $this->l = $l; - $this->r = $r; - } -} +require_once __DIR__ . '/ExcelClasses.php'; diff --git a/tests/Examples/ExcelTextFileStreamTest.php b/tests/Examples/ExcelTextFileStreamTest.php new file mode 100644 index 0000000..c3a94ac --- /dev/null +++ b/tests/Examples/ExcelTextFileStreamTest.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Tests\Verraes\Parsica\Examples; + +use PHPUnit\Framework\TestCase; +use Verraes\Parsica\Parser; +use Verraes\Parsica\PHPUnit\ParserAssertions; +use Verraes\Parsica\TextFileStream; +use function Verraes\Parsica\{alphaChar, between, char, collect, digitChar, skipHSpace1, space, string}; + +final class ExcelTextFileStreamTest extends TestCase +{ + use ParserAssertions; + + private string $stubBasePath; + + public function setUp(): void + { + parent::setUp(); // TODO: Change the autogenerated stub + $this->stubBasePath = dirname(__DIR__) . "/stubs/"; + } + + /** @test */ + public function spaceOrOperatorDependingOnContext() + { + // https://twitter.com/Mark_Baker/status/1309919606887374849?s=20 + // and https://twitter.com/Mark_Baker/status/1309960902482026498?s=20 + // `=SUM(B7:D7 C6:C8)` where space is the intersection operator for the + // intersection between the two ranges B7:D7 and C6:C8 (ie. C7), + // and `=A1 & B1` where the space is simply whitespace and should be ignored + + $parser = $this->excelParser(); + + $input = new TextFileStream($this->stubBasePath . 'example-excel-1.txt'); + $expected = new Sum( + new Intersection( + new Range(new Cell("B", "7"), new Cell("D", "7")), + new Range(new Cell("C", "6"), new Cell("C", "8")), + ) + ); + $this->assertParsesStream($input, $parser, $expected); + + $input = new TextFileStream($this->stubBasePath . 'example-excel-2.txt'); + $expected = new Ampersand( + new Cell("A", "1"), + new Cell("B", "1"), + ); + $this->assertParsesStream($input, $parser, $expected); + } + + private function excelParser(): Parser + { + $parens = fn(Parser $p): Parser => between(char('('), char(')'), $p); + $cell = collect(alphaChar(), digitChar()) + ->map(fn($o) => new Cell($o[0], $o[1])); + $range = collect($cell, char(':'), $cell) + ->map(fn($o) => new Range($o[0], $o[2])); + $intersection = collect($range, space(), $range) + ->map(fn($o) => new Intersection($o[0], $o[2])); + $sum = (string('=SUM')->followedBy($parens($intersection))) + ->map(fn($o) => new Sum($o)); + + + // consumes space before and after Parser $p + $token = fn(Parser $p): Parser => between(skipHSpace1(), skipHSpace1(), $p); + $ampersand = char('=')->followedBy(collect( + $cell, + $token(char('&')), + $cell + ))->map(fn($o) => new Ampersand($o[0], $o[2])); + + + return $sum->or($ampersand); + } + +} + +require_once __DIR__ . '/ExcelClasses.php'; diff --git a/tests/stubs/example-excel-1.txt b/tests/stubs/example-excel-1.txt new file mode 100644 index 0000000..9d3cdbc --- /dev/null +++ b/tests/stubs/example-excel-1.txt @@ -0,0 +1 @@ +=SUM(B7:D7 C6:C8) \ No newline at end of file diff --git a/tests/stubs/example-excel-2.txt b/tests/stubs/example-excel-2.txt new file mode 100644 index 0000000..f70f8bf --- /dev/null +++ b/tests/stubs/example-excel-2.txt @@ -0,0 +1 @@ +=A1 & B1 \ No newline at end of file