- First commit of first draft
This commit is contained in:
commit
66c7b349d1
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "mcnd/picea",
|
||||
"description": "A templating engine based on Twig's syntax and Plates's native uses of PHP.",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dave Mc Nicoll",
|
||||
"email": "mcndave@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Picea\\": "src/"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Picea;
|
||||
|
||||
class Builder
|
||||
{
|
||||
protected string $templatePath = "";
|
||||
|
||||
public function __construct(string $templatePath = "./Builder/ClassTemplate.php")
|
||||
{
|
||||
$this->templatePath = $templatePath;
|
||||
}
|
||||
|
||||
public function build(Compiler\Context &$context, string $compiledSource) : array
|
||||
{
|
||||
$className = "PiceaTemplate_" . $this->generateClassUID($compiledSource);
|
||||
|
||||
$replace = [
|
||||
'%NAMESPACE%' => $context->namespace,
|
||||
'%USE%' => $context->renderUses(),
|
||||
'%CLASSNAME%' => $className,
|
||||
'%EXTENDS%' => '',
|
||||
'%CONTENT%' => $compiledSource,
|
||||
];
|
||||
|
||||
$classContent = str_replace(array_keys($replace), array_values($replace), file_get_contents($this->templatePath));
|
||||
|
||||
return [
|
||||
$context->namespace, $className, $classContent,
|
||||
];
|
||||
}
|
||||
|
||||
public function generateClassUID(string $filePath) : string
|
||||
{
|
||||
return md5($filePath);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace %NAMESPACE%;
|
||||
|
||||
%USE%
|
||||
|
||||
class %CLASSNAME% %EXTENDS% {
|
||||
|
||||
protected array $__section_list = [];
|
||||
|
||||
protected array $__variables_list = [];
|
||||
|
||||
public function output() : void
|
||||
{
|
||||
extract($this->__variables_list); ?>%CONTENT%<?php
|
||||
}
|
||||
|
||||
public function __renderSection($name) : void
|
||||
{
|
||||
foreach([ 'prepend', 'default', 'append' ] as $item) {
|
||||
usort($this->__section_list[$name][$item], fn($a, $b) => $a['order'] <=> $b['order']);
|
||||
|
||||
foreach($this->__section_list[$name][$item] as $section) {
|
||||
$section['callback']();
|
||||
|
||||
if ( $item === 'default' ) {
|
||||
break 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function __renderTemplate() {
|
||||
ob_start();
|
||||
$this->output();
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Picea\Builder;
|
||||
|
||||
class SourceFileBuilder {
|
||||
|
||||
public array $section = [];
|
||||
|
||||
protected string $fileName = "";
|
||||
|
||||
protected string $filePath = "";
|
||||
|
||||
protected string $namespace = "";
|
||||
|
||||
protected string $code = "";
|
||||
|
||||
public function fileInfo(string $name, string $path) : self
|
||||
{
|
||||
$this->fileName = $name;
|
||||
$this->filePath = $path;
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Picea;
|
||||
|
||||
class Compiler
|
||||
{
|
||||
protected string $sourceCode = "";
|
||||
|
||||
protected array $syntaxObjectList = [];
|
||||
|
||||
protected array $tagList = [];
|
||||
|
||||
protected string $tagTokenOpen = "\{%";
|
||||
|
||||
protected string $tagTokenClose = "%\}";
|
||||
|
||||
protected array $extensionList = [];
|
||||
|
||||
public function compile(Compiler\Context $context) : string
|
||||
{
|
||||
$context->compiler = $this;
|
||||
|
||||
/**
|
||||
* Syntaxes such as {{ echo }} & {{= echo raw }} && {# comment #}
|
||||
*/
|
||||
foreach($this->syntaxObjectList as $syntax) {
|
||||
$syntax->parse($context, $this->sourceCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Control structures & functions {% functionName arguments %}
|
||||
*/
|
||||
$replace = "#({$this->tagTokenOpen})(.*?)({$this->tagTokenClose})#s";
|
||||
|
||||
$this->sourceCode = preg_replace_callback($replace, function ($matches) use (&$context) {
|
||||
$matches[2] = trim($matches[2]);
|
||||
|
||||
list($token, $arguments) = array_pad(array_filter(explode(' ', $matches[2], 2), 'strlen'), 2, null);
|
||||
|
||||
# @TODO Refractor this parts to allows registration to the tag's name
|
||||
if ( $this->tagList[$token] ?? false ) {
|
||||
return $this->tagList[$token]->parse($context, $arguments);
|
||||
}
|
||||
elseif ( $this->extensionList[$token] ?? false ) {
|
||||
return $this->extensionList[$token]->parse($context, $arguments);
|
||||
}
|
||||
else {
|
||||
throw new \LogicException("Impossible to find token `$token` declared in `{$matches[2]}`. Perhapse you forgot to add a custom token to Picea's engine ?");
|
||||
}
|
||||
|
||||
}, $this->sourceCode);
|
||||
|
||||
return $this->sourceCode;
|
||||
}
|
||||
|
||||
public function loadSourceCode($html) : self
|
||||
{
|
||||
$this->sourceCode = $html;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function registerExtension(Extension\Extension $extension) : self
|
||||
{
|
||||
$this->extensionList[$extension->token] = $extension;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function registerCaching(CachingStrategy $cachingStrategy) : self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function registerSyntax(Syntax\Syntax $syntaxObject) : self
|
||||
{
|
||||
$this->syntaxObjectList[] = $syntaxObject;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function registerControlStructure(ControlStructure\ControlStructure $controlStructureObject) : self
|
||||
{
|
||||
$this->tagList[$controlStructureObject->token] = $controlStructureObject;
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Picea\Compiler;
|
||||
|
||||
class BaseContext extends Context { }
|
|
@ -0,0 +1,44 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Picea\Compiler;
|
||||
|
||||
use Picea\Compiler;
|
||||
|
||||
abstract class Context {
|
||||
|
||||
public string $namespace = "";
|
||||
|
||||
public string $extendFrom = "";
|
||||
|
||||
public array $switchStack = [];
|
||||
|
||||
public array $iterateStack = [];
|
||||
|
||||
public array $useStack = [];
|
||||
|
||||
public array $hooks = [];
|
||||
|
||||
public Compiler $compiler;
|
||||
|
||||
public function hook(string $path, Callable $callback) : self
|
||||
{
|
||||
$this->hooks[$path] ??= [];
|
||||
$this->hooks[$path][] = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function run(string $path, ...$arguments) : self
|
||||
{
|
||||
if ( $this->hooks[$path] ?? false ) {
|
||||
while ( $callback = array_pop($this->hooks[$path]) ) {
|
||||
$callback(...$arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function renderUses() : string
|
||||
{
|
||||
return implode(",", $context->useStack ?? []);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class BreakToken implements ControlStructure {
|
||||
|
||||
public string $token = "break";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
return "<?php break; ?>";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class CaseToken implements ControlStructure {
|
||||
|
||||
public string $token = "case";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
$output = "";
|
||||
|
||||
if ( $context->switchStack ) {
|
||||
array_pop($context->switchStack);
|
||||
}
|
||||
else {
|
||||
$output = "<?php ";
|
||||
}
|
||||
|
||||
return ( $output ?? "" ) . "case $arguments: ?>";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
interface ControlStructure {
|
||||
public function parse(\Picae\Compiler\Context &$context, string $sourceCode);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class DefaultToken implements ControlStructure {
|
||||
|
||||
public string $token = "default";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
$output = "";
|
||||
|
||||
if ( $context->switchStack ) {
|
||||
array_pop($context->switchStack);
|
||||
}
|
||||
else {
|
||||
$output = "<?php ";
|
||||
}
|
||||
|
||||
return ( $output ?? "" ) . "default: ?>";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class ElseIfToken implements ControlStructure {
|
||||
|
||||
public string $token = "elseif";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
return "<?php elseif ($arguments): ?>";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class ElseToken implements ControlStructure {
|
||||
|
||||
public string $token = "else";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
return "<?php else: ?>";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class EndCaseToken extends BreakToken {
|
||||
public string $token = "endcase";
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class EndIfToken implements ControlStructure {
|
||||
|
||||
public string $token = "endif";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
return "<?php endif ?>";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class EndSectionToken implements ControlStructure {
|
||||
|
||||
public string $token = "endsection";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
if ( empty($context->sections) ) {
|
||||
throw new \RuntimeException("A section closing tag {% endsection %} was found without an opening {% section %} tag");
|
||||
}
|
||||
|
||||
$section = array_pop($context->sections);
|
||||
$build = $context->extendFrom ? "" : "\$this->__renderSection({$section['name']});";
|
||||
return "<?php }]; $build?>";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class EndSwitchToken implements ControlStructure {
|
||||
|
||||
public string $token = "endswitch";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
return "<?php endswitch; ?>";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class EndforToken implements ControlStructure {
|
||||
|
||||
public string $token = "endfor";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
if ( end($context->iterationStack)['or'] === false ) {
|
||||
$output = "<?php endfor; ?>";
|
||||
}
|
||||
else {
|
||||
$output = "<?php endif; ?>";
|
||||
}
|
||||
|
||||
array_pop($context->iterationStack);
|
||||
return $output;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class EndforeachToken implements ControlStructure {
|
||||
|
||||
public string $token = "endforeach";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
if ( end($context->iterationStack)['or'] === false ) {
|
||||
$output = "<?php endforeach; ?>";
|
||||
}
|
||||
else {
|
||||
$output = "<?php endif; ?>";
|
||||
}
|
||||
|
||||
array_pop($context->iterationStack);
|
||||
return $output;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class ExtendsToken implements ControlStructure {
|
||||
|
||||
public string $token = "extends";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $path) {
|
||||
# Triming string's quotes
|
||||
$path = trim($path, "\"\' \t");
|
||||
|
||||
$context->extendFrom = $path;
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class ForToken implements ControlStructure {
|
||||
|
||||
public string $token = "for";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
$uid = "$".uniqid("for_");
|
||||
|
||||
$context->iterationStack[] = [
|
||||
'or' => false,
|
||||
'uid' => $uid,
|
||||
'token' => 'endfor',
|
||||
];
|
||||
|
||||
return "<?php for ($arguments): {$uid} = 1; ?>";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class ForeachToken implements ControlStructure {
|
||||
|
||||
public string $token = "foreach";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
$uid = "$".uniqid("foreach_");
|
||||
|
||||
$context->iterationStack[] = [
|
||||
'or' => false,
|
||||
'uid' => $uid,
|
||||
'token' => 'endforeach',
|
||||
];
|
||||
|
||||
return "<?php foreach ($arguments): {$uid} = 1; ?>";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class IfToken implements ControlStructure {
|
||||
|
||||
public string $token = "if";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
return "<?php if ($arguments): ?>";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class NamespaceToken implements ControlStructure {
|
||||
|
||||
public string $token = "namespace";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
$context->namespace = $arguments;
|
||||
return "";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class OrToken implements ControlStructure {
|
||||
|
||||
public string $token = "or";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
if ( empty($context->iterationStack) ) {
|
||||
throw new \LogicException("Token `or` was used outside of iterator. Make sure your `for` or `foreach` declaration are properly made.");
|
||||
}
|
||||
|
||||
$key = count( $context->iterationStack ) - 1;
|
||||
$context->iterationStack[$key]['or'] = true;
|
||||
return "<?php {$context->iterationStack[$key]['token']}; if(false === {$context->iterationStack[$key]['uid']} ?? false): ?>";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class SectionToken implements ControlStructure {
|
||||
|
||||
public string $token = "section";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
list($name, $options) = array_pad(explode(',', $arguments), 2, null);
|
||||
|
||||
if ( $options ?? false ) {
|
||||
$options = eval($options);
|
||||
}
|
||||
|
||||
if ( ! ctype_alnum(str_replace([".", "\"", "'"], "", $name)) ) {
|
||||
throw new \RuntimeException("Your section named `{$name}` contains invalid character. Allowed are only letters, numbers and dots");
|
||||
}
|
||||
|
||||
$context->sections[] = [
|
||||
'name' => $name,
|
||||
'options' => $options,
|
||||
];
|
||||
|
||||
$action = $options['action'] ?? "default";
|
||||
|
||||
if (! in_array($action, ['prepend', 'append', 'default'])) {
|
||||
throw new \RuntimeException("An unsupported action `$action` was given as an option of a {% section %} tag");
|
||||
}
|
||||
|
||||
$order = $options['order'] ?? "count(\$this->__section_list[$name]['$action'])";
|
||||
|
||||
return "<?php \$this->__section_list[$name] ??= [ 'prepend' => [], 'append' => [], 'default' => [] ];
|
||||
\$this->__section_list[$name]['$action'][] = [ 'order' => $order, 'callback' => function() {
|
||||
extract(\$this->__variables_list); ?>";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class SwitchToken implements ControlStructure {
|
||||
|
||||
public string $token = "switch";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
$context->switchStack[] = true;
|
||||
return "<?php switch($arguments):";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\ControlStructure;
|
||||
|
||||
class UseToken implements ControlStructure {
|
||||
|
||||
public string $token = "use";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
$context->useStack[] = $arguments;
|
||||
return "";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\Extension;
|
||||
|
||||
interface Extension {
|
||||
public function parse(\Picae\Compiler\Context &$context, string $sourceCode);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\Extension;
|
||||
|
||||
class JsonExtension implements Extension {
|
||||
|
||||
public string $token = "json";
|
||||
public int $flags = JSON_HEX_TAG | \JSON_HEX_APOS | \JSON_HEX_QUOT | \JSON_THROW_ON_ERROR;
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, ?string $arguments) {
|
||||
return "<?php echo json_encode($arguments, {$this->flags}) ?>";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Picea;
|
||||
|
||||
class Picea
|
||||
{
|
||||
public Compiler\Context $context;
|
||||
|
||||
public function __construct(?Context $context = null)
|
||||
{
|
||||
$this->context = $context ?? new Compiler\BaseContext();
|
||||
}
|
||||
|
||||
public function compileSource(string $source) : array
|
||||
{
|
||||
return [
|
||||
'context' => $context = clone $this->context,
|
||||
'source' => $this->instanciateCompiler($source)->compile($context)
|
||||
];
|
||||
}
|
||||
|
||||
public function compileFile(string $filePath) : array
|
||||
{
|
||||
if (! file_exists($filePath) ) {
|
||||
throw new \InvalidArgumentException("File `$filePath` cannot be found or it is a permission problem");
|
||||
}
|
||||
|
||||
if ( false === $fileContent = file_get_contents($filePath) ) {
|
||||
throw new \ErrorException("Given file could not be opened `$filePath`. This could indicate a permission misconfiguration on your file or folder");
|
||||
}
|
||||
|
||||
return [
|
||||
'context' => $context = clone $this->context,
|
||||
'source' => $this->instanciateCompiler($fileContent)->compile($context)
|
||||
];
|
||||
}
|
||||
|
||||
public function buildFromSource(string $source) : array
|
||||
{
|
||||
$tmpFolder = sys_get_temp_dir();
|
||||
$builder = $this->instanciateBuilder();
|
||||
$compiledSource = $this->compileSource($source);
|
||||
list($namespace, $className, $compiledSource) = $builder->build($compiledSource['context'], $compiledSource['source']) ;
|
||||
|
||||
$path = "$tmpFolder/$className.php";
|
||||
file_put_contents($path, $compiledSource);
|
||||
|
||||
return [
|
||||
'path' => $path,
|
||||
'namespace' => $namespace,
|
||||
'className' => $className,
|
||||
];
|
||||
}
|
||||
|
||||
public function buildFromPath(string $path) : string
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function instanciateCompiler(string $sourceCode) : Compiler
|
||||
{
|
||||
$compiler = new Compiler();
|
||||
$compiler->loadSourceCode($sourceCode);
|
||||
|
||||
$this->registerSyntax($compiler)
|
||||
->registerControlStructure($compiler)
|
||||
->registerExtension($compiler);
|
||||
|
||||
return $compiler;
|
||||
}
|
||||
|
||||
public function instanciateBuilder() : Builder
|
||||
{
|
||||
$builder = new Builder(dirname(__FILE__) . "/Builder/ClassTemplate.php");
|
||||
return $builder;
|
||||
}
|
||||
|
||||
protected function registerSyntax(Compiler $compiler) : self
|
||||
{
|
||||
$compiler->registerSyntax( new \Picea\Syntax\PhpTagToken() );
|
||||
$compiler->registerSyntax( new \Picea\Syntax\CommentToken() );
|
||||
$compiler->registerSyntax( new \Picea\Syntax\EchoRawToken() );
|
||||
$compiler->registerSyntax( new \Picea\Syntax\EchoSafeToken() );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function registerControlStructure(Compiler $compiler) : self
|
||||
{
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\NamespaceToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\UseToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\IfToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\ElseToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\ElseIfToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\EndIfToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\ForeachToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\ForToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\OrToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\EndforeachToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\EndforToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\SwitchToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\CaseToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\DefaultToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\BreakToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\EndCaseToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\EndSwitchToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\ExtendsToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\SectionToken());
|
||||
$compiler->registerControlStructure(new \Picea\ControlStructure\EndSectionToken());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function registerExtension(Compiler $compiler) : self
|
||||
{
|
||||
$compiler->registerExtension(new \Picea\Extension\JsonExtension());
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\Syntax;
|
||||
|
||||
class CommentToken implements Syntax {
|
||||
|
||||
protected string $tokenOpen = "\{\#";
|
||||
|
||||
protected string $tokenClose = "\#\}";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, string &$sourceCode)
|
||||
{
|
||||
$sourceCode = preg_replace("#({$this->tokenOpen})(.*?)({$this->tokenClose})#s", "", $sourceCode);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\Syntax;
|
||||
|
||||
class EchoRawToken implements Syntax {
|
||||
|
||||
public string $tokenOpen = "\{\{=";
|
||||
|
||||
public string $tokenClose = "\}\}";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$content, string &$sourceCode)
|
||||
{
|
||||
$sourceCode = preg_replace_callback("#({$this->tokenOpen})(.*?)({$this->tokenClose})#s", function ($matches) {
|
||||
return "<?php echo {$matches[2]} ?>";
|
||||
}, $sourceCode);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\Syntax;
|
||||
|
||||
class EchoSafeToken implements Syntax {
|
||||
|
||||
public string $tokenOpen = "\{\{";
|
||||
|
||||
public string $tokenClose = "\}\}";
|
||||
|
||||
public int $flag = \ENT_QUOTES;
|
||||
|
||||
public string $encoding;
|
||||
|
||||
public bool $doubleEncode = true;
|
||||
|
||||
public function __construct() {
|
||||
$this->encoding = ini_get("default_charset");
|
||||
}
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, string &$sourceCode)
|
||||
{
|
||||
$sourceCode = preg_replace_callback("#({$this->tokenOpen})(.*?)({$this->tokenClose})#s", function ($matches) {
|
||||
return "<?php echo htmlspecialchars({$matches[2]}, {$this->flag}, '{$this->encoding}', " . ($this->doubleEncode ? "true" : "false") . ") ?>";
|
||||
}, $sourceCode);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\Syntax;
|
||||
|
||||
class PhpTagToken implements Syntax {
|
||||
|
||||
public string $tokenOpen = "\{\?";
|
||||
|
||||
public string $tokenClose = "\?\}";
|
||||
|
||||
public function parse(/*\Picae\Compiler\Context*/ &$context, string &$sourceCode)
|
||||
{
|
||||
$sourceCode = preg_replace_callback("#({$this->tokenOpen})(.*?)({$this->tokenClose})#s", function ($matches) {
|
||||
return "<?php {$matches[2]} ?>";
|
||||
}, $sourceCode);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Picea\Syntax;
|
||||
|
||||
interface Syntax {
|
||||
public function parse(\Picae\Compiler\Context &$context, string &$sourceCode);
|
||||
}
|
Loading…
Reference in New Issue