Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions src/Parser/Ast/ExpressionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ private function __construct(

public static function fromString(string $expressionAsString): self
{
$tokens = Tokenizer::fromSource(
Source::fromString($expressionAsString)
)->getIterator();
return self::fromTokens(
Tokenizer::fromSource(
Source::fromString($expressionAsString)
)->getIterator()
$tokens
);
}

Expand All @@ -51,7 +52,7 @@ public static function fromString(string $expressionAsString): self
* @param Precedence $precedence
* @return self
*/
public static function fromTokens(\Iterator $tokens, Precedence $precedence = Precedence::SEQUENCE): self
public static function fromTokens(\Iterator &$tokens, Precedence $precedence = Precedence::SEQUENCE): self
{
Scanner::skipSpaceAndComments($tokens);

Expand Down Expand Up @@ -122,8 +123,14 @@ public static function fromTokens(\Iterator $tokens, Precedence $precedence = Pr
}

Scanner::skipSpaceAndComments($tokens);
if (Scanner::isEnd($tokens) || $precedence->mustStopAt(Scanner::type($tokens))) {
return new self(
root: $root
);
}

while (!Scanner::isEnd($tokens) && !$precedence->mustStopAt(Scanner::type($tokens))) {
Scanner::skipSpaceAndComments($tokens);
Comment on lines +126 to +133
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The additions that are here are not necessary. The condition is also handled by the "while" loop and later comes the return.

I think i messed stuff up because the partial fix belongs to #10

either way, it works as it is, just not super clean.

switch (Scanner::type($tokens)) {
case TokenType::OPERATOR_BOOLEAN_AND:
case TokenType::OPERATOR_BOOLEAN_OR:
Expand Down
9 changes: 7 additions & 2 deletions src/Parser/Tokenizer/LookAhead.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ public function getIterator(): \Iterator
yield $token;
}

yield from $this->tokens;
if (!Scanner::isEnd($this->tokens)) {
yield from $this->tokens;
}
Comment on lines +61 to +63
Copy link
Member

@grebaldi grebaldi Jun 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (!Scanner::isEnd($this->tokens)) {
yield from $this->tokens;
}
yield from $this->tokens;

Scanner::isEnd only checks whether $this->tokens is still valid. This is implied in yield from - the extra check is not needed.

EDIT: Oh my god! Not true at all. Indeed if I remove this check, the unit tests fail... This is highly unexpected. I honestly don't know what's going on here.

}

public function shift(): void
Expand All @@ -68,8 +70,11 @@ public function shift(): void
Scanner::skipOne($this->tokens);
}

public function type(): TokenType
public function type(): ?TokenType
{
if (Scanner::isEnd($this->tokens)) {
return null;
}
return Scanner::type($this->tokens);
}
}
22 changes: 22 additions & 0 deletions src/Parser/Tokenizer/Scanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,26 @@ public static function isEnd(\Iterator $tokens): bool
{
return !$tokens->valid();
}

/**
* @param \Iterator<mixed,Token> $tokens
*/
public static function debugPrint(\Iterator &$tokens): string
{
$tokens = (function(): \Generator {
throw new \Exception('Once debugged, $tokens is empty.');
// @phpstan-ignore-next-line
yield;
})();
Comment on lines +174 to +178
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should rather be removed, right?


$tokensAsArray = [];
while ($tokens->valid()) {
$tokensAsArray[] = [
"type" => $tokens->current()->type,
"value" => $tokens->current()->value
];
$tokens->next();
}
return json_encode($tokensAsArray, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
}
}
5 changes: 4 additions & 1 deletion src/Parser/Tokenizer/Tokenizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ public static function fromSource(Source $source): Tokenizer
*/
public function getIterator(): \Iterator
{
yield from self::block($this->source->getIterator());
$fragments = $this->source->getIterator();
while ($fragments->valid()) {
yield from self::block($fragments);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@

use PackageFactory\ComponentEngine\Module\ModuleId;
use PackageFactory\ComponentEngine\Parser\Ast\EnumDeclarationNode;
use PackageFactory\ComponentEngine\Parser\Ast\ExpressionNode;
use PackageFactory\ComponentEngine\Parser\Ast\IdentifierNode;
use PackageFactory\ComponentEngine\Target\Php\Transpiler\Expression\ExpressionTranspiler;
use PackageFactory\ComponentEngine\Test\Unit\TypeSystem\Scope\Fixtures\DummyScope;
use PackageFactory\ComponentEngine\Target\Php\Transpiler\Identifier\IdentifierTranspiler;
use PackageFactory\ComponentEngine\TypeSystem\Type\EnumType\EnumStaticType;
use PackageFactory\ComponentEngine\TypeSystem\Type\StringType\StringType;
use PHPUnit\Framework\TestCase;

final class IdentifierTranspilerTest extends TestCase
Expand Down Expand Up @@ -82,4 +85,36 @@ public function transpilesIdentifierNodesReferringToEnums(): void
$actualTranspilationResult
);
}

public static function identifierInParenthesisExamples(): mixed
{
// @todo find a better place for these tests, as we actually test the ExpressionNode
return [
'(foo)' => ['(foo)', '$this->foo'],
'((foo))' => ['((foo))', '$this->foo'],
'(((foo)))' => ['(((foo)))', '$this->foo']
];
}

/**
* @dataProvider identifierInParenthesisExamples
* @test
*/
public function identifierInParenthesis(string $expression, string $expectedTranspilationResult): void
{
$expressionTranspiler = new ExpressionTranspiler(
scope: new DummyScope([
"foo" => StringType::get()
])
);

$actualTranspilationResult = $expressionTranspiler->transpile(
ExpressionNode::fromString($expression)
);

$this->assertEquals(
$expectedTranspilationResult,
$actualTranspilationResult
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public static function ternaryOperationExamples(): array
{
return [
'true ? 42 : "foo"' => ['true ? 42 : "foo"', '(true ? 42 : \'foo\')'],
'(true) ? 42 : "foo"' => ['(true) ? 42 : "foo"', '(true ? 42 : \'foo\')'],
'a ? 42 : "foo"' => ['a ? 42 : "foo"', '($this->a ? 42 : \'foo\')'],
'true ? b : "foo"' => ['true ? b : "foo"', '(true ? $this->b : \'foo\')'],
'true ? 42 : c' => ['true ? 42 : c', '(true ? 42 : $this->c)'],
Expand Down