178 lines
5.7 KiB
PHP
178 lines
5.7 KiB
PHP
|
<?php
|
||
|
namespace nur\php;
|
||
|
|
||
|
use nur\A;
|
||
|
|
||
|
class SrcGenerator {
|
||
|
const INDENT = " ";
|
||
|
|
||
|
function __construct(string $indent="") {
|
||
|
$this->indent = $indent;
|
||
|
$this->lines = [];
|
||
|
}
|
||
|
|
||
|
/** @var string */
|
||
|
private $indent;
|
||
|
|
||
|
function indent(): self {
|
||
|
$this->indent .= self::INDENT;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
function dedent(): self {
|
||
|
$this->indent = substr($this->indent, strlen(self::INDENT));
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
private $lines;
|
||
|
|
||
|
function getLines(): array {
|
||
|
return $this->lines;
|
||
|
}
|
||
|
|
||
|
private static function export($value): string {
|
||
|
if ($value === null) $value = "null";
|
||
|
else $value = var_export($value, true);
|
||
|
return $value;
|
||
|
}
|
||
|
|
||
|
private static function check_literals(&$value, ?array $literals): bool {
|
||
|
if ($literals === null) return false;
|
||
|
foreach ($literals as [$lfrom, $lto]) {
|
||
|
if ($value === $lfrom) {
|
||
|
$value = $lto;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private static function is_scalar_array(array $array, bool $check_size=true): bool {
|
||
|
if (!A::is_seq($array)) return false;
|
||
|
$scalar_array = true;
|
||
|
foreach ($array as $value) {
|
||
|
if (is_array($value)) {
|
||
|
$scalar_array = false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ($scalar_array && $check_size) {
|
||
|
# vérifier si tout le tableau tient sur 80 caractères
|
||
|
# si le tableau fait plus de 80 caractères, considérer qu'il n'est pas
|
||
|
# scalaire afin que chaque élément soit affiché sur une ligne à part
|
||
|
$size = 2; # pour '[]'
|
||
|
$first = true;
|
||
|
foreach ($array as $value) {
|
||
|
$size += strlen(self::export($value));
|
||
|
if ($first) $first = false;
|
||
|
else $size += 2; # pour ', '
|
||
|
}
|
||
|
$scalar_array = $size <= 80;
|
||
|
}
|
||
|
return $scalar_array;
|
||
|
}
|
||
|
|
||
|
private function addScalarArrayItems(array $array, ?string $prefix=null, ?string $suffix=null, ?array $literals=null): void {
|
||
|
$parts = [];
|
||
|
$parts[] = $prefix;
|
||
|
$parts[] = "[";
|
||
|
$first = true;
|
||
|
foreach ($array as $value) {
|
||
|
if ($first) $first = false;
|
||
|
else $parts[] = ", ";
|
||
|
if (!self::check_literals($value, $literals)) $value = self::export($value);
|
||
|
$parts[] = $value;
|
||
|
}
|
||
|
$parts[] = "]";
|
||
|
$parts[] = $suffix;
|
||
|
$this->lines[] = implode("", $parts);
|
||
|
}
|
||
|
|
||
|
private function addGenericArrayItems(array $values, ?string $prefix=null, ?string $suffix=null, ?array $literals=null): void {
|
||
|
$this->lines[] = $prefix."[";
|
||
|
$this->indent();
|
||
|
$this->addArrayItems($values, $literals);
|
||
|
$this->dedent();
|
||
|
$this->lines[] = $this->indent."]".$suffix;
|
||
|
}
|
||
|
|
||
|
private function addArrayItems(array $values, ?array $literals=null): void {
|
||
|
$seq = A::is_seq($values);
|
||
|
$index = 0;
|
||
|
foreach ($values as $key => $value) {
|
||
|
$prefix = $this->indent;
|
||
|
if (!$seq && $key !== $index) $prefix .= self::export($key)." => ";
|
||
|
if ($key === $index) $index++;
|
||
|
if (self::check_literals($value, $literals)) {
|
||
|
$this->lines[] = $prefix.$value.",";
|
||
|
} elseif (is_array($value)) {
|
||
|
if (self::is_scalar_array($value)) {
|
||
|
# si value ne contient que des valeurs scalaires, tout mettre sur une
|
||
|
# même ligne
|
||
|
$this->addScalarArrayItems($value, $prefix, ",", $literals);
|
||
|
} else {
|
||
|
$this->addGenericArrayItems($value, $prefix, ",", $literals);
|
||
|
}
|
||
|
} else {
|
||
|
$this->lines[] = $prefix.self::export($value).",";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function addValue($value, ?string $prefix=null, ?string $suffix=null, ?array $literals=null): self {
|
||
|
if (self::check_literals($value, $literals)) {
|
||
|
$this->lines[] = $prefix.$value.$suffix;
|
||
|
} elseif (is_array($value)) {
|
||
|
if (self::is_scalar_array($value)) {
|
||
|
# si value ne contient que des valeurs scalaires, tout mettre sur une
|
||
|
# même ligne
|
||
|
$this->addScalarArrayItems($value, $prefix, $suffix, $literals);
|
||
|
} else {
|
||
|
$this->addGenericArrayItems($value, $prefix, $suffix, $literals);
|
||
|
}
|
||
|
} else {
|
||
|
$this->lines[] = $prefix.self::export($value).$suffix;
|
||
|
}
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
function addLiteral($value, ?string $prefix=null, ?string $suffix=null): self {
|
||
|
$this->lines[] = $prefix.$value.$suffix;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
function genSof(): self {
|
||
|
$this->lines[] = "<?php # -*- coding: utf-8 mode: php -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8";
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
function genConst(string $name, $value, ?string $prefix=null, ?array $literals=null, bool $literalValue=false, ?string $valuePrefix=null): self {
|
||
|
$prefix = "$this->indent${prefix}const $name = ${valuePrefix}";
|
||
|
if ($literalValue) return $this->addLiteral($value, $prefix, ";");
|
||
|
else return $this->addValue($value, $prefix, ";", $literals);
|
||
|
}
|
||
|
|
||
|
function genVar(string $name, $value, ?string $prefix=null, ?array $literals=null, bool $literalValue=false, ?string $valuePrefix=null): self {
|
||
|
$prefix = "$this->indent${prefix}\$$name = ${valuePrefix}";
|
||
|
if ($literalValue) return $this->addLiteral($value, $prefix, ";");
|
||
|
else return $this->addValue($value, $prefix, ";", $literals);
|
||
|
}
|
||
|
|
||
|
function genReturn($value, ?string $prefix=null, ?array $literals=null, bool $literalValue=false, ?string $valuePrefix=null): self {
|
||
|
$prefix = "$this->indent${prefix}return ${valuePrefix}";
|
||
|
if ($literalValue) return $this->addLiteral($value, $prefix, ";");
|
||
|
else return $this->addValue($value, $prefix, ";", $literals);
|
||
|
}
|
||
|
|
||
|
function genLiteral($line, ?string $prefix=null, ?string $suffix=null): self {
|
||
|
$prefix = "$this->indent$prefix";
|
||
|
return $this->addLiteral($line, $prefix, $suffix);
|
||
|
}
|
||
|
|
||
|
/** fusionner les lignes générées avec $lines */
|
||
|
function mergeInto(array &$lines, bool $reset=true) {
|
||
|
A::merge($lines, $this->lines);
|
||
|
if ($reset) $this->lines = [];
|
||
|
}
|
||
|
}
|