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 = [];
 | |
|   }
 | |
| }
 |