Main.php

<?php

namespace Tlf\Breg\Test;

class Main extends \Tlf\Tester {

    /**
     * @bug(fixed, 3-20-2022) When a function call has an arg, the rest of the functions fail to parse. 
     *
     *
     */
    public function testTwoFunctionCalls(){
        $br = new \Breg();
        $br->handle('everything',function(){return '(.+)';});
        $br->handle('subtags',function(){return 'sub';});
        $reg = <<<REGEX
            /a  \    
                ::everything(arg) # everything in between
                some stuff
                ::everything(unother)
                ::subtags()
            g/ # umm, the alphabet ends on z, actually

        REGEX;
        $parsed = $br->parse($reg);

        $this->compare(
            '/a  \ (.+)some stuff(.+)subg/',
            $parsed
        );
    }

    /** @test matching a basic regex */
    public function testBasicMatch(){
        $br = new \Breg();
        $reg = '/a(.+)g(h)/';
        $str = '0abcdefghi';
        $ret = $br->match($reg, $str);
        $this->compare(
            ['abcdefgh','bcdef','h'],
            $ret[0]
        );
    }

    /** @test a full-featured usage for documentation */
    public function testDocumentation(){
        // @export_start(Example.Full)
        $reg = <<<REGEX
            /abc\ # abc then a space
                ( # join referenced regexes with a |
                ::combine({{one}}{{two}}{{three}} ;; | )
                )\\ # literal backslash

                \# # literal hashtag (then comment)
            xyz/
        REGEX;
        $reg_refs = [
            'one'=>'(1|one|uno)',
            'two'=>'(2|two|dos)',
            'three'=>'(3|three|tres)',
            'four'=>'(4|four|quatro)'
        ];
        $br = new \Breg();
        $br->handle('combine',
            function(array $keys, string $joiner) use ($reg_refs){
                // make an array of only the selected regs
                $regs = [];
                foreach ($keys as $k){
                    $regs[] = $reg_refs[$k];
                }
                return implode($joiner, $regs);
            }
        );
        $final = $br->parse($reg);
        
        $this->compare(
            '/abc\ ((1|one|uno)|(2|two|dos)|(3|three|tres))\\\\#xyz/',
            $final,
        );
        $this->is_true(
            preg_match($final, 'abc dos\\#xyz/') === 1
        );
        // @export_end(Example.Full)
    }

    /**
     * @test argument list (array)
     */
    public function testBuildRegFuncArgs(){
        $br = new \Breg();
        $br->handle('letters',
            function(array $letters){
                return implode('', $letters);
            }
        );
        $reg = <<<REGEX
            /a 
                ::letters({{b}}{{c}}{{d}}{{f}}) # everything in between
            g/ # umm, the alphabet ends on z, actually

        REGEX;
        $target = '/a  \ ::everything()g/';
        $parsed = $br->parse($reg);

        $this->compare(
            '/abcdfg/',
            $parsed
        );
    }
    /** @test regex with function call containing an underscore */
    public function testBuildFunctionWithUnderscore(){
        $br = new \Breg();
        $br->handle('every_thing',function(){return '(.+)';});
        $reg = <<<REGEX
            /a  \    
                ::every_thing() # everything in between
            g/ # umm, the alphabet ends on z, actually

        REGEX;
        $parsed = $br->parse($reg);

        $this->compare(
            '/a  \ (.+)g/',
            $parsed
        );
    }

    /** @test regex with function call */
    public function testBuildRegAuto(){
        $br = new \Breg();
        $br->handle('everything',function(){return '(.+)';});
        $reg = <<<REGEX
            /a  \    
                ::everything() # everything in between
            g/ # umm, the alphabet ends on z, actually

        REGEX;
        $parsed = $br->parse($reg);

        $this->compare(
            '/a  \ (.+)g/',
            $parsed
        );
    }

    /**
     * @test parsing regex & then filling in the function manually
     */
    public function testBuildRegManual(){
        $parser = new \Breg\Parser();

        $reg = <<<REGEX
            /a  \    
                ::everything() # everything in between
            g/ # umm, the alphabet ends on z, actually

        REGEX;
        $parsed = $parser->parse($reg);

        //this would normally use a callback, but this is a simple test
        $replacement = '(.+)'; 
        $clean = $parsed['clean_reg'];
        $clean = str_replace($parsed['functions'][0]['definition'], $replacement, $clean);

        $this->compare(
            '/a  \ (.+)g/',
            $clean
        );
    }

    /**
     * @test function is parsed out
     */
    public function testParseFunctions(){
        $br = new \Breg\Parser();
        $reg = <<<REGEX
            /a  \    
                ::everything() # everything in between
            g/ # umm, the alphabet ends on z, actually

        REGEX;
        $target = '/a  \ ::everything()g/';
        $parsed = $br->parse($reg);

        $this->compare(
            ['source_reg'=>$reg,
            'functions'=>[
                [   'definition'=>'::everything()',
                    'name'=>'everything',
                    'args'=>[],
                    'argString'=>'',
                ]
            ],
            'clean_reg'=>$target,
            ],
            $parsed
        );
    }

    /**
     *
     * @test backslash at end of line adds `\<space>` to the regex (and preserves whitespace before the backslash)
     */
    public function testParseEscapedEndOfLine(){
        $br = new \Breg\Parser();
        $reg = <<<REGEX
            /a  \    
                (.+) # everything in between
            g/ # umm, the alphabet ends on z, actually

        REGEX;
        $target = '/a  \ (.+)g/';
        $parsed = $br->parse($reg);
        print_r($parsed);

        $this->compare(
            ['source_reg'=>$reg,
            'functions'=>[],
            'clean_reg'=>$target,
            ],
            $parsed
        );
    }

    /** @test comments in regex */
    public function testParseComments(){
        $br = new \Breg\Parser();
        $reg = <<<REGEX
            /a # first letter of the alphabet
                (.+) # everything in between
            g/ # umm, the alphabet ends on z, actually

        REGEX;
        $target = '/a(.+)g/';
        $parsed = $br->parse($reg);
        print_r($parsed);

        $this->compare(
            ['source_reg'=>$reg,
            'functions'=>[],
            'clean_reg'=>$target,
            ],
            $parsed
        );
    }

    /** @test multi-line regex */
    public function testParseMultiLine(){
        $br = new \Breg\Parser();
        $reg = <<<REGEX
            /a
                (.+)
            g/

        REGEX;
        $target = '/a(.+)g/';
        $parsed = $br->parse($reg);
        print_r($parsed);

        $this->compare(
            ['source_reg'=>$reg,
            'functions'=>[],
            'clean_reg'=>$target,
            ],
            $parsed
        );
    }

    /**
     * @test regular regex
     */
    public function testParseSimple(){
        $br = new \Breg\Parser();
        $reg = '/a(.+)g/';
        $parsed = $br->parse($reg);
        print_r($parsed);

        $this->compare(
            ['source_reg'=>$reg,
            'functions'=>[],
            'clean_reg'=>$reg,
            ],
            $parsed
        );
    }
}