- Added while/endwhile and do/while syntaxes

- Fix the abstractclass requirement of parse() function
This commit is contained in:
Dave M. 2022-12-19 19:36:39 +00:00
parent 33298ff2e4
commit bb29a56077
36 changed files with 115 additions and 73 deletions

View File

@ -0,0 +1,47 @@
<?php
namespace Picea\ControlStructure;
abstract class AbstractLoop implements ControlStructure {
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
switch($token) {
case "while":
case "foreach":
$name = "$".uniqid("{$token}_");
$stack = array_filter($context->iterationStack ?? [], function($item) {
return ! $item['or'];
});
$count = count($stack);
if ( $count > 0 ) {
$name .= "[" . end($stack)['uid'] . "]";
}
$context->iterationStack[] = [
'or' => false,
'uid' => $name,
'token' => "end{$token}",
];
return "<?php $token ($arguments): $name = ( $name ?? 0 ) + 1; ?>";
case "endwhile":
case "endforeach":
$last = end($context->iterationStack);
if ( $last['or'] === false ) {
$output = "<?php $token; ?>";
}
else {
$output = "<?php endif; if ( isset({$last['uid']}) ) unset({$last['uid']}); ?>";
}
array_pop($context->iterationStack);
return $output;
}
}
}

View File

@ -6,7 +6,7 @@ class BlockToken implements ControlStructure {
public array $token = [ "arguments", "block", "endblock", "define", "slot", "endslot", "using" ]; public array $token = [ "arguments", "block", "endblock", "define", "slot", "endslot", "using" ];
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
static $slotDefinitions = []; static $slotDefinitions = [];
switch($token) { switch($token) {

View File

@ -6,7 +6,7 @@ class BreakToken implements ControlStructure {
public string $token = "break"; public string $token = "break";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
return "<?php break; ?>"; return "<?php break; ?>";
} }

View File

@ -6,7 +6,7 @@ class CaseToken implements ControlStructure {
public string $token = "case"; public string $token = "case";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
$output = ""; $output = "";
if ( $context->switchStack ) { if ( $context->switchStack ) {

View File

@ -6,7 +6,7 @@ class ContinueToken implements ControlStructure {
public string $token = "continue"; public string $token = "continue";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
return "<?php continue; ?>"; return "<?php continue; ?>";
} }

View File

@ -3,5 +3,5 @@
namespace Picea\ControlStructure; namespace Picea\ControlStructure;
interface ControlStructure { interface ControlStructure {
public function parse(\Picae\Compiler\Context &$context, string $sourceCode, string $token); public function parse(\Picea\Compiler\Context &$context, string $sourceCode, string $token);
} }

View File

@ -6,7 +6,7 @@ class DefaultToken implements ControlStructure {
public string $token = "default"; public string $token = "default";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
$output = ""; $output = "";
if ( $context->switchStack ) { if ( $context->switchStack ) {

View File

@ -6,7 +6,7 @@ class EndRawToken implements ControlStructure {
public string $token = "endraw"; public string $token = "endraw";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
} }
} }

View File

@ -6,7 +6,7 @@ class ExtendsToken implements ControlStructure {
public string $token = "extends"; public string $token = "extends";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $path, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $path, string $token) {
# Triming string's quotes # Triming string's quotes
$path = trim($path, "\"\' \t"); $path = trim($path, "\"\' \t");

View File

@ -6,7 +6,7 @@ class ForToken implements ControlStructure {
public array $token = [ "for", "endfor" ]; public array $token = [ "for", "endfor" ];
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
switch($token) { switch($token) {
case "for": case "for":
$uid = "$".uniqid("for_"); $uid = "$".uniqid("for_");

View File

@ -2,46 +2,8 @@
namespace Picea\ControlStructure; namespace Picea\ControlStructure;
class ForeachToken implements ControlStructure { use DI\Definition\Source\AnnotationBasedAutowiring;
class ForeachToken extends AbstractLoop {
public array $token = [ "foreach", "endforeach" ]; public array $token = [ "foreach", "endforeach" ];
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) {
switch($token) {
case "foreach":
$name = "$".uniqid("foreach_");
$stack = array_filter($context->iterationStack ?? [], function($item) {
return ! $item['or'];
});
$count = count($stack);
if ( $count > 0 ) {
$name .= "[" . end($stack)['uid'] . "]";
}
$context->iterationStack[] = [
'or' => false,
'uid' => $name,
'token' => 'endforeach',
];
return "<?php foreach ($arguments): $name = ( $name ?? 0 ) + 1; ; ?>";
case "endforeach":
$last = end($context->iterationStack);
if ( $last['or'] === false ) {
$output = "<?php endforeach; ?>";
}
else {
$output = "<?php endif; unset({$last['uid']}) ?>";
}
array_pop($context->iterationStack);
return $output;
}
}
} }

View File

@ -6,7 +6,7 @@ class FunctionToken implements ControlStructure {
public array $token = [ "function", "endfunction", "return" ]; public array $token = [ "function", "endfunction", "return" ];
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
switch($token) { switch($token) {
case "function": case "function":
return $this->printFunction($context, $arguments); return $this->printFunction($context, $arguments);

View File

@ -6,7 +6,7 @@ class IfToken implements ControlStructure {
public array $token = [ "if", "else", "elseif", "endif" ]; public array $token = [ "if", "else", "elseif", "endif" ];
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
switch($token) { switch($token) {
case "if": case "if":
return "<?php if ($arguments): ?>"; return "<?php if ($arguments): ?>";

View File

@ -6,7 +6,7 @@ class IncludeToken implements ControlStructure {
public string $token = "include"; public string $token = "include";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
return "<?php echo \$___class__template->picea->inlineContent($arguments); ?>"; return "<?php echo \$___class__template->picea->inlineContent($arguments); ?>";
} }
} }

View File

@ -6,7 +6,7 @@ class NamespaceToken implements ControlStructure {
public string $token = "namespace"; public string $token = "namespace";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
$context->namespace = $arguments; $context->namespace = $arguments;
return ""; return "";
} }

View File

@ -6,9 +6,9 @@ class OrToken implements ControlStructure {
public string $token = "or"; public string $token = "or";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
if ( empty($context->iterationStack) ) { if ( empty($context->iterationStack) ) {
throw new \LogicException("Token `or` was used outside of iterator. Make sure your `for` or `foreach` declaration are properly made."); throw new \LogicException("Token `or` was used outside of iterator. Make sure your `for`, `foreach`, `while`, `do/until` declaration are properly made.");
} }
$key = count( $context->iterationStack ) - 1; $key = count( $context->iterationStack ) - 1;

View File

@ -6,7 +6,7 @@ class RawToken implements ControlStructure {
public string $token = "raw"; public string $token = "raw";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
} }
} }

View File

@ -6,7 +6,7 @@ class SectionToken implements ControlStructure {
public array $token = [ "section", "endsection" ]; public array $token = [ "section", "endsection" ];
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
switch($token) { switch($token) {
case "section": case "section":
return $this->printSection($context, $arguments); return $this->printSection($context, $arguments);

View File

@ -6,7 +6,7 @@ class SwitchToken implements ControlStructure {
public array $token = [ "switch", "case", "endswitch" ]; public array $token = [ "switch", "case", "endswitch" ];
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
switch($token) { switch($token) {
case "switch": case "switch":
$context->switchStack[] = true; $context->switchStack[] = true;

View File

@ -6,7 +6,7 @@ class UseToken implements ControlStructure {
public string $token = "use"; public string $token = "use";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
$context->useStack[] = $arguments; $context->useStack[] = $arguments;
return ""; return "";
} }

View File

@ -6,7 +6,7 @@ class ViewToken implements ControlStructure {
public string $token = "view"; public string $token = "view";
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
# The way this is ordered, if you provide a second arguments, being an array of variables, get_defined_vars() will not be pushed inside the view # The way this is ordered, if you provide a second arguments, being an array of variables, get_defined_vars() will not be pushed inside the view
return "<?php echo \$___class__template->picea->inlineHtml(\$this, $arguments, get_defined_vars()); ?>"; return "<?php echo \$___class__template->picea->inlineHtml(\$this, $arguments, get_defined_vars()); ?>";
} }

View File

@ -0,0 +1,32 @@
<?php
namespace Picea\ControlStructure;
class WhileToken extends AbstractLoop {
public array $token = [ "do", "while", "endwhile", ];
public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
switch($token) {
case "do":
$context->iterationStack[] = [
'or' => false,
'token' => "do",
];
return "<?php do { ?>";
case "while":
if ( $context->iterationStack ?? false ) {
if ( end($context->iterationStack)['token'] === 'do' ) {
array_pop($context->iterationStack);
return "<?php } while($arguments); ?>";
}
}
}
return parent::parse($context, $arguments, $token);
}
}

View File

@ -3,5 +3,5 @@
namespace Picea\Extension; namespace Picea\Extension;
interface Extension { interface Extension {
public function parse(\Picae\Compiler\Context &$context, string $sourceCode, string $token); public function parse(\Picea\Compiler\Context &$context, string $sourceCode, string $token);
} }

View File

@ -10,7 +10,7 @@ class JsonExtension implements Extension, FunctionExtension {
public int $flags = JSON_HEX_TAG | \JSON_HEX_QUOT | \JSON_THROW_ON_ERROR | \JSON_UNESCAPED_UNICODE; public int $flags = JSON_HEX_TAG | \JSON_HEX_QUOT | \JSON_THROW_ON_ERROR | \JSON_UNESCAPED_UNICODE;
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token)
{ {
$flag = $this->flags; $flag = $this->flags;

View File

@ -24,7 +24,7 @@ class LanguageExtension implements Extension, FunctionExtension {
]; ];
} }
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) : string public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string
{ {
switch($token) { switch($token) {
case "language.set": case "language.set":

View File

@ -25,7 +25,7 @@ class MoneyExtension implements Extension {
$context->pushFunction("money", [ $this, 'money' ]); $context->pushFunction("money", [ $this, 'money' ]);
} }
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
return "<?php echo money($arguments) ?>"; return "<?php echo money($arguments) ?>";
} }

View File

@ -6,7 +6,7 @@ class PhpExtension implements Extension {
public array $token = [ "php" ]; public array $token = [ "php" ];
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
return "<?php $arguments ?>"; return "<?php $arguments ?>";
} }
} }

View File

@ -18,7 +18,7 @@ class PrintExtension implements Extension {
$this->encoding = ini_get("default_charset"); $this->encoding = ini_get("default_charset");
} }
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) : string public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string
{ {
switch($token) { switch($token) {
case 'print': case 'print':

View File

@ -19,7 +19,7 @@ class TitleExtension implements Extension {
$context->pushFunction("title", [ $this, 'handleTitle' ]); $context->pushFunction("title", [ $this, 'handleTitle' ]);
} }
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) { public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) {
return "<?php echo title($arguments) ?>"; return "<?php echo title($arguments) ?>";
} }

View File

@ -30,7 +30,7 @@ PATTERN;
$this->register($context); $this->register($context);
} }
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) : ?string public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : ?string
{ {
switch($token) { switch($token) {
case "asset": case "asset":

View File

@ -44,6 +44,7 @@ class DefaultRegistrations implements LanguageRegistration
$compiler->registerControlStructure(new \Picea\ControlStructure\IfToken()); $compiler->registerControlStructure(new \Picea\ControlStructure\IfToken());
$compiler->registerControlStructure(new \Picea\ControlStructure\ForeachToken()); $compiler->registerControlStructure(new \Picea\ControlStructure\ForeachToken());
$compiler->registerControlStructure(new \Picea\ControlStructure\ForToken()); $compiler->registerControlStructure(new \Picea\ControlStructure\ForToken());
$compiler->registerControlStructure(new \Picea\ControlStructure\WhileToken());
$compiler->registerControlStructure(new \Picea\ControlStructure\OrToken()); $compiler->registerControlStructure(new \Picea\ControlStructure\OrToken());
$compiler->registerControlStructure(new \Picea\ControlStructure\SwitchToken()); $compiler->registerControlStructure(new \Picea\ControlStructure\SwitchToken());
$compiler->registerControlStructure(new \Picea\ControlStructure\DefaultToken()); $compiler->registerControlStructure(new \Picea\ControlStructure\DefaultToken());

View File

@ -24,7 +24,7 @@ class Request implements Extension {
$this->register($context); $this->register($context);
} }
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments, string $token) : string { } public function parse(\Picea\Compiler\Context &$context, ?string $arguments, string $token) : string { }
public function register(Context $context) : void public function register(Context $context) : void
{ {

View File

@ -10,7 +10,7 @@ class CommentToken implements Syntax {
protected string $tokenClose = "\#\}"; protected string $tokenClose = "\#\}";
public function parse(/*\Picae\Compiler\Context*/ &$context, string &$sourceCode) public function parse(\Picea\Compiler\Context &$context, string &$sourceCode)
{ {
$sourceCode = preg_replace("#({$this->tokenOpen})(.*?)({$this->tokenClose})#s", "", $sourceCode); $sourceCode = preg_replace("#({$this->tokenOpen})(.*?)({$this->tokenClose})#s", "", $sourceCode);
} }

View File

@ -8,7 +8,7 @@ class EchoRawToken implements Syntax {
public string $tokenClose = "\}\}"; public string $tokenClose = "\}\}";
public function parse(/*\Picae\Compiler\Context*/ &$content, string &$sourceCode) public function parse(\Picea\Compiler\Context &$content, string &$sourceCode)
{ {
$sourceCode = preg_replace_callback("#({$this->tokenOpen})(.*?)({$this->tokenClose})#s", function ($matches) { $sourceCode = preg_replace_callback("#({$this->tokenOpen})(.*?)({$this->tokenClose})#s", function ($matches) {
$line = trim($matches[2], " \t\n\r\0\x0B;"); $line = trim($matches[2], " \t\n\r\0\x0B;");

View File

@ -18,7 +18,7 @@ class EchoSafeToken implements Syntax {
$this->encoding = ini_get("default_charset"); $this->encoding = ini_get("default_charset");
} }
public function parse(/*\Picae\Compiler\Context*/ &$context, string &$sourceCode) public function parse(\Picea\Compiler\Context &$context, string &$sourceCode)
{ {
$sourceCode = preg_replace_callback("#({$this->tokenOpen})(.*?)({$this->tokenClose})#s", function ($matches) { $sourceCode = preg_replace_callback("#({$this->tokenOpen})(.*?)({$this->tokenClose})#s", function ($matches) {
$line = trim($matches[2], " \t\n\r\0\x0B;"); $line = trim($matches[2], " \t\n\r\0\x0B;");

View File

@ -3,5 +3,5 @@
namespace Picea\Syntax; namespace Picea\Syntax;
interface Syntax { interface Syntax {
public function parse(\Picae\Compiler\Context &$context, string &$sourceCode); public function parse(\Picea\Compiler\Context &$context, string &$sourceCode);
} }