diff --git a/.github/workflows/php-ci.yml b/.github/workflows/php-ci.yml
new file mode 100644
index 0000000..1328584
--- /dev/null
+++ b/.github/workflows/php-ci.yml
@@ -0,0 +1,33 @@
+name: PHP CI
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+
+jobs:
+ build:
+ name: "PHP Tests"
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ php-version: [ 8.1, 8.2, 8.3 ]
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Set up PHP ${{ matrix.php-version }}
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-version }}
+ coverage: none
+ tools: composer:v2
+
+ - name: Install dependencies
+ run: composer --prefer-source install
+
+ - name: Run tests
+ run: ./vendor/bin/phpunit -v
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index d1502b0..63dcaa1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
vendor/
composer.lock
+.phpunit.result.cache
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index c7d6c7c..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-language: php
-
-php:
- - 7.1
- - 7.2
- - 7.3
-
-before_script:
- - composer --prefer-source install
-
-script:
- - ./vendor/bin/phpunit -v --coverage-clover ./build/logs/clover.xml
-
-after_script:
- - ./vendor/bin/test-reporter --coverage-report ./build/logs/clover.xml
diff --git a/composer.json b/composer.json
index 9c8f00d..b9f72dc 100644
--- a/composer.json
+++ b/composer.json
@@ -11,13 +11,12 @@
],
"license": "MIT",
"require": {
- "php": ">=7.1",
+ "php": ">=8.1",
"ext-SPL": "*",
- "doctrine/lexer": ">=1.0"
+ "doctrine/lexer": "^3.0"
},
"require-dev": {
- "phpunit/phpunit": "~5.0",
- "codeclimate/php-test-reporter": "dev-master"
+ "phpunit/phpunit": "^9.6"
},
"autoload": {
"psr-0": {
diff --git a/lib/CrEOF/Geo/String/Lexer.php b/lib/CrEOF/Geo/String/Lexer.php
index 4a8cba8..bed4788 100644
--- a/lib/CrEOF/Geo/String/Lexer.php
+++ b/lib/CrEOF/Geo/String/Lexer.php
@@ -62,7 +62,7 @@ public function __construct($input = null)
*
* @return int
*/
- protected function getType(&$value)
+ protected function getType(string &$value)
{
if (is_numeric($value)) {
$value += 0;
@@ -71,6 +71,8 @@ protected function getType(&$value)
return self::T_INTEGER;
}
+ $value = rtrim(sprintf('%.8F', $value), '0');
+
return self::T_FLOAT;
}
diff --git a/lib/CrEOF/Geo/String/Parser.php b/lib/CrEOF/Geo/String/Parser.php
index 5561122..66aed87 100644
--- a/lib/CrEOF/Geo/String/Parser.php
+++ b/lib/CrEOF/Geo/String/Parser.php
@@ -222,7 +222,7 @@ private function degrees()
$glimpse = $this->lexer->glimpse();
// If a colon hasn't been matched, and next token is a number followed by degree symbol, when tuple separator is space instead of comma, this value is complete
- if (Lexer::T_COLON !== $this->nextSymbol && $this->lexer->isNextTokenAny(array(Lexer::T_INTEGER, Lexer::T_FLOAT)) && Lexer::T_DEGREE === $glimpse['type']) {
+ if ($glimpse !== null && Lexer::T_COLON !== $this->nextSymbol && $this->lexer->isNextTokenAny(array(Lexer::T_INTEGER, Lexer::T_FLOAT)) && Lexer::T_DEGREE === $glimpse->type) {
return $degrees;
}
@@ -407,7 +407,7 @@ private function cardinal($value)
{
// If cardinal direction was not on previous coordinate it can be anything
if (null === $this->nextCardinal) {
- $this->nextCardinal = Lexer::T_CARDINAL_LON === $this->lexer->lookahead['type'] ? Lexer::T_CARDINAL_LON : Lexer::T_CARDINAL_LAT;
+ $this->nextCardinal = Lexer::T_CARDINAL_LON === $this->lexer->lookahead->type ? Lexer::T_CARDINAL_LON : Lexer::T_CARDINAL_LAT;
}
// Match cardinal direction
@@ -468,7 +468,7 @@ private function match($token)
$this->lexer->moveNext();
// Return the token value
- return $this->lexer->token['value'];
+ return $this->lexer->token->value;
}
/**
@@ -482,11 +482,11 @@ private function syntaxError($expected)
{
$expected = sprintf('Expected %s, got', $expected);
$token = $this->lexer->lookahead;
- $found = null === $this->lexer->lookahead ? 'end of string.' : sprintf('"%s"', $token['value']);
+ $found = null === $this->lexer->lookahead ? 'end of string.' : sprintf('"%s"', $token->value);
$message = sprintf(
'[Syntax Error] line 0, col %d: Error: %s %s in value "%s"',
- isset($token['position']) ? $token['position'] : '-1',
+ $token->position ?? -1,
$expected,
$found,
$this->input
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 17aa61e..dbfadc0 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,7 +1,7 @@
./tests/CrEOF/Geo/String/Tests
-
-
-
- lib
-
- tests
- vendor
-
-
-
diff --git a/tests/CrEOF/Geo/String/Tests/LexerTest.php b/tests/CrEOF/Geo/String/Tests/LexerTest.php
index 7265684..05d60b6 100644
--- a/tests/CrEOF/Geo/String/Tests/LexerTest.php
+++ b/tests/CrEOF/Geo/String/Tests/LexerTest.php
@@ -24,6 +24,8 @@
namespace CrEOF\Geo\String\Tests;
use CrEOF\Geo\String\Lexer;
+use Doctrine\Common\Lexer\Token;
+use PHPUnit\Framework\TestCase;
/**
* Lexer tests
@@ -31,13 +33,13 @@
* @author Derek J. Lambert
* @license http://dlambert.mit-license.org MIT
*/
-class LexerTest extends \PHPUnit_Framework_TestCase
+class LexerTest extends TestCase
{
/**
* @param string $input
* @param array $expectedTokens
*
- * @dataProvider testDataSource
+ * @dataProvider tokenDataSource
*/
public function testLexer($input, array $expectedTokens)
{
@@ -53,7 +55,7 @@ public function testReusedLexer()
{
$lexer = new Lexer();
- foreach ($this->testDataSource() as $data) {
+ foreach ($this->tokenDataSource() as $data) {
$input = $data['input'];
$expectedTokens = $data['expectedTokens'];
$index = 0;
@@ -69,149 +71,149 @@ public function testReusedLexer()
/**
* @return array[]
*/
- public function testDataSource()
+ public function tokenDataSource()
{
return array (
array(
'input' => '15',
'expectedTokens' => array(
- array('value' => 15, 'type' => Lexer::T_INTEGER, 'position' => 0),
+ new Token(15, Lexer::T_INTEGER, 0),
)
),
array(
'input' => '1E5',
'expectedTokens' => array(
- array('value' => 100000, 'type' => Lexer::T_FLOAT, 'position' => 0),
+ new Token(100000, Lexer::T_FLOAT, 0),
)
),
array(
'input' => '1e5',
'expectedTokens' => array(
- array('value' => 100000, 'type' => Lexer::T_FLOAT, 'position' => 0),
+ new Token(100000, Lexer::T_FLOAT, 0),
)
),
array(
'input' => '1.5E5',
'expectedTokens' => array(
- array('value' => 150000, 'type' => Lexer::T_FLOAT, 'position' => 0),
+ new Token(150000, Lexer::T_FLOAT, 0),
)
),
array(
'input' => '1E-5',
'expectedTokens' => array(
- array('value' => 0.00001, 'type' => Lexer::T_FLOAT, 'position' => 0),
+ new Token('0.00001', Lexer::T_FLOAT, 0),
)
),
array(
'input' => '40° 26\' 46" N',
'expectedTokens' => array(
- array('value' => 40, 'type' => Lexer::T_INTEGER, 'position' => 0),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 2),
- array('value' => 26, 'type' => Lexer::T_INTEGER, 'position' => 5),
- array('value' => '\'', 'type' => Lexer::T_APOSTROPHE, 'position' => 7),
- array('value' => 46, 'type' => Lexer::T_INTEGER, 'position' => 9),
- array('value' => '"', 'type' => Lexer::T_QUOTE, 'position' => 11),
- array('value' => 'N', 'type' => Lexer::T_CARDINAL_LAT, 'position' => 13)
+ new Token(40, Lexer::T_INTEGER, 0),
+ new Token('°', Lexer::T_DEGREE, 2),
+ new Token(26, Lexer::T_INTEGER, 5),
+ new Token('\'', Lexer::T_APOSTROPHE, 7),
+ new Token(46, Lexer::T_INTEGER, 9),
+ new Token('"', Lexer::T_QUOTE, 11),
+ new Token('N', Lexer::T_CARDINAL_LAT, 13),
)
),
array(
'input' => '40° 26\' 46" N 79° 58\' 56" W',
'expectedTokens' => array(
- array('value' => 40, 'type' => Lexer::T_INTEGER, 'position' => 0),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 2),
- array('value' => 26, 'type' => Lexer::T_INTEGER, 'position' => 5),
- array('value' => '\'', 'type' => Lexer::T_APOSTROPHE, 'position' => 7),
- array('value' => 46, 'type' => Lexer::T_INTEGER, 'position' => 9),
- array('value' => '"', 'type' => Lexer::T_QUOTE, 'position' => 11),
- array('value' => 'N', 'type' => Lexer::T_CARDINAL_LAT, 'position' => 13),
- array('value' => 79, 'type' => Lexer::T_INTEGER, 'position' => 15),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 17),
- array('value' => 58, 'type' => Lexer::T_INTEGER, 'position' => 20),
- array('value' => '\'', 'type' => Lexer::T_APOSTROPHE, 'position' => 22),
- array('value' => 56, 'type' => Lexer::T_INTEGER, 'position' => 24),
- array('value' => '"', 'type' => Lexer::T_QUOTE, 'position' => 26),
- array('value' => 'W', 'type' => Lexer::T_CARDINAL_LON, 'position' => 28)
+ new Token(40, Lexer::T_INTEGER, 0),
+ new Token('°', Lexer::T_DEGREE, 2),
+ new Token(26, Lexer::T_INTEGER, 5),
+ new Token('\'', Lexer::T_APOSTROPHE, 7),
+ new Token(46, Lexer::T_INTEGER, 9),
+ new Token('"', Lexer::T_QUOTE, 11),
+ new Token('N', Lexer::T_CARDINAL_LAT, 13),
+ new Token(79, Lexer::T_INTEGER, 15),
+ new Token('°', Lexer::T_DEGREE, 17),
+ new Token(58, Lexer::T_INTEGER, 20),
+ new Token('\'', Lexer::T_APOSTROPHE, 22),
+ new Token(56, Lexer::T_INTEGER, 24),
+ new Token('"', Lexer::T_QUOTE, 26),
+ new Token('W', Lexer::T_CARDINAL_LON, 28),
)
),
array(
'input' => '40°26\'46"N 79°58\'56"W',
'expectedTokens' => array(
- array('value' => 40, 'type' => Lexer::T_INTEGER, 'position' => 0),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 2),
- array('value' => 26, 'type' => Lexer::T_INTEGER, 'position' => 4),
- array('value' => '\'', 'type' => Lexer::T_APOSTROPHE, 'position' => 6),
- array('value' => 46, 'type' => Lexer::T_INTEGER, 'position' => 7),
- array('value' => '"', 'type' => Lexer::T_QUOTE, 'position' => 9),
- array('value' => 'N', 'type' => Lexer::T_CARDINAL_LAT, 'position' => 10),
- array('value' => 79, 'type' => Lexer::T_INTEGER, 'position' => 12),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 14),
- array('value' => 58, 'type' => Lexer::T_INTEGER, 'position' => 16),
- array('value' => '\'', 'type' => Lexer::T_APOSTROPHE, 'position' => 18),
- array('value' => 56, 'type' => Lexer::T_INTEGER, 'position' => 19),
- array('value' => '"', 'type' => Lexer::T_QUOTE, 'position' => 21),
- array('value' => 'W', 'type' => Lexer::T_CARDINAL_LON, 'position' => 22)
+ new Token(40, Lexer::T_INTEGER, 0),
+ new Token('°', Lexer::T_DEGREE, 2),
+ new Token(26, Lexer::T_INTEGER, 4),
+ new Token('\'', Lexer::T_APOSTROPHE, 6),
+ new Token(46, Lexer::T_INTEGER, 7),
+ new Token('"', Lexer::T_QUOTE, 9),
+ new Token('N', Lexer::T_CARDINAL_LAT, 10),
+ new Token(79, Lexer::T_INTEGER, 12),
+ new Token('°', Lexer::T_DEGREE, 14),
+ new Token(58, Lexer::T_INTEGER, 16),
+ new Token('\'', Lexer::T_APOSTROPHE, 18),
+ new Token(56, Lexer::T_INTEGER, 19),
+ new Token('"', Lexer::T_QUOTE, 21),
+ new Token('W', Lexer::T_CARDINAL_LON, 22),
)
),
array(
'input' => '40°26\'46"N, 79°58\'56"W',
'expectedTokens' => array(
- array('value' => 40, 'type' => Lexer::T_INTEGER, 'position' => 0),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 2),
- array('value' => 26, 'type' => Lexer::T_INTEGER, 'position' => 4),
- array('value' => '\'', 'type' => Lexer::T_APOSTROPHE, 'position' => 6),
- array('value' => 46, 'type' => Lexer::T_INTEGER, 'position' => 7),
- array('value' => '"', 'type' => Lexer::T_QUOTE, 'position' => 9),
- array('value' => 'N', 'type' => Lexer::T_CARDINAL_LAT, 'position' => 10),
- array('value' => ',', 'type' => Lexer::T_COMMA, 'position' => 11),
- array('value' => 79, 'type' => Lexer::T_INTEGER, 'position' => 13),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 15),
- array('value' => 58, 'type' => Lexer::T_INTEGER, 'position' => 17),
- array('value' => '\'', 'type' => Lexer::T_APOSTROPHE, 'position' => 19),
- array('value' => 56, 'type' => Lexer::T_INTEGER, 'position' => 20),
- array('value' => '"', 'type' => Lexer::T_QUOTE, 'position' => 22),
- array('value' => 'W', 'type' => Lexer::T_CARDINAL_LON, 'position' => 23)
+ new Token(40, Lexer::T_INTEGER, 0),
+ new Token('°', Lexer::T_DEGREE, 2),
+ new Token(26, Lexer::T_INTEGER, 4),
+ new Token('\'', Lexer::T_APOSTROPHE, 6),
+ new Token(46, Lexer::T_INTEGER, 7),
+ new Token('"', Lexer::T_QUOTE, 9),
+ new Token('N', Lexer::T_CARDINAL_LAT, 10),
+ new Token(',', Lexer::T_COMMA, 11),
+ new Token(79, Lexer::T_INTEGER, 13),
+ new Token('°', Lexer::T_DEGREE, 15),
+ new Token(58, Lexer::T_INTEGER, 17),
+ new Token('\'', Lexer::T_APOSTROPHE, 19),
+ new Token(56, Lexer::T_INTEGER, 20),
+ new Token('"', Lexer::T_QUOTE, 22),
+ new Token('W', Lexer::T_CARDINAL_LON, 23)
)
),
array(
'input' => '40.4738° N, 79.553° W',
'expectedTokens' => array(
- array('value' => 40.4738, 'type' => Lexer::T_FLOAT, 'position' => 0),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 7),
- array('value' => 'N', 'type' => Lexer::T_CARDINAL_LAT, 'position' => 10),
- array('value' => ',', 'type' => Lexer::T_COMMA, 'position' => 11),
- array('value' => 79.553, 'type' => Lexer::T_FLOAT, 'position' => 13),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 19),
- array('value' => 'W', 'type' => Lexer::T_CARDINAL_LON, 'position' => 22)
+ new Token('40.4738', Lexer::T_FLOAT, 0),
+ new Token('°', Lexer::T_DEGREE, 7),
+ new Token('N', Lexer::T_CARDINAL_LAT, 10),
+ new Token(',', Lexer::T_COMMA, 11),
+ new Token('79.553', Lexer::T_FLOAT, 13),
+ new Token('°', Lexer::T_DEGREE, 19),
+ new Token('W', Lexer::T_CARDINAL_LON, 22)
)
),
array(
'input' => '40.4738°, 79.553°',
'expectedTokens' => array(
- array('value' => 40.4738, 'type' => Lexer::T_FLOAT, 'position' => 0),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 7),
- array('value' => ',', 'type' => Lexer::T_COMMA, 'position' => 9),
- array('value' => 79.553, 'type' => Lexer::T_FLOAT, 'position' => 11),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 17),
+ new Token('40.4738', Lexer::T_FLOAT, 0),
+ new Token('°', Lexer::T_DEGREE, 7),
+ new Token(',', Lexer::T_COMMA, 9),
+ new Token('79.553', Lexer::T_FLOAT, 11),
+ new Token('°', Lexer::T_DEGREE, 17),
)
),
array(
'input' => '40.4738° -79.553°',
'expectedTokens' => array(
- array('value' => 40.4738, 'type' => Lexer::T_FLOAT, 'position' => 0),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 7),
- array('value' => '-', 'type' => Lexer::T_MINUS, 'position' => 10),
- array('value' => 79.553, 'type' => Lexer::T_FLOAT, 'position' => 11),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 17),
+ new Token('40.4738', Lexer::T_FLOAT, 0),
+ new Token('°', Lexer::T_DEGREE, 7),
+ new Token('-', Lexer::T_MINUS, 10),
+ new Token('79.553', Lexer::T_FLOAT, 11),
+ new Token('°', Lexer::T_DEGREE, 17),
)
),
array(
'input' => "40.4738° \t -79.553°",
'expectedTokens' => array(
- array('value' => 40.4738, 'type' => Lexer::T_FLOAT, 'position' => 0),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 7),
- array('value' => '-', 'type' => Lexer::T_MINUS, 'position' => 12),
- array('value' => 79.553, 'type' => Lexer::T_FLOAT, 'position' => 13),
- array('value' => '°', 'type' => Lexer::T_DEGREE, 'position' => 19),
+ new Token('40.4738', Lexer::T_FLOAT, 0),
+ new Token('°', Lexer::T_DEGREE, 7),
+ new Token('-', Lexer::T_MINUS, 12),
+ new Token('79.553', Lexer::T_FLOAT, 13),
+ new Token('°', Lexer::T_DEGREE, 19),
)
)
);
diff --git a/tests/CrEOF/Geo/String/Tests/ParserTest.php b/tests/CrEOF/Geo/String/Tests/ParserTest.php
index a7aa67a..8f12709 100644
--- a/tests/CrEOF/Geo/String/Tests/ParserTest.php
+++ b/tests/CrEOF/Geo/String/Tests/ParserTest.php
@@ -24,6 +24,7 @@
namespace CrEOF\Geo\String\Tests;
use CrEOF\Geo\String\Parser;
+use PHPUnit\Framework\TestCase;
/**
* Parser tests
@@ -31,7 +32,7 @@
* @author Derek J. Lambert
* @license http://dlambert.mit-license.org MIT
*/
-class ParserTest extends \PHPUnit_Framework_TestCase
+class ParserTest extends TestCase
{
/**
* @param string $input
@@ -45,20 +46,12 @@ public function testGoodValues($input, $expected)
$value = $parser->parse();
- $this->assertEquals($expected, $value);
- }
-
- public function testParserReuse()
- {
- $parser = new Parser();
-
- foreach ($this->dataSourceGood() as $data) {
- $input = $data['input'];
- $expected = $data['expected'];
-
- $value = $parser->parse($input);
-
- $this->assertEquals($expected, $value);
+ if (!is_array($expected)) {
+ $expected = [$expected];
+ $value = [$value];
+ }
+ foreach ($expected as $key => $expectedValue) {
+ self::assertSame((string) $expected[$key], (string) $value[$key]);
}
}
@@ -71,7 +64,8 @@ public function testParserReuse()
*/
public function testBadValues($input, $exception, $message)
{
- $this->setExpectedException($exception, $message);
+ self::expectException($exception);
+ self::expectExceptionMessage($message);
$parser = new Parser($input);