Directives.php

<?php

namespace Tlf\LexerTrait;

/**
 * Manages the state of directives, including the different levels of directives and starting/stopping directives.
 */
trait Directives {

    /**
     * A stack of directives. Each layer of the stack has a 'started', 'unstarted', and 'directives' list.
     */
    public $directiveStack = [];


    public function newDirectivesLayer(){
        $this->directiveStack[] = [
            // 'directives'=>[],
            'unstarted'=>[],
            'started'=>[],
        ];
    }

    public function getTopDirectives(){
        return $this->topDirectivesList();
    }
    protected function &topDirectivesList(){
        return $this->directiveStack[count($this->directiveStack)-1];
    }
    /**
     *
     * @param $directive a previously unstarted directive
     */
    public function directiveStarted(object $directive){
        $list = &$this->topDirectivesList();
        if (!isset($list['unstarted'][$directive->_name])){
            $name = $directive->_name;
            echo "\n  -- '$name' cannot be started because it isn't in unstarted.";
            return;
        }
        $list['started'][$directive->_name] = $directive;
        unset($list['unstarted'][$directive->_name]);
    }
    /**
     * Move a directive from started stack to unstarted
     *
     * @param $directive a directive that was stopped 
     */
    public function directiveStopped(object $directive){
        $list = &$this->topDirectivesList();
        if (!isset($list['started'][$directive->_name])){
            $name = $directive->_name;
            echo "\n  -- '$name' cannot be stopped because it isn't started.";
            return;
        }
        $list['unstarted'][$directive->_name] = $directive;
        unset($list['started'][$directive->_name]);
    }
    /**
     * Adds a directed to the list of unstarted directives on the top directive list.
     * @note If the directive stack is empty, creates a new directive layer
     */
    public function addDirective(object $directive, bool $is_started = false){
        if (count($this->directiveStack)===0)$this->newDirectivesLayer();

        $list = &$this->topDirectivesList();
        if ($is_started)$list['started'][$directive->_name] = $directive;
        else $list['unstarted'][$directive->_name] = $directive;
    }

    public function popDirectivesLayer(){
        if (count($this->directiveStack)>0){
            array_pop($this->directiveStack);
            return;
        }
        throw new \Exception("\n\nThere must be at least one directive layer in order to pop one.\n");
    }

}