/** * @test */ public function itDumpsAHumanReadableParseTableWithExplainingComments() { $grammar = new ExampleGrammar(); $analyzer = new Analyzer(); $result = $analyzer->analyze($grammar); $dumper = new DebugTableDumper($grammar); $dumped = $dumper->dump($result->getParseTable()); $this->assertStringEqualsFile(__DIR__ . '/res/table/debug.php', $dumped); }
/** * @test */ public function theWrittenTableShouldBeAsCompactAsPossible() { $grammar = new ExampleGrammar(); $analyzer = new Analyzer(); $table = $analyzer->analyze($grammar)->getParseTable(); $dumper = new ProductionTableDumper(); $dumped = $dumper->dump($table); $this->assertStringEqualsFile(__DIR__ . '/res/table/production.php', $dumped); }
/** * Constructor. * * @param \Dissect\Parser\Grammar $grammar The grammar. * @param array $parseTable If given, the parser doesn't have to analyze the grammar. */ public function __construct(P\Grammar $grammar, array $parseTable = null) { $this->grammar = $grammar; if ($parseTable) { $this->parseTable = $parseTable; } else { $analyzer = new Analyzer(); $this->parseTable = $analyzer->analyze($grammar)->getParseTable(); } }
protected function execute(InputInterface $input, OutputInterface $output) { $class = strtr($input->getArgument('grammar-class'), '/', '\\'); $formatter = $this->getHelperSet()->get('formatter'); $output->writeln('<info>Analyzing...</info>'); $output->writeln(''); if (!class_exists($class)) { $output->writeln(array($formatter->formatBlock(sprintf('The class "%s" could not be found.', $class), 'error', true))); return 1; } $grammar = new $class(); if ($dir = $input->getOption('output-dir')) { $cwd = rtrim(getcwd(), DIRECTORY_SEPARATOR); $outputDir = $cwd . DIRECTORY_SEPARATOR . $dir; } else { $refl = new ReflectionClass($class); $outputDir = pathinfo($refl->getFileName(), PATHINFO_DIRNAME); } $analyzer = new Analyzer(); $automaton = null; try { $result = $analyzer->analyze($grammar); $conflicts = $result->getResolvedConflicts(); $automaton = $result->getAutomaton(); $table = $result->getParseTable(); if ($conflicts) { foreach ($conflicts as $conflict) { $output->writeln($this->formatConflict($conflict)); } $output->writeln(sprintf("<info><comment>%d</comment> conflicts in total", count($conflicts))); $output->writeln(''); } $output->writeln('<info>Writing the parse table...</info>'); $fileName = $outputDir . DIRECTORY_SEPARATOR . 'parse_table.php'; if ($input->getOption('debug')) { $tableDumper = new DebugTableDumper($grammar); } else { $tableDumper = new ProductionTableDumper(); } $code = $tableDumper->dump($table); $ret = @file_put_contents($fileName, $code); if ($ret === false) { $output->writeln('<error>Error writing the parse table</error>'); } else { $output->writeln('<info>Parse table written</info>'); } } catch (ConflictException $e) { $output->writeln(array($formatter->formatBlock(explode("\n", $e->getMessage()), 'error', true))); $automaton = $e->getAutomaton(); } if ($input->getOption('dfa')) { $output->writeln(''); $automatonDumper = new AutomatonDumper($automaton); if ($input->getOption('state') === null) { $output->writeln('<info>Exporting the DFA...</info>'); $dot = $automatonDumper->dump(); $file = 'automaton.dot'; } else { $state = (int) $input->getOption('state'); if (!$automaton->hasState($state)) { $output->writeln(array($formatter->formatBlock(sprintf('The automaton has no state #%d', $state), 'error', true))); return 1; } $output->writeln(sprintf('<info>Exporting the DFA state <comment>%d</comment>...', $state)); $dot = $automatonDumper->dumpState($state); $file = sprintf('state_%d.dot', $state); } $fileName = $outputDir . DIRECTORY_SEPARATOR . $file; $ret = @file_put_contents($fileName, $dot); if ($ret === false) { $output->writeln('<error>Error writing to the file</error>'); } else { $output->writeln('<info>Successfully exported</info>'); } } return 0; }
protected function setUp() { $analyzer = new Analyzer(); $automaton = $analyzer->analyze(new ExampleGrammar())->getAutomaton(); $this->dumper = new AutomatonDumper($automaton); }