summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaria Carolin Chabowski <laria@laria.me>2020-05-01 17:33:13 +0200
committerLaria Carolin Chabowski <laria@laria.me>2020-05-01 17:33:13 +0200
commit7449faaa76a5b4008fd51a6562cca2e0a852ea6b (patch)
tree9e6bc34afe9e4e7d49b1a26f0b67485869b0a9de /src
parentb0c9a4aeb61aff8a8fa60746cd566e6dbe05a3b5 (diff)
downloadste-7449faaa76a5b4008fd51a6562cca2e0a852ea6b.tar.gz
ste-7449faaa76a5b4008fd51a6562cca2e0a852ea6b.tar.bz2
ste-7449faaa76a5b4008fd51a6562cca2e0a852ea6b.zip
Clean up code and improve documentation
This switches the code documentation genarator (we're now using phpdoc instead of NaturalDoc). Also various small code cleanup tasks: - Remove unused code - Get rid of `and` / `or`, we're using `&&` / `||` now - Adding missing return values - Helping PhpStorm to detect some dynamically called functions (mark_builtin_callable in Transcompiler) - Reword transcompiling => compiling in documentation
Diffstat (limited to 'src')
-rw-r--r--src/ste/ASTNode.php8
-rw-r--r--src/ste/Calc.php48
-rw-r--r--src/ste/CantLoadTemplate.php8
-rw-r--r--src/ste/CantSaveTemplate.php8
-rw-r--r--src/ste/FatalRuntimeError.php6
-rw-r--r--src/ste/FilesystemStorageAccess.php28
-rw-r--r--src/ste/Misc.php4
-rw-r--r--src/ste/ParseCompileError.php8
-rw-r--r--src/ste/Parser.php114
-rw-r--r--src/ste/RuntimeError.php8
-rw-r--r--src/ste/STECore.php177
-rw-r--r--src/ste/STEStandardLibrary.php74
-rw-r--r--src/ste/Scope.php39
-rw-r--r--src/ste/StorageAccess.php51
-rw-r--r--src/ste/TagNode.php11
-rw-r--r--src/ste/TextNode.php7
-rw-r--r--src/ste/Transcompiler.php181
-rw-r--r--src/ste/VariableNode.php13
18 files changed, 593 insertions, 200 deletions
diff --git a/src/ste/ASTNode.php b/src/ste/ASTNode.php
index 2163161..3e74635 100644
--- a/src/ste/ASTNode.php
+++ b/src/ste/ASTNode.php
@@ -4,8 +4,16 @@ namespace kch42\ste;
abstract class ASTNode
{
+ /** @var string */
public $tpl;
+
+ /** @var int */
public $offset;
+
+ /**
+ * @param string $tpl
+ * @param int $off
+ */
public function __construct($tpl, $off)
{
$this->tpl = $tpl;
diff --git a/src/ste/Calc.php b/src/ste/Calc.php
index 64d2b7a..2f2d09d 100644
--- a/src/ste/Calc.php
+++ b/src/ste/Calc.php
@@ -2,15 +2,25 @@
namespace kch42\ste;
-/* Class Calc contains static methods needed by <ste:calc /> */
+/**
+ * Class Calc contains static methods needed by <ste:calc />
+ */
class Calc
{
private function __construct()
{
}
- /* We could also just eval() the $infix_math code, but this is much cooler :-D (Parser inception) */
- public static function shunting_yard($infix_math)
+ /**
+ * Parse a mathematical expression with the shunting yard algorithm (https://en.wikipedia.org/wiki/Shunting-yard_algorithm)
+ *
+ * We could also just eval() the $infix_math code, but this is much cooler :-D (Parser inception)
+
+ * @param string $infix_math
+ * @return array
+ * @throws RuntimeError
+ */
+ private static function shunting_yard($infix_math)
{
$operators = array(
"+" => array("l", 2),
@@ -68,11 +78,17 @@ class Calc
} else {
$priority = $operators[$token][1];
if ($operators[$token][0] == "l") {
- while ((!empty($op_stack)) and ($priority <= $operators[$op_stack[count($op_stack)-1]][1])) {
+ while (
+ !empty($op_stack)
+ && $priority <= $operators[$op_stack[count($op_stack)-1]][1]
+ ) {
$output_queue[] = array_pop($op_stack);
}
} else {
- while ((!empty($op_stack)) and ($priority < $operators[$op_stack[count($op_stack)-1]][1])) {
+ while (
+ !empty($op_stack)
+ && $priority < $operators[$op_stack[count($op_stack)-1]][1]
+ ) {
$output_queue[] = array_pop($op_stack);
}
}
@@ -91,7 +107,12 @@ class Calc
return $output_queue;
}
- public static function pop2(&$array)
+ /**
+ * @param array $array
+ * @return array
+ * @throws RuntimeError
+ */
+ private static function pop2(&$array)
{
$rv = array(array_pop($array), array_pop($array));
if (array_search(null, $rv, true) !== false) {
@@ -100,7 +121,12 @@ class Calc
return $rv;
}
- public static function calc_rpn($rpn)
+ /**
+ * @param array $rpn A mathematical expression in reverse polish notation
+ * @return int|float
+ * @throws RuntimeError
+ */
+ private static function calc_rpn($rpn)
{
$stack = array();
foreach ($rpn as $token) {
@@ -140,6 +166,14 @@ class Calc
return array_pop($stack);
}
+ /**
+ * Calculate a simple mathematical expression. Supported operators are +, -, *, /, ^.
+ * You can use ( and ) to group expressions together.
+ *
+ * @param string $expr
+ * @return float|int
+ * @throws RuntimeError
+ */
public static function calc($expr)
{
return self::calc_rpn(self::shunting_yard($expr));
diff --git a/src/ste/CantLoadTemplate.php b/src/ste/CantLoadTemplate.php
index 20200d6..92604cc 100644
--- a/src/ste/CantLoadTemplate.php
+++ b/src/ste/CantLoadTemplate.php
@@ -1,13 +1,9 @@
<?php
-// File: CantLoadTemplate.php
-
-// Namespace: kch42\ste
namespace kch42\ste;
-/*
- * Class: CantLoadTemplate
- * An exception that a <StorageAccess> implementation can throw, if it is unable to load a template.
+/**
+ * An exception that a {@see StorageAccess} implementation can throw, if it is unable to load a template.
*/
class CantLoadTemplate extends StorageAccessFailure
{
diff --git a/src/ste/CantSaveTemplate.php b/src/ste/CantSaveTemplate.php
index edbb93e..92cdfe7 100644
--- a/src/ste/CantSaveTemplate.php
+++ b/src/ste/CantSaveTemplate.php
@@ -1,13 +1,9 @@
<?php
-// File: CantSaveTemplate.php
-
-// Namespace: kch42\ste
namespace kch42\ste;
-/*
- * Class: CantSaveTemplate
- * An exception that a <StorageAccess> implementation can throw, if it is unable to save a template.
+/**
+ * An exception that a {@see StorageAccess} implementation can throw, if it is unable to save a template.
*/
class CantSaveTemplate extends StorageAccessFailure
{
diff --git a/src/ste/FatalRuntimeError.php b/src/ste/FatalRuntimeError.php
index ab40af5..3f5183f 100644
--- a/src/ste/FatalRuntimeError.php
+++ b/src/ste/FatalRuntimeError.php
@@ -1,12 +1,8 @@
<?php
-// File: FatalRuntimeError.php
-
-// Namespace: kch42\ste
namespace kch42\ste;
-/*
- * Class: FatalRuntimeError
+/**
* An Exception a tag can throw, if a fatal (irreparable) runtime error occurred.
* This Exception will always "bubble up" so you probably want to catch them. Remember that this exception is also in the namespace ste!
*/
diff --git a/src/ste/FilesystemStorageAccess.php b/src/ste/FilesystemStorageAccess.php
index d477e36..cb2fe7f 100644
--- a/src/ste/FilesystemStorageAccess.php
+++ b/src/ste/FilesystemStorageAccess.php
@@ -1,25 +1,21 @@
<?php
-// File: FilesystemStorageAccess.php
-
-// Namespace: kch42\ste
namespace kch42\ste;
-/*
- * Class: FilesystemStorageAccess
- * The default <StorageAccess> implementation for loading / saving templates into a directory structure.
+/**
+ * The default {@see StorageAccess} implementation for loading / saving templates into a directory structure.
*/
class FilesystemStorageAccess implements StorageAccess
{
+ /** @var string */
protected $sourcedir;
+
+ /** @var string */
protected $transcompileddir;
- /*
- * Constructor: __construct
- *
- * Parameters:
- * $src - The directory with the sources (Writing permissions are not mandatory, because STE does not save template sources).
- * $transc - The directory with the transcompiled templates (the PHP instance / the HTTP Server needs writing permissions to this directory).
+ /**
+ * @param string $src - The directory with the sources (Writing permissions are not mandatory, because STE does not save template sources).
+ * @param string $transc - The directory with the compiled templates (the PHP instance / the HTTP Server needs writing permissions to this directory).
*/
public function __construct($src, $transc)
{
@@ -43,13 +39,16 @@ class FilesystemStorageAccess implements StorageAccess
$src_stat = @stat($src_fn);
$transc_stat = @stat($transc_fn);
- if (($src_stat === false) and ($transc_stat === false)) {
+ if ($src_stat === false && $transc_stat === false) {
throw new CantLoadTemplate("Template not found.");
} elseif ($transc_stat === false) {
$mode = StorageAccess::MODE_SOURCE;
return file_get_contents($src_fn);
} elseif ($src_stat === false) {
include($transc_fn);
+ if (!isset($transcompile_fx)) {
+ throw new CantLoadTemplate("Compiled template file $transc_fn does not set \$transcompile_fx");
+ }
return $transcompile_fx;
} else {
if ($src_stat["mtime"] > $transc_stat["mtime"]) {
@@ -57,6 +56,9 @@ class FilesystemStorageAccess implements StorageAccess
return file_get_contents($src_fn);
} else {
include($transc_fn);
+ if (!isset($transcompile_fx)) {
+ throw new CantLoadTemplate("Compiled template file $transc_fn does not set \$transcompile_fx");
+ }
return $transcompile_fx;
}
}
diff --git a/src/ste/Misc.php b/src/ste/Misc.php
index d017ee3..330b3d2 100644
--- a/src/ste/Misc.php
+++ b/src/ste/Misc.php
@@ -4,6 +4,10 @@ namespace kch42\ste;
class Misc
{
+ /**
+ * @param string $text
+ * @return string
+ */
public static function escape_text($text)
{
return addcslashes($text, "\r\n\t\$\0..\x1f\\\"\x7f..\xff");
diff --git a/src/ste/ParseCompileError.php b/src/ste/ParseCompileError.php
index f5f0272..29590da 100644
--- a/src/ste/ParseCompileError.php
+++ b/src/ste/ParseCompileError.php
@@ -2,6 +2,9 @@
namespace kch42\ste;
+/**
+ * An exception thrown by the parser or compiler
+ */
class ParseCompileError extends \Exception
{
public $msg;
@@ -16,10 +19,13 @@ class ParseCompileError extends \Exception
$this->message = "$msg (Template $tpl, Offset $offset)";
}
+ /**
+ * Update the message to include a human readable offset.
+ * @param string $code
+ */
public function rewrite($code)
{
$line = substr_count(str_replace("\r\n", "\n", substr($code, 0, $this->off)), "\n") + 1;
$this->message = "{$this->msg} (Template {$this->tpl}, Line $line)";
- $this->is_rewritten = true;
}
}
diff --git a/src/ste/Parser.php b/src/ste/Parser.php
index 40f5f20..0280f6d 100644
--- a/src/ste/Parser.php
+++ b/src/ste/Parser.php
@@ -1,20 +1,25 @@
<?php
-// File: Parser.php
-
-// Namespace: kch42\ste
namespace kch42\ste;
-/*
- * Class: Parser
+use LogicException;
+
+/**
* The class, where the parser lives in. Can not be constructed manually.
* Use the static method parse.
*/
class Parser
{
+ /** @var string */
private $text;
+
+ /** @var string */
private $name;
+
+ /** @var int */
private $off;
+
+ /** @var int */
private $len;
const PARSE_SHORT = 1;
@@ -22,6 +27,10 @@ class Parser
const ESCAPES_DEFAULT = '$?~{}|\\';
+ /**
+ * @param string $text
+ * @param string $name
+ */
private function __construct($text, $name)
{
$this->text = $text;
@@ -30,6 +39,10 @@ class Parser
$this->len = mb_strlen($text);
}
+ /**
+ * @param int $n
+ * @return string
+ */
private function next($n = 1)
{
if ($n <= 0) {
@@ -40,11 +53,17 @@ class Parser
return $c;
}
+ /**
+ * @return bool
+ */
private function eof()
{
return ($this->off == $this->len);
}
+ /**
+ * @param int $n
+ */
private function back($n = 1)
{
if ($n <= 0) {
@@ -53,11 +72,19 @@ class Parser
$this->off = max($this->off - $n, 0);
}
+ /**
+ * @param string $needle
+ * @return false|int
+ */
private function search_off($needle)
{
return mb_strpos($this->text, $needle, $this->off);
}
+ /**
+ * @param string[] $needles
+ * @return array 4-tuple of found key, offset, text preceding offset, old offset
+ */
private function search_multi($needles)
{
$oldoff = $this->off;
@@ -81,6 +108,10 @@ class Parser
return array($which, $minoff, mb_substr($this->text, $oldoff, $minoff - $oldoff), $oldoff);
}
+ /**
+ * @param string $needle
+ * @return array 3-tuple of offset (or false), text preceding offset, old offset
+ */
private function search($needle)
{
$oldoff = $this->off;
@@ -95,7 +126,11 @@ class Parser
return array($off, mb_substr($this->text, $oldoff, $off - $oldoff), $oldoff);
}
- private function take_while($cb)
+ /**
+ * @param callable $cb
+ * @return string
+ */
+ private function take_while(callable $cb)
{
$s = "";
while (($c = $this->next()) !== "") {
@@ -113,6 +148,10 @@ class Parser
$this->take_while("ctype_space");
}
+ /**
+ * @return string
+ * @throws ParseCompileError
+ */
private function get_name()
{
$off = $this->off;
@@ -125,21 +164,16 @@ class Parser
return $name;
}
- /*
- * Function: parse
+ /**
* Parses the input into an AST.
*
- * You only need this function, if you want to manually trnascompile a template.
+ * You only need this function, if you want to manually compile a template.
*
- * Parameters:
- * $text - The input code.
- * $name - The name of the template.
+ * @param string $text The input code.
+ * @param string $name The name of the template.
*
- * Returns:
- * An array of <ASTNode> objects.
- *
- * Throws:
- * <ParseCompileError>
+ * @return ASTNode[]
+ * @throws ParseCompileError
*/
public static function parse($text, $name)
{
@@ -151,10 +185,15 @@ class Parser
return self::tidyup_ast($res[0]);
}
+ /**
+ * @param ASTNode[] $ast
+ * @return ASTNode[]
+ */
private static function tidyup_ast($ast)
{
$out = array();
+ /** @var TextNode|null $prevtext */
$prevtext = null;
$first = true;
@@ -206,6 +245,17 @@ class Parser
return $out;
}
+ /**
+ * @param string $escapes
+ * @param int $flags
+ * @param string|null $breakon
+ * @param string|null $separator
+ * @param null $nullaction
+ * @param string|null $opentag
+ * @param int $openedat
+ * @return ASTNode[][]
+ * @throws ParseCompileError
+ */
private function parse_text($escapes, $flags, $breakon = null, $separator = null, $nullaction = null, $opentag = null, $openedat = -1)
{
$elems = array();
@@ -250,14 +300,14 @@ class Parser
}
break;
case "commentopen":
- list($off, $before, $offbefore) = $this->search("</ste:comment>");
+ list($off, , $offbefore) = $this->search("</ste:comment>");
if ($off === false) {
throw new ParseCompileError("ste:comment was not closed", $this->name, $offbefore);
}
break;
case "rawopen":
$off_start = $off;
- list($off, $before, $offbefore) = $this->search("</ste:rawtext>");
+ list($off, $before, ) = $this->search("</ste:rawtext>");
if ($off === false) {
throw new ParseCompileError("ste:rawtext was not closed", $this->name, $off_start);
}
@@ -352,6 +402,12 @@ class Parser
return $elems;
}
+ /**
+ * @param string $shortname
+ * @param int $openedat
+ * @return ASTNode[][]
+ * @throws ParseCompileError
+ */
private function parse_short($shortname, $openedat)
{
$tplname = $this->name;
@@ -369,6 +425,12 @@ class Parser
);
}
+ /**
+ * @param int $openedat
+ * @param bool $curly
+ * @return VariableNode
+ * @throws ParseCompileError
+ */
private function parse_var($openedat, $curly)
{
$varnode = new VariableNode($this->name, $openedat);
@@ -377,12 +439,16 @@ class Parser
$varnode->arrayfields = $this->parse_array();
}
- if (($curly) && ($this->next() != "}")) {
+ if ($curly && ($this->next() != "}")) {
throw new ParseCompileError("Unclosed '\${'", $this->name, $openedat);
}
return $varnode;
}
+ /**
+ * @return ASTNode[]
+ * @throws ParseCompileError
+ */
private function parse_array()
{
$tplname = $this->name;
@@ -409,6 +475,11 @@ class Parser
return $arrayfields;
}
+ /**
+ * @param int $openedat
+ * @return TagNode
+ * @throws ParseCompileError
+ */
private function parse_tag($openedat)
{
$tplname = $this->name;
@@ -475,5 +546,8 @@ class Parser
$tag->params[$param] = $paramval[0];
}
}
+
+ // Help PhpStorm detect that we shouldn't be here
+ throw new LogicException("Somehow we left the infinite loop?");
}
}
diff --git a/src/ste/RuntimeError.php b/src/ste/RuntimeError.php
index dace1d4..51fd29d 100644
--- a/src/ste/RuntimeError.php
+++ b/src/ste/RuntimeError.php
@@ -1,14 +1,10 @@
<?php
-// File: RuntimeError.php
-
-// Namespace: kch42\ste
namespace kch42\ste;
-/*
- * Class: RuntimeError
+/**
* An Exception that a tag can throw, if a non-fatal runtime error occurred.
- * By default this will return in no output at all. But if <STECore::$mute_runtime_errors> is false, this will generate a error message instead of the tag's output.
+ * By default this will return in no output at all. But if {@see STECore::$mute_runtime_errors} is false, this will generate a error message instead of the tag's output.
*/
class RuntimeError extends \Exception
{
diff --git a/src/ste/STECore.php b/src/ste/STECore.php
index 13fb2f6..40d680a 100644
--- a/src/ste/STECore.php
+++ b/src/ste/STECore.php
@@ -1,43 +1,64 @@
<?php
-// File: STECore.php
-
-// Namespace: kch42\ste
namespace kch42\ste;
-/*
- * Class: STECore
+use Exception;
+
+/**
* The Core of STE
*/
class STECore
{
+ /** @var callable[] */
private $tags;
+
+ /** @var StorageAccess */
private $storage_access;
+
+ /** @var string */
private $cur_tpl_dir;
+
+ /** @var Scope */
public $scope;
- /*
- * Variables: Public variables
- *
- * $blocks - Associative array of blocks (see the language definition).
- * $blockorder - The order of the blocks (an array)
- * $mute_runtime_errors - If true (default) a <RuntimeError> exception will result in no output from the tag, if false a error message will be written to output.
- * $fatal_error_on_missing_tag - If true, STE will throw a <FatalRuntimeError> if a tag was called that was not registered, otherwise (default) a regular <RuntimeError> will be thrown and automatically handled by STE (see <$mute_runtime_errors>).
- * $vars - Variables in the top scope of the template.
+ /**
+ * @var array
+ * Associative array of blocks (see the language definition).
*/
public $blocks;
+
+ /**
+ * @var array
+ * The order of the blocks (an array)
+ */
public $blockorder;
+
+ /**
+ * @var bool
+ * If true (default) a {@see RuntimeError} exception will result in no
+ * output from the tag, if false a error message will be written to output.
+ */
public $mute_runtime_errors = true;
+
+ /**
+ * @var bool
+ * If true, STE will throw a {@see FatalRuntimeError} if a tag was called
+ * that was not registered, otherwise (default) a regular
+ * {@see RuntimeError} will be thrown and automatically handled by STE
+ * (see {@see STECore::$mute_runtime_errors}).
+ */
public $fatal_error_on_missing_tag = false;
+
+ /**
+ * @var array
+ * Variables in the top scope of the template.
+ */
public $vars;
- /*
- * Constructor: __construct
- *
- * Parameters:
- * $storage_access - An Instance of a <StorageAccess> implementation.
+ /**
+ * @param StorageAccess $storage_access
*/
- public function __construct($storage_access)
+ public function __construct(StorageAccess $storage_access)
{
$this->storage_access = $storage_access;
$this->cur_tpl_dir = "/";
@@ -50,42 +71,47 @@ class STECore
$this->scope->vars =& $this->vars;
}
- /*
- * Function: register_tag
+ /**
* Register a custom tag.
*
* Parameters:
- * $name - The name of the tag.
- * $callback - A callable function (This must take three parameters: The <STECore> instance, an associative array of parameters, and a function representing the tags content(This expects the <STECore> instance as its only parameter and returns its text result, i.e to get the text, you neeed to call this function with the <STECore> instance as a parameter)).
+ * @param string $name The name of the tag.
+ * @param callable $callback A callable function
+ * Must take three parameters:
*
- * Throws:
- * An Exception if the tag could not be registered (if $callback is not callable or if $name is empty)
+ * The {@see STECore} instance,
+ * an associative array of parameters,
+ * and a function representing the tags content
+ * (This expects the {@see STECore} instance as
+ * its only parameter and returns its text result,
+ * i.e to get the text, you need to call this
+ * function with the {@see STECore} instance as a
+ * parameter).
+ *
+ * @throws Exception If the tag could not be registered (if $callback is not callable or if $name is empty)
*/
public function register_tag($name, $callback)
{
if (!is_callable($callback)) {
- throw new \Exception("Can not register tag \"$name\", not callable.");
+ throw new Exception("Can not register tag \"$name\", not callable.");
}
if (empty($name)) {
- throw new \Exception("Can not register tag, empty name.");
+ throw new Exception("Can not register tag, empty name.");
}
$this->tags[$name] = $callback;
}
- /*
- * Function: call_tag
+ /**
* Calling a custom tag (builtin ones can not be called)
*
- * Parameters:
- * $name - The Tag's name
- * $params - Associative array of parameters
- * $sub - A callable function (expecting an <STECore> instance as it's parameter) that represents the tag's content.
+ * @param string $name The Tag's name
+ * @param array $params Associative array of parameters
+ * @param callable $sub A callable function (expecting an {@see STECore} instance as it's parameter) that represents the tag's content.
*
- * Throws:
- * Might throw a <FatalRuntimeError> (see <$fatal_error_on_missing_tag>.
+ * @throws FatalRuntimeError see {@see STECore::$fatal_error_on_missing_tag}.
*
- * Returns:
- * The output of the tag or, if a <RuntimeError> was thrown, the appropiate result (see <$mute_runtime_errors>).
+ * @return string The output of the tag or, if a {@see RuntimeError} was thrown, the appropriate result
+ * (see {@see STECore::$mute_runtime_errors}).
*/
public function call_tag($name, $params, $sub)
{
@@ -103,28 +129,37 @@ class STECore
return "RuntimeError occurred on tag '$name': " . $e->getMessage();
}
}
+
+ return "";
}
+ /**
+ * {@see Calc::calc()}
+ *
+ * @param string $expression
+ * @return float|int
+ * @throws RuntimeError
+ */
public function calc($expression)
{
return Calc::calc($expression);
}
- /*
- * Function: exectemplate
- * Executes a template and returns the result. The huge difference to <load> is that this function will also output all blocks.
+ /**
+ * Executes a template and returns the result.
*
- * Parameters:
- * $tpl - The name of the template to execute.
+ * The huge difference to {@see STECore::load()} is that this function will also output all blocks.
*
- * Throws:
- * * A <CantLoadTemplate> exception if the template could not be loaded.
- * * A <ParseCompileError> if the template could not be parsed or transcompiled.
- * * A <FatalRuntimeError> if a tag threw it or if a tag was not found and <$fatal_error_on_missing_tag> is true.
- * * Might also throw different exceptions, if a external tag threw it (but they should use <RuntimeError> or <FatalRuntimeError> to make it possible for STE to handle them correctly).
+ * @param string $tpl The name of the template to execute.
*
- * Returns:
- * The output of the template.
+ * @throws CantLoadTemplate If the template could not be loaded.
+ * @throws ParseCompileError If the template could not be parsed or compiled.
+ * @throws FatalRuntimeError If a tag threw it or if a tag was not found and <$fatal_error_on_missing_tag> is true.
+ *
+ * Might also throw different exceptions, if a external tag threw it
+ * (but they should use {@see RuntimeError} or {@see FatalRuntimeError} to make it possible for STE to handle them correctly).
+ *
+ * @return string The output of the template.
*/
public function exectemplate($tpl)
{
@@ -211,22 +246,21 @@ class STECore
return $this->scope->get_var_by_name($name);
}
- /*
- * Function: load
- * Load a template and return its result (blocks not included, use <exectemplate> for this).
+ /**
+ * Load a template and return its result (blocks not included, use {@see STECore::exectemplate} for this).
*
- * Parameters:
- * $tpl - The name of the template to be loaded.
- * $quiet - If true, do not output anything and do not modify the blocks. This can be useful to load custom tags that are programmed in the STE Template Language. Default: false.
+ * @param string $tpl The name of the template to be loaded.
+ * @param bool $quiet If true, do not output anything and do not modify the blocks. This can be useful to load custom tags that are programmed in the STE Template Language. Default: false.
*
- * Throws:
- * * A <CantLoadTemplate> exception if the template could not be loaded.
- * * A <ParseCompileError> if the template could not be parsed or transcompiled.
- * * A <FatalRuntimeError> if a tag threw it or if a tag was not found and <$fatal_error_on_missing_tag> is true.
- * * Might also throw different exceptions, if a external tag threw it (but they should use <RuntimeError> or <FatalRuntimeError> to make it possible for STE to handle them correctly).
+ * @throws CantLoadTemplate If the template could not be loaded.
+ * @throws CantSaveTemplate If the template could not be saved.
+ * @throws ParseCompileError If the template could not be parsed or compiled.
+ * @throws FatalRuntimeError If a tag threw it or if a tag was not found and {@see STECore::$fatal_error_on_missing_tag} is true.
*
- * Returns:
- * The result of the template (if $quiet == false).
+ * Might also throw different exceptions, if a external tag threw it
+ * (but they should use {@see RuntimeError} or {@see FatalRuntimeError} to make it possible for STE to handle them correctly).
+ *
+ * @return string|null The result of the template (if $quiet == false).
*/
public function load($tpl, $quiet = false)
{
@@ -238,7 +272,7 @@ class STECore
$tpl = $this->cur_tpl_dir . "/" . $tpl;
}
$pathex = array_filter(explode("/", $tpl), function ($s) {
- return ($s != ".") and (!empty($s));
+ return $s != "." && !empty($s);
});
$pathex = array_merge($pathex);
while (($i = array_search("..", $pathex)) !== false) {
@@ -277,26 +311,31 @@ class STECore
if ($quiet) {
$this->blocks = $blocks_back;
$this->blockorder = $blockorder_back;
+
+ return null;
} else {
return $output;
}
}
/*
- * Function: evalbool
* Test, if a text represents false (an empty / only whitespace text) or true (everything else).
*
- * Parameters:
- * $txt - The text to test.
+ * @param string $txt The text to test.
*
- * Returns:
- * true/false.
+ * @return bool
*/
public function evalbool($txt)
{
return trim(@(string)$txt) != "";
}
+ /**
+ * Internal function for implementing tag content and custom tags.
+ *
+ * @param callable $fx
+ * @return \Closure
+ */
public function make_closure($fx)
{
$bound_scope = $this->scope;
@@ -312,7 +351,7 @@ class STECore
$result = call_user_func_array($fx, $args);
$ste->scope = $prev;
return $result;
- } catch (\Exception $e) {
+ } catch (Exception $e) {
$ste->scope = $prev;
throw $e;
}
diff --git a/src/ste/STEStandardLibrary.php b/src/ste/STEStandardLibrary.php
index 9850afe..e39b7af 100644
--- a/src/ste/STEStandardLibrary.php
+++ b/src/ste/STEStandardLibrary.php
@@ -13,6 +13,12 @@ class STEStandardLibrary
}
}
+ /**
+ * @param STECore $ste
+ * @param array $params
+ * @param callable $sub
+ * @return string
+ */
public static function escape($ste, $params, $sub)
{
if ($ste->evalbool(@$params["lines"])) {
@@ -22,11 +28,24 @@ class STEStandardLibrary
}
}
+ /**
+ * @param STECore $ste
+ * @param array $params
+ * @param callable $sub
+ * @return string
+ */
public static function strlen($ste, $params, $sub)
{
return strlen($sub($ste));
}
+ /**
+ * @param STECore $ste
+ * @param array $params
+ * @param callable $sub
+ * @return string
+ * @throws RuntimeError
+ */
public static function arraylen($ste, $params, $sub)
{
if (empty($params["array"])) {
@@ -36,6 +55,13 @@ class STEStandardLibrary
return (is_array($a)) ? count($a) : "";
}
+ /**
+ * @param STECore $ste
+ * @param array $params
+ * @param callable $sub
+ * @return string
+ * @throws RuntimeError
+ */
public static function inc($ste, $params, $sub)
{
if (empty($params["var"])) {
@@ -45,6 +71,13 @@ class STEStandardLibrary
$ref++;
}
+ /**
+ * @param STECore $ste
+ * @param array $params
+ * @param callable $sub
+ * @return string
+ * @throws RuntimeError
+ */
public static function dec($ste, $params, $sub)
{
if (empty($params["var"])) {
@@ -54,11 +87,24 @@ class STEStandardLibrary
$ref--;
}
+ /**
+ * @param STECore $ste
+ * @param array $params
+ * @param callable $sub
+ * @return string
+ */
public static function date($ste, $params, $sub)
{
return @strftime($sub($ste), empty($params["timestamp"]) ? @time() : (int) $params["timestamp"]);
}
+ /**
+ * @param STECore $ste
+ * @param array $params
+ * @param callable $sub
+ * @return string
+ * @throws RuntimeError
+ */
public static function in_array($ste, $params, $sub)
{
if (empty($params["array"])) {
@@ -71,6 +117,13 @@ class STEStandardLibrary
return in_array($sub($ste), $ar) ? "y" : "";
}
+ /**
+ * @param STECore $ste
+ * @param array $params
+ * @param callable $sub
+ * @return string
+ * @throws RuntimeError
+ */
public static function join($ste, $params, $sub)
{
if (empty($params["array"])) {
@@ -79,6 +132,13 @@ class STEStandardLibrary
return implode($sub($ste), $ste->get_var_by_name($params["array"]));
}
+ /**
+ * @param STECore $ste
+ * @param array $params
+ * @param callable $sub
+ * @return string
+ * @throws RuntimeError
+ */
public static function split($ste, $params, $sub)
{
if (empty($params["array"])) {
@@ -90,6 +150,13 @@ class STEStandardLibrary
$ste->set_var_by_name($params["array"], explode($params["delim"], $sub($ste)));
}
+ /**
+ * @param STECore $ste
+ * @param array $params
+ * @param callable $sub
+ * @return string
+ * @throws RuntimeError
+ */
public static function array_add($ste, $params, $sub)
{
if (empty($params["array"])) {
@@ -104,6 +171,13 @@ class STEStandardLibrary
}
}
+ /**
+ * @param STECore $ste
+ * @param array $params
+ * @param callable $sub
+ * @return string
+ * @throws RuntimeError
+ */
public static function array_filter($ste, $params, $sub)
{
if (empty($params["array"])) {
diff --git a/src/ste/Scope.php b/src/ste/Scope.php
index e312876..afb2bfc 100644
--- a/src/ste/Scope.php
+++ b/src/ste/Scope.php
@@ -4,9 +4,17 @@ namespace kch42\ste;
class Scope implements \ArrayAccess
{
+ /** @var self|null */
private $parent = null;
+
+ /** @var array */
public $vars = array();
+ /**
+ * @param string $name
+ * @return string[]
+ * @throws RuntimeError
+ */
private static function parse_name($name)
{
$remain = $name;
@@ -44,6 +52,12 @@ class Scope implements \ArrayAccess
return $fields;
}
+ /**
+ * @param string $name
+ * @param bool $localonly
+ * @return mixed A reference to the resolved variable
+ * @throws VarNotInScope
+ */
private function &get_topvar_reference($name, $localonly)
{
if (array_key_exists($name, $this->vars)) {
@@ -59,6 +73,13 @@ class Scope implements \ArrayAccess
throw new VarNotInScope();
}
+ /**
+ * @param string $name
+ * @param bool $create_if_not_exist
+ * @param bool $localonly
+ * @return mixed A reference to the resolved variable
+ * @throws RuntimeError
+ */
public function &get_var_reference($name, $create_if_not_exist, $localonly=false)
{
$nullref = null;
@@ -107,24 +128,42 @@ class Scope implements \ArrayAccess
return $ref;
}
+ /**
+ * @param string $name
+ * @param mixed $val
+ * @throws RuntimeError
+ */
public function set_var_by_name($name, $val)
{
$ref = &$this->get_var_reference($name, true);
$ref = $val;
}
+ /**
+ * @param string $name
+ * @param mixed $val
+ * @throws RuntimeError
+ */
public function set_local_var($name, $val)
{
$ref = &$this->get_var_reference($name, true, true);
$ref = $val;
}
+ /**
+ * @param string $name
+ * @return mixed Returns an empty string, if not found or unset
+ * @throws RuntimeError
+ */
public function get_var_by_name($name)
{
$ref = $this->get_var_reference($name, false);
return $ref === null ? "" : $ref;
}
+ /**
+ * @return self
+ */
public function new_subscope()
{
$o = new self();
diff --git a/src/ste/StorageAccess.php b/src/ste/StorageAccess.php
index e2e8727..38dea7e 100644
--- a/src/ste/StorageAccess.php
+++ b/src/ste/StorageAccess.php
@@ -1,56 +1,45 @@
<?php
-// File: StorageAccess.php
-
-// Namespace: kch42\ste
namespace kch42\ste;
-/*
- * Class: StorageAccess
- * An interface.
+/**
* A StorageAccess implementation is used to access the templates from any storage.
* This means, that you are not limited to store the Templates inside directories, you can also use a database or something else.
*/
interface StorageAccess
{
- /*
- * Constants: Template modes
- *
- * MODE_SOURCE - The Templates source
- * MODE_TRANSCOMPILED - The transcompiled template
- */
+ /** @var int The template's source */
const MODE_SOURCE = 0;
+
+ /** @var int The compiled template */
const MODE_TRANSCOMPILED = 1;
- /*
- * Function: load
+ /**
* Loading a template.
*
- * Parameters:
- * $tpl - The name of the template.
- * &$mode - Which mode is preferred? One of the <Template modes>.
- * If <MODE_SOURCE>, the raw sourcecode is expected, if <MODE_TRANSCOMPILED> the transcompiled template *as a callable function* (expecting an <STECore> instance as first parameter) is expected.
- * If the transcompiled version is not available or older than the source, you can set this parameter to <MODE_SOURCE> and return the source.
+ * @param string $tpl The name of the template.
+ * @param string &$mode Which mode is preferred? One of the MODE_* constants.
+ * If {@see StorageAccess::MODE_SOURCE}, the raw sourcecode is expected,
+ * if {@see StorageAccess::MODE_TRANSCOMPILED} the compiled template
+ * *as a callable function* (expecting an {@see STECore} instance as first parameter) is expected.
+ *
+ * If the compiled version is not available or older than the source, you can set this
+ * parameter to {@see StorageAccess::MODE_SOURCE} and return the source.
*
- * Throws:
- * A <CantLoadTemplate> exception if the template could not be loaded.
+ * @throws CantLoadTemplate If the template could not be loaded.
*
- * Returns:
- * Either the sourcecode or a callable function (first, and only parameter: an <STECore> instance).
+ * @return string|callable Either the sourcecode or a callable function (first, and only parameter: an {@see STECore} instance).
*/
public function load($tpl, &$mode);
- /*
- * Function: save
+ /**
* Saves a template.
*
- * Throws:
- * A <CantSaveTemplate> exception if the template could not be saved.
+ * @param string $tpl -The name of the template.
+ * @param string $data - The data to be saved.
+ * @param int $mode - One of the MODE_* constants.
*
- * Parameters:
- * $tpl -The name of the template.
- * $data - The data to be saved.
- * $mode - A <Template mode> constant.
+ * @throws CantSaveTemplate If the template could not be saved.
*/
public function save($tpl, $data, $mode);
}
diff --git a/src/ste/TagNode.php b/src/ste/TagNode.php
index c1a14e5..18567b2 100644
--- a/src/ste/TagNode.php
+++ b/src/ste/TagNode.php
@@ -4,9 +4,20 @@ namespace kch42\ste;
class TagNode extends ASTNode
{
+ /** @var string */
public $name;
+
+ /** @var ASTNode[][] */
public $params = array();
+
+ /** @var ASTNode[] */
public $sub = array();
+
+ /**
+ * @param string $tpl
+ * @param int $off
+ * @param string $name
+ */
public function __construct($tpl, $off, $name = "")
{
parent::__construct($tpl, $off);
diff --git a/src/ste/TextNode.php b/src/ste/TextNode.php
index c68dd2f..199c203 100644
--- a/src/ste/TextNode.php
+++ b/src/ste/TextNode.php
@@ -4,7 +4,14 @@ namespace kch42\ste;
class TextNode extends ASTNode
{
+ /** @var string */
public $text;
+
+ /**
+ * @param string $tpl
+ * @param int $off
+ * @param string $text
+ */
public function __construct($tpl, $off, $text = "")
{
parent::__construct($tpl, $off);
diff --git a/src/ste/Transcompiler.php b/src/ste/Transcompiler.php
index d223b53..88c008e 100644
--- a/src/ste/Transcompiler.php
+++ b/src/ste/Transcompiler.php
@@ -1,13 +1,9 @@
<?php
-// File: Transcompiler.php
-
-// Namespace: kch42\ste
namespace kch42\ste;
-/*
- * Class: Transcompiler
- * Contains the STE transcompiler. You'll only need this, if you want to manually transcompile a STE template.
+/**
+ * Contains the STE compiler. You'll only need this, if you want to manually compile a STE template.
*/
class Transcompiler
{
@@ -18,33 +14,44 @@ class Transcompiler
return $typ . '_' . str_replace('.', '_', uniqid('', true));
}
+ private static function mark_builtin_callable(callable $c)
+ {
+ return $c;
+ }
+
public static function init_builtins()
{
if (self::$builtins !== null) {
return;
}
+ /** @var callable[] builtins */
self::$builtins = array(
- "if" => array("\\kch42\\ste\\Transcompiler", "builtin_if"),
- "cmp" => array("\\kch42\\ste\\Transcompiler", "builtin_cmp"),
- "not" => array("\\kch42\\ste\\Transcompiler", "builtin_not"),
- "even" => array("\\kch42\\ste\\Transcompiler", "builtin_even"),
- "for" => array("\\kch42\\ste\\Transcompiler", "builtin_for"),
- "foreach" => array("\\kch42\\ste\\Transcompiler", "builtin_foreach"),
- "infloop" => array("\\kch42\\ste\\Transcompiler", "builtin_infloop"),
- "break" => array("\\kch42\\ste\\Transcompiler", "builtin_break"),
- "continue" => array("\\kch42\\ste\\Transcompiler", "builtin_continue"),
- "block" => array("\\kch42\\ste\\Transcompiler", "builtin_block"),
- "load" => array("\\kch42\\ste\\Transcompiler", "builtin_load"),
- "mktag" => array("\\kch42\\ste\\Transcompiler", "builtin_mktag"),
- "tagcontent" => array("\\kch42\\ste\\Transcompiler", "builtin_tagcontent"),
- "set" => array("\\kch42\\ste\\Transcompiler", "builtin_set"),
- "setlocal" => array("\\kch42\\ste\\Transcompiler", "builtin_setlocal"),
- "get" => array("\\kch42\\ste\\Transcompiler", "builtin_get"),
- "calc" => array("\\kch42\\ste\\Transcompiler", "builtin_calc")
+ "if" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_if")),
+ "cmp" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_cmp")),
+ "not" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_not")),
+ "even" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_even")),
+ "for" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_for")),
+ "foreach" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_foreach")),
+ "infloop" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_infloop")),
+ "break" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_break")),
+ "continue" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_continue")),
+ "block" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_block")),
+ "load" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_load")),
+ "mktag" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_mktag")),
+ "tagcontent" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_tagcontent")),
+ "set" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_set")),
+ "setlocal" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_setlocal")),
+ "get" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_get")),
+ "calc" => self::mark_builtin_callable(array("\\kch42\\ste\\Transcompiler", "builtin_calc"))
);
}
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_if($ast)
{
$output = "";
@@ -53,9 +60,9 @@ class Transcompiler
$else = null;
foreach ($ast->sub as $node) {
- if (($node instanceof TagNode) and ($node->name == "then")) {
+ if (($node instanceof TagNode) && $node->name == "then") {
$then = $node->sub;
- } elseif (($node instanceof TagNode) and ($node->name == "else")) {
+ } elseif (($node instanceof TagNode) && $node->name == "else") {
$else = $node->sub;
} else {
$condition[] = $node;
@@ -78,6 +85,12 @@ class Transcompiler
}
return $output;
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_cmp($ast)
{
$operators = array(
@@ -116,7 +129,10 @@ class Transcompiler
if (!isset($ast->params["op"])) {
throw new ParseCompileError("self::Transcompile error: op not given in <ste:cmp>.", $ast->tpl, $ast->offset);
}
- if ((count($ast->params["op"]) == 1) and ($ast->params["op"][0] instanceof TextNode)) {
+ if (
+ count($ast->params["op"]) == 1
+ && ($ast->params["op"][0] instanceof TextNode)
+ ) {
/* Operator is known at compile time, this saves *a lot* of output code! */
$op = trim($ast->params["op"][0]->text);
$op_php = null;
@@ -144,6 +160,12 @@ class Transcompiler
}
return $code;
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_not($ast)
{
$code = "\$outputstack[] = '';\n\$outputstack_i++;\n";
@@ -151,6 +173,12 @@ class Transcompiler
$code .= "\$outputstack_i--;\n\$outputstack[\$outputstack_i] .= (!\$ste->evalbool(array_pop(\$outputstack))) ? 'yes' : '';\n";
return $code;
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_even($ast)
{
$code = "\$outputstack[] = '';\n\$outputstack_i++;\n";
@@ -158,6 +186,12 @@ class Transcompiler
$code .= "\$outputstack_i--;\n\$tmp_even = array_pop(\$outputstack);\n\$outputstack[\$outputstack_i] .= (is_numeric(\$tmp_even) and (\$tmp_even % 2 == 0)) ? 'yes' : '';\n";
return $code;
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_for($ast)
{
$code = "";
@@ -179,7 +213,10 @@ class Transcompiler
$step = null; /* i.e. not known at compilation time */
if (empty($ast->params["step"])) {
$step = 1;
- } elseif ((count($ast->params["step"]) == 1) and ($ast->params["step"][0] instanceof TextNode)) {
+ } elseif (
+ count($ast->params["step"]) == 1
+ && ($ast->params["step"][0] instanceof TextNode)
+ ) {
$step = $ast->params["step"][0]->text + 0;
} else {
list($val, $pre) = self::_transcompile($ast->params["step"], true);
@@ -216,6 +253,12 @@ class Transcompiler
return $code;
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_foreach($ast)
{
$loopname = self::tempvar("foreachloop");
@@ -282,18 +325,40 @@ class Transcompiler
return $code;
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_infloop($ast)
{
return "while(true)\n{\n" . self::indent_code(self::loopbody(self::indent_code(self::_transcompile($ast->sub)))) . "\n}\n";
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ */
private static function builtin_break($ast)
{
return "throw new \\kch42\\ste\\BreakException();\n";
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ */
private static function builtin_continue($ast)
{
return "throw new \\kch42\\ste\\ContinueException();\n";
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_block($ast)
{
if (empty($ast->params["name"])) {
@@ -315,6 +380,12 @@ class Transcompiler
return $code;
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_load($ast)
{
if (empty($ast->params["name"])) {
@@ -325,6 +396,12 @@ class Transcompiler
$code .= "\$outputstack[\$outputstack_i] .= \$ste->load(" . $val . ");\n";
return $code;
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_mktag($ast)
{
$code = "";
@@ -356,10 +433,21 @@ class Transcompiler
return $code;
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ */
private static function builtin_tagcontent($ast)
{
return "\$outputstack[\$outputstack_i] .= \$sub(\$ste);";
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_set($ast)
{
if (empty($ast->params["var"])) {
@@ -376,6 +464,12 @@ class Transcompiler
return $code;
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_setlocal($ast)
{
if (empty($ast->params["var"])) {
@@ -392,6 +486,12 @@ class Transcompiler
return $code;
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_get($ast)
{
if (empty($ast->params["var"])) {
@@ -401,6 +501,12 @@ class Transcompiler
list($val, $pre) = self::_transcompile($ast->params["var"], true);
return "$pre\$outputstack[\$outputstack_i] .= \$ste->get_var_by_name(" . $val . ");";
}
+
+ /**
+ * @param TagNode $ast
+ * @return string
+ * @throws ParseCompileError
+ */
private static function builtin_calc($ast)
{
$code = "\$outputstack[] = '';\n\$outputstack_i++;\n";
@@ -425,6 +531,12 @@ class Transcompiler
return "try\n{\n" . self::indent_code($code) . "\n}\ncatch(\\kch42\\ste\\BreakException \$e) { break; }\ncatch(\\kch42\\ste\\ContinueException \$e) { continue; }\n";
}
+ /**
+ * @param ASTNode[] $ast
+ * @param bool $avoid_outputstack
+ * @return array|string
+ * @throws ParseCompileError
+ */
private static function _transcompile($ast, $avoid_outputstack = false)
{ /* The real self::transcompile function, does not add boilerplate code. */
$code = "";
@@ -477,16 +589,15 @@ class Transcompiler
return $code;
}
- /*
- * Function: transcompile
- * Transcompiles an abstract syntax tree to PHP.
- * You only need this function, if you want to manually transcompile a template.
+ /**
+ * Compiles an abstract syntax tree to PHP.
+ * You only need this function, if you want to manually compile a template.
*
- * Parameters:
- * $ast - The abstract syntax tree to transcompile.
+ * @param ASTNode[] $ast The abstract syntax tree to compile.
*
- * Returns:
- * PHP code. The PHP code is an anonymous function expecting a <STECore> instance as its parameter and returns a string (everything that was not pached into a section).
+ * @return string PHP code. The PHP code is an anonymous function expecting an {@see STECore} instance as its
+ * parameter and returns a string (everything that was not packed into a section).
+ * @throws ParseCompileError
*/
public static function transcompile($ast)
{ /* self::Transcompile and add some boilerplate code. */
diff --git a/src/ste/VariableNode.php b/src/ste/VariableNode.php
index d03fdce..9a4ced8 100644
--- a/src/ste/VariableNode.php
+++ b/src/ste/VariableNode.php
@@ -4,13 +4,24 @@ namespace kch42\ste;
class VariableNode extends ASTNode
{
+ /** @var string */
public $name;
+
+ /** @var ASTNode[][] */
public $arrayfields = array();
+
+ /**
+ * @return string
+ */
public function transcompile()
{
$varaccess = '@$ste->scope[' . (is_numeric($this->name) ? $this->name : '"' . Misc::escape_text($this->name) . '"'). ']';
foreach ($this->arrayfields as $af) {
- if ((count($af) == 1) and ($af[0] instanceof TextNode) and is_numeric($af[0]->text)) {
+ if (
+ count($af) == 1
+ && ($af[0] instanceof TextNode)
+ && is_numeric($af[0]->text)
+ ) {
$varaccess .= '[' . $af->text . ']';
} else {
$varaccess .= '[' . implode(".", array_map(function ($node) {