<?php
namespace Tlf\Lexer;
class Ast {
protected $_path;
protected $_name;
protected $_ext;
public $_source;
protected $_tree = [];
public $_type;
public function __construct($type, $startingTree=[]){
$this->_type = $type;
$this->_tree = $startingTree ?? [];
$this->set('type',$type);
}
/**
* Removes an ast if it is setto/addedto this ast. If $key points to an empty array, then $key is unset from this ast
*
* @param $key The key $ast was setto/addedto
* @param $ast The ast to remove
*/
public function removeAst($key, $ast){
$value = $this->_tree[$key];
if (is_array($value)){
foreach ($value as $i=>$target){
if ($target===$ast)unset($this->tree[$key][$i]);
}
if ($this->tree[$key]===[])unset($this->tree[$key]);
} else if ($value===$ast){
unset($this->tree[$key]);
}
}
/**
* Set $value to $key, overwriting any previously set value
*/
public function set($key,$value){
$this->_tree[$key] = $value;
}
public function append($key, $value){
$this->_tree[$key] = $this->_tree[$key] . $value;
}
/**
* @param $keyValues a `key=>value` array to call `$this->set($key, $value)` on each entry
*/
public function setAll(array $keyValues){
foreach ($keyValues as $key=>$value){
$this->set($key,$value);
}
}
/**
* Add $value to an array
* @param $key the key that we'll be pushing $value onto
* @param $value the value to append
* @param $subKey a subkey for an assoc array
*/
public function add($key,$value, $subKey=false){
// if (!isset($this->_tree[$key]))$this->_tree[$key] = [];
if ($subKey===false)
$this->_tree[$key][] = $value;
else
$this->_tree[$key][$subKey] = $value;
}
/**
* Alias for add
*/
public function push($key, $value, $subKey=false){
$this->add($key, $value, $subKey);
}
/**
* Check if key is set on this ast.
* @return true if yes, false otherwise
*/
public function has(string $key): bool{
return isset($this->_tree[$key]);
}
public function get($key){
return $this->_tree[$key] ?? null;
}
/**
* Get the current tree as-is (asts are still asts)
*/
public function getAll(){
return $this->_tree;
}
protected $passthrough = [];
public function addPassthrough($ast){
$this->passthrough[] = $ast;
}
/**
* Get the tree as a pure array
*/
public function getTree($sourceTree=null){
static $a = 0;
$srcTreeIsNull = is_null($sourceTree);
$sourceTree = $sourceTree ?? $this->_tree;
$tree = [];
foreach ($sourceTree as $key=>$value){
if (is_array($value)){
$tree[$key] = $this->getTree($value);
// $tree[$key] = 'array';
// $tree[$key] = json_encode($value);
} else if ($value instanceof Ast){
$tree[$key] = $value->getTree();
} else {
$tree[$key] = $value;
}
}
if ($srcTreeIsNull){
foreach ($this->passthrough as $pt){
$ptTree = $pt->getTree();
unset($ptTree['type']);
foreach ($ptTree as $k=>$v){
// if ($k=='methods'){
// $a++;
// echo "\n\n\n\n\n-----";
// var_dump($this);
// echo "\n\n\n\n\n-----";
// var_dump($ptTree);
// echo "\n\n\n\n\n-----";
// if ($a==2)exit;
// }
if (is_object($v))$v = $v->getTree();
// $tree[$k] = '--'.$this->type.':'.$k.'--'.$a++;
$tree[$k] = $v;
}
}
}
return $tree;
}
public function setTree($astTree){
$this->_tree = $astTree;
}
public function __get($prop){
return $this->get($prop);
}
public function __set($prop, $value){
$this->set($prop, $value);
}
public function __isset($prop){
return isset($this->_tree[$prop]);
}
static public function __set_state($array){
return $array;
}
}