Exemplo n.º 1
0
    public function visitGrammar(GrammarNode $node)
    {
        $result = '';
        if ($node->getNamespace() !== null) {
            $result .= "namespace {$node->getNamespace()};\n\n";
        }
        if (count($node->getImports()) > 0) {
            foreach ($node->getImports() as $import) {
                $result .= "use {$import};\n";
            }
            $result .= "\n";
        }
        if ($node->getBase() === null) {
            $result .= <<<EOS
class {$node->getName()}
{
    protected \$string;
    protected \$position;
    protected \$value;
    protected \$cache;
    protected \$cut;
    protected \$errors;
    protected \$warnings;

EOS;
        } else {
            $result .= <<<EOS
class {$node->getName()} extends {$node->getBase()}
{
EOS;
        }
        $pieces = $this->getResults($node->getLength());
        foreach ($pieces as $piece) {
            $result .= <<<EOS

    {$this->indent($piece)}

EOS;
        }
        if ($node->getStartSymbol() !== null) {
            $result .= <<<EOS

    private function line()
    {
        if (!empty(\$this->errors)) {
            \$positions = array_keys(\$this->errors);
        } else {
            \$positions = array_keys(\$this->warnings);
        }

        return count(explode("\\n", substr(\$this->string, 0, max(\$positions))));
    }

    private function rest()
    {
        return '"' . substr(\$this->string, \$this->position) . '"';
    }

    protected function report(\$position, \$expecting)
    {
        if (\$this->cut) {
            \$this->errors[\$position][] = \$expecting;
        } else {
            \$this->warnings[\$position][] = \$expecting;
        }
    }

    private function expecting()
    {
        if (!empty(\$this->errors)) {
            ksort(\$this->errors);

            return end(\$this->errors)[0];
        }

        ksort(\$this->warnings);

        return implode(', ', end(\$this->warnings));
    }

    public function parse(\$_string)
    {
        \$this->string = \$_string;
        \$this->position = 0;
        \$this->value = null;
        \$this->cache = array();
        \$this->cut = false;
        \$this->errors = array();
        \$this->warnings = array();

        \$_success = \$this->parse{$node->getStartSymbol()}();

        if (\$_success && \$this->position < strlen(\$this->string)) {
            \$_success = false;

            \$this->report(\$this->position, "end of file");
        }

        if (!\$_success) {
            throw new \\InvalidArgumentException("Syntax error, expecting {\$this->expecting()} on line {\$this->line()}");
        }

        return \$this->value;
    }

EOS;
        }
        $result .= <<<EOS
}
EOS;
        $this->results[] = $result;
    }