diff --git a/src/Expansion.php b/src/Expansion.php index c479b1f..74758b3 100644 --- a/src/Expansion.php +++ b/src/Expansion.php @@ -210,8 +210,10 @@ private function mutate(TokenStream $ts, Ast $context, Engine $engine) : TokenSt if (\count($result->{'args'}) === 0) $cg->this->fail(self::E_EMPTY_EXPANDER_SLICE, $expander->implode(), $expander->tokens()[0]->line()); - $expansion = TokenStream::fromSlice($result->{'args'}); + $expansion = ParsedTokenStream::fromSlice($result->{'args'}); + $mutation = $cg->this->mutate($expansion, $cg->context, $cg->engine); + $mutation->setAst($cg->context); $expander = $cg->this->compileCallable('\Yay\Dsl\Expanders\\', $expander, self::E_BAD_EXPANDER); $mutation = $expander($mutation, $cg->engine); @@ -249,12 +251,15 @@ private function mutate(TokenStream $ts, Ast $context, Engine $engine) : TokenSt if ($key = $result->{'key'}) { $scope[(string) $result->{'key'}] = new Token(T_LNUMBER, (string) $i); } + $expansion = TokenStream::fromSlice($result->{'expansion'}); + $mutation = $cg->this->mutate( $expansion, (new Ast('', $cg->context->unwrap() + (is_array($scope) ? $scope : [$scope]))), $cg->engine ); + if ($i !== count($context)-1) foreach ($delimiters as $d) $mutation->push($d); $cg->ts->inject($mutation); } diff --git a/src/ParsedTokenStream.php b/src/ParsedTokenStream.php new file mode 100644 index 0000000..54420e5 --- /dev/null +++ b/src/ParsedTokenStream.php @@ -0,0 +1,17 @@ +ast = $ast; + } + + function getAst() { + return $this->ast; + } +} diff --git a/src/TokenStream.php b/src/TokenStream.php index 3ecebc0..059cf26 100644 --- a/src/TokenStream.php +++ b/src/TokenStream.php @@ -235,7 +235,7 @@ function isEmpty() : bool { } static function fromSourceWithoutOpenTag(string $source) : self { - $ts = self::fromSource('first->next = $ts->first->next->next; $ts->first->next->previous = $ts->first; $ts->reset(); @@ -246,7 +246,7 @@ static function fromSourceWithoutOpenTag(string $source) : self { static function fromSource(string $source) : self { $tokens = \token_get_all($source); - $ts = new self; + $ts = new static; $first = new NodeStart; $last = new NodeEnd; @@ -293,7 +293,7 @@ static function fromSource(string $source) : self { } static function fromSlice(array $tokens) : self { - $ts = new self; + $ts = new static; $first = new NodeStart; $last = new NodeEnd; @@ -321,6 +321,6 @@ static function fromSlice(array $tokens) : self { } static function fromSequence(Token ...$tokens) : self { - return self::fromSlice($tokens); + return static::fromSlice($tokens); } } diff --git a/tests/TokenStreamTest.php b/tests/TokenStreamTest.php index 0b21d3c..bacd2e3 100644 --- a/tests/TokenStreamTest.php +++ b/tests/TokenStreamTest.php @@ -187,4 +187,14 @@ function testPush() { $ts->push(new Token(T_WHITESPACE, ' ')); $this->assertEquals('tokens()); + $stream->setAst($source); + + + $this->assertSame($source, $stream->getAst()); + } } diff --git a/tests/fixtures/expanders.php b/tests/fixtures/expanders.php index a500e6d..f4a4d18 100644 --- a/tests/fixtures/expanders.php +++ b/tests/fixtures/expanders.php @@ -1,6 +1,6 @@ getAst(); + + $leaf = $ast->{"* outer inner 0 0"}->token(); + $ast->{"outer inner 0 0"} = new Token($leaf->type(), strrev($leaf->value())); + + return ParsedTokenStream::fromSource( + join(" ", $ast->tokens()) + ); +} + +function upper_ast_expander(ParsedTokenStream $stream, Engine $engine) : ParsedTokenStream { + $ast = $stream->getAst(); + + $leaf = $ast->{"* outer inner 0 0"}->token(); + $ast->{"outer inner 0 0"} = new Token($leaf->type(), strtoupper($leaf->value())); + + return ParsedTokenStream::fromSource( + join(" ", $ast->tokens()) + ); +} + +function wrap_ast_expander(ParsedTokenStream $stream, Engine $engine) : ParsedTokenStream { + $ast = $stream->getAst(); + + $leaf = $ast->{"* outer inner 0 0"}->token(); + $ast->{"outer inner 0 0"} = new Token($leaf->type(), "[{$leaf->value()}]"); + + return ParsedTokenStream::fromSource( + join(" ", $ast->tokens()) + ); +} diff --git a/tests/fixtures/parsers.php b/tests/fixtures/parsers.php index 1a7d71d..c1cacd5 100644 --- a/tests/fixtures/parsers.php +++ b/tests/fixtures/parsers.php @@ -1,7 +1,7 @@ > { + $$(\Yay\tests\fixtures\expanders\wrap_ast_expander( + $$(\Yay\tests\fixtures\expanders\upper_ast_expander( + $$(\Yay\tests\fixtures\expanders\reverse_ast_expander( + $(outer) + )) + )) + )) +} + +foo + +?> +--EXPECTF-- +