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; }