Skip to content

Commit

Permalink
Merge branch 'release/0.2.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
jmalloc committed Jul 8, 2013
2 parents 10b8c3c + 02fdd99 commit a5e3856
Show file tree
Hide file tree
Showing 14 changed files with 204 additions and 106 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Duct Changelog

### 0.2.1 (2013-07-08)

* **[NEW]** Added `error` event to `EventedParser`
* **[FIXED]** Parsers are now reset when an exception is thrown

### 0.2.0 (2013-07-08)

* **[NEW]** Added `EventedParser`, a SAX-JS/Clarinet-like event-based JSON parser
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,9 @@ the following events are emitted as the buffer is parsed.
* **object-key** (string $key): emitted when an object key is encountered
* **value** (mixed $value): emitted whenever a scalar or null is encountered, including inside objects and arrays
* **document** (mixed $value): emitted after an entire JSON document has been parsed
* **error** (Exception $error): emitted when a syntax error is encountered

<!-- references -->
[Build Status]: https://travis-ci.org/IcecaveStudios/duct.png?branch=develop
[Test Coverage]: https://coveralls.io/repos/IcecaveStudios/duct/badge.png?branch=develop
[SemVer]: http://calm-shore-6115.herokuapp.com/?label=semver&value=0.2.0&color=yellow
[SemVer]: http://calm-shore-6115.herokuapp.com/?label=semver&value=0.2.1&color=yellow
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?php
namespace Icecave\Duct\TypeCheck\Validator\Icecave\Duct\Exception;
namespace Icecave\Duct\TypeCheck\Validator\Icecave\Duct\Detail\Exception;

class LexerExceptionTypeCheck extends \Icecave\Duct\TypeCheck\AbstractValidator
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?php
namespace Icecave\Duct\TypeCheck\Validator\Icecave\Duct\Exception;
namespace Icecave\Duct\TypeCheck\Validator\Icecave\Duct\Detail\Exception;

class ParserExceptionTypeCheck extends \Icecave\Duct\TypeCheck\AbstractValidator
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,6 @@ public function reset(array $arguments)
}
}

public function lex(array $arguments)
{
$argumentCount = \count($arguments);
if ($argumentCount < 1) {
throw new \Icecave\Duct\TypeCheck\Exception\MissingArgumentException('buffer', 0, 'string');
} elseif ($argumentCount > 1) {
throw new \Icecave\Duct\TypeCheck\Exception\UnexpectedArgumentException(1, $arguments[1]);
}
$value = $arguments[0];
if (!\is_string($value)) {
throw new \Icecave\Duct\TypeCheck\Exception\UnexpectedArgumentValueException(
'buffer',
0,
$arguments[0],
'string'
);
}
}

public function feed(array $arguments)
{
$argumentCount = \count($arguments);
Expand All @@ -74,13 +55,6 @@ public function finalize(array $arguments)
}
}

public function tokens(array $arguments)
{
if (\count($arguments) > 0) {
throw new \Icecave\Duct\TypeCheck\Exception\UnexpectedArgumentException(0, $arguments[0]);
}
}

public function consume(array $arguments)
{
if (\count($arguments) > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,32 @@ public function validateConstruct(array $arguments)
}
}

public function feed(array $arguments)
{
$argumentCount = \count($arguments);
if ($argumentCount < 1) {
throw new \Icecave\Duct\TypeCheck\Exception\MissingArgumentException('buffer', 0, 'string');
} elseif ($argumentCount > 1) {
throw new \Icecave\Duct\TypeCheck\Exception\UnexpectedArgumentException(1, $arguments[1]);
}
$value = $arguments[0];
if (!\is_string($value)) {
throw new \Icecave\Duct\TypeCheck\Exception\UnexpectedArgumentValueException(
'buffer',
0,
$arguments[0],
'string'
);
}
}

public function finalize(array $arguments)
{
if (\count($arguments) > 0) {
throw new \Icecave\Duct\TypeCheck\Exception\UnexpectedArgumentException(0, $arguments[0]);
}
}

