Skip to content

Commit

Permalink
Adding Stream methods skipWhile, consumeWhile, consumeValueWhile and …
Browse files Browse the repository at this point in the history
…consumeValueUntil
  • Loading branch information
lukewatts committed May 30, 2022
1 parent 629f38c commit df66d73
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 15 deletions.
73 changes: 58 additions & 15 deletions src/Stream.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,42 +57,84 @@ public function current(): \Affinity4\Tokenizer\Token
}

/**
* Next All
* Skip While
*
* @return array
* Skip each token that is a match in ...$args
* Stops when a token does not match ...$args list
*
* @param string $type
*
* @return void
*/
public function nextAll(): array
public function skipWhile(...$args): void
{
$tokens = [];
$token = $this->current();
while ($token) {
$tokens[] = $token;
while ($token && in_array($token->type, $args)) {
$token = $this->next();
}

return $tokens;
}

/**
* Next Until
*
* @param string $type
* Consume While
*
* Moves pointer ahead while type is one of ...$args
*
* Returns array of tokens which where 'consumed'
*
* @return array
*/
public function nextUntil(string $type): array
public function consumeWhile(... $args): array
{
$tokens = [];
$token = $this->current();
while ($token && $token->type !== $type) {
$tokens = [];
while ($token && in_array($token->type, $args)) {
$tokens[] = $token;

$token = $this->next();
}

return $tokens;
}

/**
* consumeValueWhile
*
* @param arglist $args
*
* @return string
*/
public function consumeValueWhile(... $args): string
{
$tokens = $this->consumeWhile(...$args);
$i = 0;
$value = '';
while ($tokens[$i]) {
$value .= $tokens[$i]->value;
}

return $value;
}

/**
* Consume Value Until
*
* Returns value up until one of the provided token types is matched
*
* @param arglist $args
*
* @return string
*/
public function consumeValueUntil(...$args): string
{
$Token = $this->current();
$value = '';
while ($Token && !in_array($Token->type, $args)) {
$value .= $Token->value;
$Token = $this->next();
}

return $value;
}

/**
* Next Token
*
Expand Down Expand Up @@ -161,6 +203,7 @@ public function hasNext(): bool

return isset($this->tokens[$pos]);
}


/**
* Rewind
Expand Down
126 changes: 126 additions & 0 deletions tests/StreamTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -352,4 +352,130 @@ public function testStreamTokensAreCorrect(): void
$this->assertSame($next['length'], $this->Stream->current()->length);
}
}

/**
* @covers \Affinity4\Tokenizer\Stream::skipWhile
*
* @return void
*/
public function testSkipWhileMethod(): void
{
$template = ' div(class="test")';

$Tokenizer = new Tokenizer([
'\s+' => 'T_WHITESPACE',
'\S+' => 'T_NOT_WHITESPACE'
]);

$Stream = $Tokenizer->tokenize($template);

$Stream->skipWhile('T_WHITESPACE');

$this->assertSame('T_NOT_WHITESPACE', $Stream->current()->type);
$this->assertSame('div(class="test")', $Stream->current()->value);
}

/**
* @covers \Affinity4\Tokenizer\Stream::consumeWhile
*
* @return void
*/
public function testConsumeWhileMethod(): void
{
$template = 'div(class="test")';

$Tokenizer = new Tokenizer([
'\w+' => 'T_WORD',
'[^a-zA-Z0-9_]' => 'T_NOT_WORD'
]);

$Stream = $Tokenizer->tokenize($template);

$tokens = $Stream->consumeWhile('T_WORD');

$this->assertCount(1, $tokens);
$this->assertSame('T_WORD', $tokens[0]->type);
$this->assertSame('div', $tokens[0]->value);
}

/**
* @covers \Affinity4\Tokenizer\Stream::consumeValueWhile
*
* @return void
*/
public function testConsumeValueWhileMethod(): void
{
$template = 'div(class="test")';

$Tokenizer = new Tokenizer([
'\w+' => 'T_WORD',
'[^a-zA-Z0-9_]' => 'T_NOT_WORD'
]);

$Stream = $Tokenizer->tokenize($template);

$tokens = $Stream->consumeValueWhile('T_WORD');

$this->assertCount(1, $tokens);
$this->assertSame('T_WORD', $tokens[0]->type);
$this->assertSame('div', $tokens[0]->value);
}

/**
* @covers \Affinity4\Tokenizer\Stream::consumeValueUntil
*
* @return void
*/
public function testConsumeValueUntilMethod(): void
{
$template = 'div(class="test")';

$Tokenizer = new Tokenizer([
'\w+' => 'T_WORD',
Token::T_OPEN_PARENTHESIS => 'T_OPEN_PARENTHESIS',
Token::T_CLOSE_PARENTHESIS => 'T_CLOSE_PARENTHESIS',
Token::T_EQUALS => 'T_EQUALS',
Token::T_DOUBLE_QUOTE => 'T_DOUBLE_QUOTE'
]);

$Stream = $Tokenizer->tokenize($template);

$Stream->skipWhile('T_WORD');

$this->assertSame('(', $Stream->current()->value);
$this->assertSame('T_OPEN_PARENTHESIS', $Stream->current()->type);
$Stream->next();
$attributes = $Stream->consumeValueUntil('T_CLOSE_PARENTHESIS');
$this->assertSame('class="test"', $attributes);
$this->assertSame(')', $Stream->current()->value);
$this->assertSame('T_CLOSE_PARENTHESIS', $Stream->current()->type);
}

/**
* @covers \Affinity4\Tokenizer\Stream::consumeValueUntil
*
* @return void
*/
public function testConsumeValueUntilMethodWhereNoTokensConsumed(): void
{
$template = 'div()'; // testing what happens when the very next token is the 'until'

$Tokenizer = new Tokenizer([
'\w+' => 'T_WORD',
Token::T_OPEN_PARENTHESIS => 'T_OPEN_PARENTHESIS',
Token::T_CLOSE_PARENTHESIS => 'T_CLOSE_PARENTHESIS',
]);

$Stream = $Tokenizer->tokenize($template);

$Stream->skipWhile('T_WORD');

$this->assertSame('(', $Stream->current()->value);
$this->assertSame('T_OPEN_PARENTHESIS', $Stream->current()->type);
$Stream->next();
$attributes = $Stream->consumeValueUntil('T_CLOSE_PARENTHESIS');
$this->assertEmpty($attributes);
$this->assertSame(')', $Stream->current()->value);
$this->assertSame('T_CLOSE_PARENTHESIS', $Stream->current()->type);
}
}

0 comments on commit df66d73

Please sign in to comment.