Skip to content

Commit

Permalink
Merge pull request #7 from creof/develop
Browse files Browse the repository at this point in the history
Merge develop for 2.1.0 release
  • Loading branch information
djlambert committed Apr 9, 2016
2 parents 1057fe7 + fa6daaa commit 0191764
Show file tree
Hide file tree
Showing 14 changed files with 749 additions and 1,134 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Added
### Changed

## [2.1.0] - 2016-04-09
### Added
- Add tokens for 3DM, 3DZ, and 4D coordinates to Lexer.
- Method Lexer::value() to get current token value.
- Match Z, M, or ZM tokens in Parser (not currently used).
- Add test for Parser reuse.
- Add test for Lexer reuse.

### Changed
- Regex used to catch tokens.
- Allow Lexer instantiation with no parameters so object can be reused.
- Allow Parser instantiation with no parameters so object can be reused.
- Changed visibility of Parser::$type.
- Use Lexer::value() in Parser.
- Set srid to null before parsing value.
- Consolidated all Parser test data into ParserTest.
- Update usage documentation in README.md.

## [2.0.0] - 2015-11-18
### Added
- Change base namespace to CrEOF\Geo\WKT to avoid class collision with other CrEOF packages.
Expand Down
29 changes: 24 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,36 @@ Lexer and parser library for WKT/EWKT spatial object strings.

## Usage

Pass value to be parsed in the constructor, then call parse() on the created object.
There are two use patterns for the parser. The value to be parsed can be passed into the constructor, then parse()
called on the returned ```Parser``` object:

```php
$input = 'POLYGON((0 0,10 0,10 10,0 10,0 0))';

$parser = new Parser($input);
$value = $parser->parse();

$value = $parser->parse();
```

If many values need to be parsed, a single ```Parser``` instance can be used:

```php
$input1 = 'POLYGON((0 0,10 0,10 10,0 10,0 0))';
$input2 = 'POINT(0,0)';

$parser = new Parser();

$value1 = $parser->parse($input1);
$value2 = $parser->parse($input2);
```

## Return

The parser will return an array with the keys ```srid```, ```type```, and ```value```.
- ```srid``` is the SRID if EWKT was passed in the constructor, null otherwise.
- ```type``` is the spatial object type.
- ```value``` will contain an array with 2 numeric values, or nested arrays containing these depending on the spatial object type.
- ```type``` is the spatial object type (POINT, LINESTRING, etc.)
- ```value``` will contain an array with integer or float values for points, or nested arrays containing these based on spatial object type.
- ```srid``` is the SRID if EWKT value was parsed, null otherwise.

## Exceptions