public function on(array $arguments)
{
$argumentCount = \count($arguments);
Expand Down
32 changes: 23 additions & 9 deletions lib/Icecave/Duct/AbstractParser.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Icecave\Duct;

use Exception;
use Icecave\Duct\Detail\Lexer;
use Icecave\Duct\Detail\TokenStreamParser;
use Icecave\Duct\TypeCheck\TypeCheck;
Expand Down Expand Up @@ -30,15 +31,19 @@ public function __construct(Lexer $lexer = null, TokenStreamParser $parser = nul

$this->lexer = $lexer;
$this->parser = $parser;

$this->lexer->on(
'token',
array($this->parser, 'feedToken')
);
}

/**
* Parse one or more complete JSON values.
*
* @param string $buffer The JSON data.
*
* @return Vector<mixed> The sequence of parsed JSON values.
* @throws Exception\ParserException Indicates that the JSON stream terminated midway through a JSON value.
* @throws Exception\SyntaxExceptionInterface
*/
public function parse($buffer)
{
Expand All @@ -63,28 +68,37 @@ public function reset()
/**
* Feed (potentially incomplete) JSON data to the parser.
*
* @param string $buffer The JSON data.
* @param string $buffer The JSON data.
* @throws Exception\SyntaxExceptionInterface
*/
public function feed($buffer)
{
$this->typeCheck->feed(func_get_args());

$this->lexer->feed($buffer);
$this->parser->feed($this->lexer->tokens());
try {
$this->lexer->feed($buffer);
} catch (Exception $e) {
$this->reset();
throw $e;
}
}

/**
* Finalize parsing.
*
* @throws Exception\ParserException Indicates that the JSON stream terminated midway through a JSON value.
* @throws Exception\SyntaxExceptionInterface
*/
public function finalize()
{
$this->typeCheck->finalize(func_get_args());

$this->lexer->finalize();
$this->parser->feed($this->lexer->tokens());
$this->parser->finalize();
try {
$this->lexer->finalize();
$this->parser->finalize();
} catch (Exception $e) {
$this->reset();
throw $e;
}
}

private $typeCheck;
Expand Down
46 changes: 6 additions & 40 deletions lib/Icecave/Duct/Detail/Lexer.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<?php
namespace Icecave\Duct\Detail;

use Icecave\Collections\Vector;
use Evenement\EventEmitter;
use Icecave\Duct\TypeCheck\TypeCheck;

/**
* Streaming JSON lexer.
*
* Converts incoming streams of JSON data into tokens.
*/
class Lexer
class Lexer extends EventEmitter
{
/**
* @param string $encoding The encoding of the incoming JSON data stream.
Expand All @@ -34,32 +34,14 @@ public function reset()
$this->inputBuffer = '';
$this->tokenBuffer = '';
$this->unicodeBuffer = '';
$this->tokens = new Vector;
}

/**
* Tokenize JSON data.
*
* @param string $buffer The JSON data.
*
* @return Vector<Token> The sequence of tokens representing the JSON data.
* @throws Exception\LexerException Indicates that the input terminated midway through a token.
*/
public function lex($buffer)
{
$this->typeCheck->lex(func_get_args());

$this->reset();
$this->feed($buffer);
$this->finalize();

return $this->tokens();
}

/**
* Feed JSON data to the lexer.
*
* @param string $buffer The JSON data.
*
* @throws Exception\LexerException
*/
public function feed($buffer)
{
Expand Down Expand Up @@ -105,21 +87,6 @@ public function finalize()
}
}

/**
* Fetch the tokens produced by the lexer so far and remove them from the internal token sequence.
*
* @return Vector<Token> The sequence of tokens representing the JSON value.
*/
public function tokens()
{
$this->typeCheck->tokens(func_get_args());

$tokens = clone $this->tokens;
$this->tokens->clear();

return $tokens;
}

private function consume()
{
if (!mb_check_encoding($this->inputBuffer, $this->encoding)) {
Expand Down Expand Up @@ -412,7 +379,7 @@ private function isWhitespace($char)
*/
private function emitSpecial($char)
{
$this->tokens->pushBack(Token::createSpecial($char));
$this->emit('token', array(Token::createSpecial($char)));
$this->tokenBuffer = '';
$this->state = LexerState::BEGIN();
}
Expand All @@ -422,7 +389,7 @@ private function emitSpecial($char)
*/
private function emitLiteral($value)
{
$this->tokens->pushBack(Token::createLiteral($value));
$this->emit('token', array(Token::createLiteral($value)));
$this->tokenBuffer = '';
$this->state = LexerState::BEGIN();
}
Expand Down Expand Up @@ -496,5 +463,4 @@ private function convertUnicodeCodepoint($codepoint)
private $tokenBuffer;
private $unicodeBuffer;
private $unicodeHighSurrogate;
private $tokens;
}
4 changes: 3 additions & 1 deletion lib/Icecave/Duct/Detail/TokenStreamParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public function reset()
* Feed tokens to the parser.
*
* @param mixed<Token> $tokens The sequence of tokens.
*
* @throws Exception\ParserException
*/
public function feed($tokens)
{
Expand Down Expand Up @@ -61,7 +63,7 @@ public function finalize()
/**
* @param Token $token
*/
private function feedToken(Token $token)
public function feedToken(Token $token)
{
if (!$this->stack->isEmpty()) {
switch ($this->stack->next()->state) {
Expand Down
34 changes: 34 additions & 0 deletions lib/Icecave/Duct/EventedParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
namespace Icecave\Duct;

use Evenement\EventEmitterInterface;
use Exception;
use Icecave\Duct\Detail\Lexer;
use Icecave\Duct\Detail\TokenStreamParser;
use Icecave\Duct\TypeCheck\TypeCheck;
Expand All @@ -24,6 +25,39 @@ public function __construct(Lexer $lexer = null, TokenStreamParser $parser = nul
parent::__construct($lexer, $parser);
}

/**
* Feed (potentially incomplete) JSON data to the parser.
*
* @param string $buffer The JSON data.
* @throws Exception\SyntaxExceptionInterface
*/
public function feed($buffer)
{
$this->typeCheck->feed(func_get_args());

try {
parent::feed($buffer);
} catch (Exception $e) {
$this->emit('error', array($e));
}
}

/**
* Finalize parsing.
*
* @throws Exception\SyntaxExceptionInterface
*/
public function finalize()
{
$this->typeCheck->finalize(func_get_args());

try {
parent::finalize();
} catch (Exception $e) {
$this->emit('error', array($e));
}
}

/**
* @param string $event
* @param callable $listener
Expand Down
4 changes: 2 additions & 2 deletions lib/Icecave/Duct/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ public function __construct(Lexer $lexer = null, TokenStreamParser $parser = nul
*
* @param string $buffer The JSON data.
*
* @return Vector<mixed> The sequence of parsed JSON values.
* @throws Exception\ParserException Indicates that the JSON stream terminated midway through a JSON value.
* @return Vector<mixed> The sequence of parsed JSON values.
* @throws Exception\SyntaxExceptionInterface
*/
public function parse($buffer)
{
Expand Down
Loading

0 comments on commit a5e3856

Please sign in to comment.