GrammarBase.php

<?php

namespace Tlf\Lexer\Test;

class GrammarBase extends \Tlf\Tester {

    protected $grammar;

    public function prepare(){
        $this->grammar = new \Tlf\Lexer\Grammar();
    }



    /** I wrote this for thinking purposes, and I will probably use it for some testing maybe????
     * Might be able to delete it.
     */
    protected $sampleDirectiveList = [
            'grp'=>[
                'stop'=>[
                    //overrides target.stop.rewind & target_2.stop.rewind
                    'rewind'=>1
                ],
                'is'=>[
                    ':target'=>[
                        //overrides grp.stop.rewind & target.stop.rewind
                        'rewind'=>2,
                    ],
                    ':target_2'=>[],
                ]
            ],
            'target'=>[
                'stop'=>[
                    'match'=>'abc',
                    // overrides nothing
                    'rewind'=>3,
                ]
            ],
            'parent'=>[
                'stop'=>[
                    'then :grp'=>[
                        //highest priority. This always overrides whatever its loading
                        'rewind'=>4
                    ],
                ]
            ],

            'target_2'=>[],
        ];

    /**
     *
     * @return multi dimensional array
     * @array.key is the thing being tested
     * @array.child is an array with 3 child arrays
     * @array.child.index1 is the name of the directive to load
     * @array.child.index2 is the the overrides
     * @array.child.index3 is the expected directive list to be returned
     */
    protected function getDirectivesToLookup(){

        return [
            'Empty Directive'=>[
                ':empty_directive',
                [],
                ['empty_directive'=>[]],
            ],
            'Is Directive'=>[
                ':is_directive',
                [],
                [
                    'is_target'=>[
                        'stop'=>[
                            'match'=>['/is/'],
                        ],
                    ],
                    'is_target_2'=>[
                        'stop'=>[
                            'match'=>['/is_2/'],
                        ],
                    ],
                    'is_target_3'=>[
                        'stop'=>[
                            'match'=>['/is_3/'],
                        ],
                    ],
                ],
            ],
        ];
    }
    protected function getSourceDirectives(){
        return [
            'empty_directive'=>[
            ],
            'is_directive'=>[
                'is'=>[
                    ':is_target'=>[],
                    ':is_target_2'=>[],
                    ':is_target_3'=>[],
                ],
            ],
            'is_target'=>[
                'stop'=>[
                    'match'=>['/is/'],
                ],
            ],
            'is_target_2'=>[
                'stop'=>[
                    'match'=>['/is_2/'],
                ],
            ],
            'is_target_3'=>[
                'stop'=>[
                    'match'=>['/is_3/'],
                ],
            ],
        ];
    }

    protected function testGetDirectives(){
        $grammar = new \Tlf\Lexer\Grammar();
        $grammar->directives = $this->getSourceDirectives();
        foreach ($this->getDirectivesToLookup() as $testName=>$pieces){
            if ($testName!='Is Directive'){
                //var_dump("")
                //exit;
                //@todo REMOVE THIS continue
                continue;
            }
            $this->test($testName);
            $lookupName = $pieces[0];
            $overrides = $pieces[1];
            $expectedList = $pieces[2];

            $actualList = $grammar->getDirectives($lookupName, $overrides);

            foreach ($actualList as $name=>$d){
                unset($d->_name);
                unset($d->_grammar);
                $actualList[$name] = (array)$d;
            }

            $this->compare($expectedList, $actualList);
        }
    }

    protected function testExpandIsDirectiveWithOverrides(){
        $this->disable();
        echo "\n\n";
            
            echo "This test is disabled because I haven't actually implemented it yet. Its currently a copy+paste from testExpandIsDirective() (no overrides) ";

        echo "\n\n";

        return false;
        $grammar = new \Tlf\Lexer\Grammar();
        $dRoot = $grammar->directives = $this->getSourceDirectives();
        
        $sourceDirective = (object)$grammar->directives['is_directive'];
        $sourceDirective->_name = 'is_directive';
        $sourceDirective->_grammar = 'grammar';
        $directiveList = $grammar->expandDirectiveWithIs($sourceDirective);


        foreach ($directiveList as $directiveName=>$directive){
            unset($directive->_name);
            unset($directive->_grammar);
            $directiveList[$directiveName] = (array)$directive;
        }

        $this->compare(
            [
                'is_target'=>$dRoot['is_target'],
                'is_target_2'=>$dRoot['is_target_2'],
                'is_target_3'=>$dRoot['is_target_3'],
            ],
            $directiveList
        );
    }