The ```Lexer``` and ```Parser``` will throw expections implementing interface ```CrEOF\Geo\WKT\Exception\ExceptionInterface```.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
"require": {
"php": ">=5.3.3",
"ext-SPL": "*",
"doctrine/lexer": ">=1.0"
"doctrine/lexer": "~1.0"
},
"require-dev": {
"phpunit/phpunit": ">=4.8",
"phpunit/phpunit": "<5.0",
"codeclimate/php-test-reporter": "dev-master"
},
"autoload": {
Expand Down
48 changes: 36 additions & 12 deletions lib/CrEOF/Geo/WKT/Lexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,46 @@ class Lexer extends AbstractLexer
const T_MINUS = 14;
const T_SEMICOLON = 50;
const T_SRID = 500;
const T_ZM = 501;
const T_Z = 502;
const T_M = 503;

// Geometry types > 600
const T_TYPE = 600;
const T_POINT = 601;
const T_LINESTRING = 602;
const T_POLYGON = 603;
const T_MULTIPOINT = 604;
const T_MULTILINESTRING = 605;
const T_MULTIPOLYGON = 606;
const T_GEOMETRYCOLLECTION = 607;
const T_TYPE = 600;
const T_POINT = 601;
const T_LINESTRING = 602;
const T_POLYGON = 603;
const T_MULTIPOINT = 604;
const T_MULTILINESTRING = 605;
const T_MULTIPOLYGON = 606;
const T_GEOMETRYCOLLECTION = 607;
const T_CIRCULARSTRING = 608;
const T_COMPOUNDCURVE = 609;
const T_CURVEPOLYGON = 610;
const T_MULTICURVE = 611;
const T_MULTISURFACE = 612;
const T_CURVE = 613;
const T_SURFACE = 614;
const T_POLYHEDRALSURFACE = 615;
const T_TIN = 616;
const T_TRIANGLE = 617;

/**
* @param string $input a query string
*/
public function __construct($input)
public function __construct($input = null)
{
$this->setInput($input);
if (null !== $input) {
$this->setInput($input);
}
}

/**
* @return mixed
*/
public function value()
{
return $this->token['value'];
}

/**
Expand Down Expand Up @@ -114,8 +137,9 @@ protected function getType(&$value)
protected function getCatchablePatterns()
{
return array(
'[a-z]*',
'(?:[+-]?[0-9]+)(?:[\.][0-9]+)?'
'',
'zm|[a-z]+[a-ln-z]',
'[+-]?[0-9]+(?:[\.][0-9]+)?'
);
}

Expand Down
105 changes: 60 additions & 45 deletions lib/CrEOF/Geo/WKT/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class Parser
/**
* @var string
*/
protected $type;
private $type;

/**
* @var string
Expand All @@ -51,25 +51,35 @@ class Parser
/**
* @var Lexer
*/
private $lexer;
private static $lexer;

/**
* @param string $input
*/
public function __construct($input)
public function __construct($input = null)
{
$this->input = $input;
$this->lexer = new Lexer($input);
self::$lexer = new Lexer();

if (null !== $input) {
$this->input = $input;
}
}

/**
* @return array
*/
public function parse()
public function parse($input = null)
{
$this->lexer->moveNext();
if (null !== $input) {
$this->input = $input;
}

if ($this->lexer->lookahead['type'] == Lexer::T_SRID) {
self::$lexer->setInput($this->input);
self::$lexer->moveNext();

$this->srid = null;

if (self::$lexer->isNextToken(Lexer::T_SRID)) {
$this->srid = $this->srid();
}

Expand All @@ -90,7 +100,7 @@ protected function srid()
$this->match(Lexer::T_EQUALS);
$this->match(Lexer::T_INTEGER);

$srid = $this->lexer->token['value'];
$srid = self::$lexer->value();

$this->match(Lexer::T_SEMICOLON);

Expand All @@ -106,7 +116,33 @@ protected function type()
{
$this->match(Lexer::T_TYPE);

return $this->lexer->token['value'];
return self::$lexer->value();
}

/**
* Match spatial geometry object
*
* @return array
*/
protected function geometry()
{
$type = $this->type();
$this->type = $type;

if (self::$lexer->isNextTokenAny(array(Lexer::T_Z, Lexer::T_M, Lexer::T_ZM))) {
$this->match(self::$lexer->lookahead['type']);
}

$this->match(Lexer::T_OPEN_PARENTHESIS);

$value = $this->$type();

$this->match(Lexer::T_CLOSE_PARENTHESIS);

return array(
'type' => $type,
'value' => $value
);
}

/**
Expand All @@ -129,18 +165,18 @@ protected function point()
*/
protected function coordinate()
{
$this->match(($this->lexer->isNextToken(Lexer::T_FLOAT) ? Lexer::T_FLOAT : Lexer::T_INTEGER));
$this->match((self::$lexer->isNextToken(Lexer::T_FLOAT) ? Lexer::T_FLOAT : Lexer::T_INTEGER));

if (! $this->lexer->isNextToken(Lexer::T_E)) {
return $this->lexer->token['value'];
if (! self::$lexer->isNextToken(Lexer::T_E)) {
return self::$lexer->value();
}

$number = $this->lexer->token['value'];
$number = self::$lexer->value();

$this->match(Lexer::T_E);
$this->match(Lexer::T_INTEGER);

return $number * pow(10, $this->lexer->token['value']);
return $number * pow(10, self::$lexer->value());
}

/**
Expand Down Expand Up @@ -172,7 +208,7 @@ protected function pointList()
{
$points = array($this->point());

while ($this->lexer->isNextToken(Lexer::T_COMMA)) {
while (self::$lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);

$points[] = $this->point();
Expand All @@ -194,7 +230,7 @@ protected function pointLists()

$this->match(Lexer::T_CLOSE_PARENTHESIS);

while ($this->lexer->isNextToken(Lexer::T_COMMA)) {
while (self::$lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);
$this->match(Lexer::T_OPEN_PARENTHESIS);

Expand All @@ -219,7 +255,7 @@ protected function multiPolygon()

$this->match(Lexer::T_CLOSE_PARENTHESIS);

while ($this->lexer->isNextToken(Lexer::T_COMMA)) {
while (self::$lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);
$this->match(Lexer::T_OPEN_PARENTHESIS);

Expand Down Expand Up @@ -251,27 +287,6 @@ protected function multiLineString()
return $this->pointLists();
}

/**
* Match spatial geometry object
*
* @return array
*/
protected function geometry()
{
$type = $this->type();

$this->match(Lexer::T_OPEN_PARENTHESIS);

$value = $this->$type();

$this->match(Lexer::T_CLOSE_PARENTHESIS);

return array(
'type' => $type,
'value' => $value
);
}

/**
* Match GEOMETRYCOLLECTION value
*
Expand All @@ -281,7 +296,7 @@ protected function geometryCollection()
{
$collection = array($this->geometry());

while ($this->lexer->isNextToken(Lexer::T_COMMA)) {
while (self::$lexer->isNextToken(Lexer::T_COMMA)) {
$this->match(Lexer::T_COMMA);

$collection[] = $this->geometry();
Expand All @@ -297,13 +312,13 @@ protected function geometryCollection()
*/
protected function match($token)
{
$lookaheadType = $this->lexer->lookahead['type'];
$lookaheadType = self::$lexer->lookahead['type'];

if ($lookaheadType !== $token && ($token !== Lexer::T_TYPE || $lookaheadType <= Lexer::T_TYPE)) {
throw $this->syntaxError($this->lexer->getLiteral($token));
throw $this->syntaxError(self::$lexer->getLiteral($token));
}

$this->lexer->moveNext();
self::$lexer->moveNext();
}

/**
Expand All @@ -316,8 +331,8 @@ protected function match($token)
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']);
$token = self::$lexer->lookahead;
$found = null === self::$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',
Expand Down
Loading

0 comments on commit 0191764

Please sign in to comment.