Main.php

<?php

namespace Tlf\Lexer\PhpNew;

trait Handlers {

    //
    //
    //Helper methods
    //
    //

    /**
     * add a docblock to the ast if there is a previous docblock set. unset the previous docblock.
     *
     * @param $ast an object
     */
    public function docblock(object $ast){
        if ($docblock = $this->lexer->unsetPrevious('docblock')){
            $ast->docblock = $docblock;
        }
    }


    public function setArgDeclaration($arg){
        $lexer = $this->lexer;
        $xpn = $lexer->previous('xpn');
        $declaration = $xpn->declaration;
        $pos = count($declaration);
        while (--$pos>=0&&$declaration[$pos]!='('&&$declaration[$pos]!=','){}
        if ($pos>0)$declaration = array_slice($declaration,$pos+1);
        $arg->declaration = trim(implode('',$declaration));
        $lexer->popHead();
        $xpn->words = [];

    }

    public function closeArg($arg){
        $lexer = $this->lexer;
        $xpn = $lexer->previous('xpn');
        $declaration = $xpn->declaration;
        $pos = count($declaration);
        while (--$pos>=0&&$declaration[$pos]!='('&&$declaration[$pos]!=','){}
        if ($pos>0)$declaration = array_slice($declaration,$pos+1);
        $arg->declaration = trim(implode('',$declaration));
        if ($xpn->waiting_for == 'value'){
            $arg->value = implode('',$xpn->words);
            $xpn->waiting_for = null;
        }
        $lexer->popHead();
        $xpn->words = [];
    }


    //
    //
    // operation / word routers
    //
    //



    public function handleWord($lexer, $ast, $token, $directive){
        $word = $token->buffer();
        $xpn = $lexer->previous('xpn');
        $xpn->push('declaration', $word);
        $xpn->push('words', $word);

        $method = 'wd_'.$word;

        // @bug if a variable name `$word` has a matching function `wd_$word`, then the variable will not be recognized
        // This means variables have special allowance & the word that is detected cannot be handled normally
        // it has to be passed to unhandled_wd
        // so where does that logic belong?
        // Probably just call it from `wd_namespace()` bc `wd_namespace()` should know when it is viable


        if (method_exists($this,$method)){
            if ($lexer->debug){
                echo "\n    call ".$method.'()';
            }
            $this->$method($lexer,$xpn,$ast);
        } else {
            if ($lexer->debug){
                echo "\n    unhandled_wd '$word'";
            }
            $this->unhandled_wd($lexer, $xpn, $ast, $word);
        }

        $xpn->last_word = $word;
    }

    /**
     * Convert an expression into an informational ast
     */
    public function handleOperation($lexer, $ast, $token, $directive){
        $xpn = $lexer->previous('xpn');
        //I'm gonna have to also handle multi-character operations like:
            // == === && ||
            // ... (vararg)
        $map = $this->get_operations();
        $char = $token->buffer();
        if (!isset($map[$char])){
            $lexer->haltInstructions();
            $lexer->directiveStopped($directive);
            $token->next();
            echo "\n     --Invalid operator: $char";
            return;
            // echo "\n\n--ERROR--\n\n";
            // echo "Char '$char' does not have any operations associated with it. Available operations are:";
            // print_r($map);
            // throw new \Exception("Invalid character matched");
        }


        $method = 'op_'.$map[$char];

        if ($lexer->debug){
            echo "\n    call '$method'";
        }
        if (!method_exists($this,$method)){
            return;
        }

        $this->$method($lexer, $ast, $xpn);
        // $this->$method($lexer, $expression, $token, $directive);
    
        $lexer->unsetPrevious('docblock');
        $lexer->previous('xpn')->last_op = $map[$char];
    }
}