    protected function testExpandIsDirective(){
        $grammar = new \Tlf\Lexer\Grammar();
        $dRoot = $grammar->directives = $this->getSourceDirectives();
        
        $sourceDirective = (object)$grammar->directives['is_directive'];
        $sourceDirective->_name = 'is_directive';
        $sourceDirective->_grammar = 'grammar';
        $directiveList = $grammar->expandDirectiveWithIs($sourceDirective);


        foreach ($directiveList as $directiveName=>$directive){
            unset($directive->_name);
            unset($directive->_grammar);
            $directiveList[$directiveName] = (array)$directive;
        }

        $this->compare(
            [
                'is_target'=>$dRoot['is_target'],
                'is_target_2'=>$dRoot['is_target_2'],
                'is_target_3'=>$dRoot['is_target_3'],
            ],
            $directiveList
        );
    }

    /**
     *
     * @return multi dimensional array
     * @array.key is the thing being tested
     * @array.child is an array with 3 child arrays
     * @array.child.index1 is the source/root directive
     * @array.child.index2 is the overrides
     * @array.child.index3 is the expected result
     */
    protected function getOverrideDirectives(){
        return [
            'Is overrides'=>[
                [
                    'is'=>[
                        ':source'=>[],
                    ],
                ],
                [
                    'is'=>[
                        ':override'=>[],
                    ],
                ],
                [
                    'is'=>[
                        ':override'=>[],
                        ':source'=>[],
                    ],
                ],
            ],
            'Source match is second'=>[
                [
                    'start'=>[
                        'then'=>[':cat'],
                        'match'=>['uhoh'],
                    ],
                ],
                [
                    'start'=>[
                        'match //'=>['abc'],
                        'hide'=>['nothing'],
                    ],
                ],
                [
                    'start'=>[
                        'match //'=>['abc'],
                        'hide'=>['nothing'],
                        'then'=>[':cat'],
                        'match'=>['uhoh'],
                    ]
                ],
            ],
            'Source nomatch' => [
                [
                    'start'=>[
                        'then'=>[':cat'],
                    ],
                ],
                [
                    'start'=>[
                        'hide'=>['nothing'],
                        'match'=>['abc'],
                    ],
                ],
                [
                    'start'=>[
                        'hide'=>['nothing'],
                        'match'=>['abc'],
                        'then'=>[':cat'],
                    ]
                ],
            ],
            'Source match, then overrides, then other source instructions'=>[
                [
                    'start'=>[
                        'match'=>['abc'],
                        'then'=>[':cat'],
                    ],
                ],
                [
                    'start'=>[
                        'hide'=>['nothing'],
                    ],
                ],
                [
                    'start'=>[
                        'match'=>['abc'],
                        'hide'=>['nothing'],
                        'then'=>[':cat'],
                    ]
                ],
            ],
            'Direct Key Overrides'=>[
                [
                    'stop'=>[
                        'match'=> ['abc'],
                        'then'=> ['cats'],
                    ]
                ],
                [
                    'stop'=>[
                        'match'=> ['dog'],
                        'rewind'=>1,
                    ]
                ],
                [
                    'stop'=>[
                        'match'=>['dog'],
                        'rewind'=>1,
                        'then'=>['cats'],
                    ],
                ],
            ]

        ];
    }

    protected function testDirectiveOverrides(){
    
        foreach ($this->getOverrideDirectives() as $testName=>$pieces){
            $source = (object)$pieces[0];
            $overrides = (object)$pieces[1];
            $expect = $pieces[2];
            $actual = $this->grammar->getOverriddenDirective($overrides, $source);
            $this->is_object($actual);
            $this->test($testName);
            $this->compare($expect, (array)$actual,true);
        }
    }

    /**
     *
     * @return multi dimensional array
     * @key is the thing being tested
     * @child.index1 is the input directive, as one would define it
     * @child.index2 is the expected output directive, as returned from the normalize method
     */
    protected function getNormalizeDirectives(){
        return [
            'Stop'=>[
                [
                    'stop'=>[
                        'then :cat',
                        'then :dog'=>['override'],
                        'then :bear ...',
                    ],
                ],
                [
                    'stop'=>[
                        'then :cat'=>[],
                        'then :dog'=>['override'],
                        'then :bear ...'=>[],
                    ],
                ],
            ],
            'Is'=>[
                [
                    'is'=>[
                        ':cat',
                        ':dog'=>['override'],
                        ':bear',
                    ],
                ],
                [
                    'is'=>[
                        ':cat'=>[],
                        ':dog'=>['override'],
                        ':bear'=>[],
                    ],
                ],
            ],
        ];
    }

    public function testDirectiveNormalization(){
        foreach ($this->getNormalizeDirectives() as $name=>$comparators){
            $this->test($name);
            $directive = $comparators[0];
            $expect = $comparators[1];
            $normal = $this->grammar->normalizeDirective($directive);
            $this->is_object($normal);
            $this->compare($expect, (array)$normal);
        }
    }
}