GenerateCommand::generate()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 4
1
<?php
2
/**
3
 * This file is part of PHP-Yacc package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace PhpYacc\Console;
11
12
use PhpYacc\Generator;
13
use PhpYacc\Grammar\Context;
14
use Symfony\Component\Console\Command\Command;
15
use Symfony\Component\Console\Exception\InvalidArgumentException;
16
use Symfony\Component\Console\Exception\InvalidOptionException;
17
use Symfony\Component\Console\Exception\RuntimeException;
18
use Symfony\Component\Console\Input\InputArgument;
19
use Symfony\Component\Console\Input\InputInterface;
20
use Symfony\Component\Console\Input\InputOption;
21
use Symfony\Component\Console\Output\OutputInterface;
22
23
/**
24
 * Class GenerateCommand.
25
 */
26
class GenerateCommand extends Command
27
{
28
    /**
29
     * @return void
30
     */
31
    public function configure(): void
32
    {
33
        $this->setName('generate');
34
        $this->setDescription('The command to generate a parser.');
35
        $this->addArgument('grammar', InputArgument::REQUIRED, 'Grammar file.');
36
37
        $this->addOption('skeleton', 's', InputOption::VALUE_REQUIRED, 'Specify the skeleton to use.');
38
        $this->addOption('output', 'o', InputOption::VALUE_REQUIRED, 'Leave output to file.');
39
        $this->addOption('class', 'c', InputOption::VALUE_REQUIRED, 'Parser class name.', 'YaccParser');
40
    }
41
42
    /**
43
     * @param InputInterface  $input
44
     * @param OutputInterface $output
45
     *
46
     * @return void
47
     */
48
    public function execute(InputInterface $input, OutputInterface $output): void
49
    {
50
        $this->validateInput($input);
51
52
        $grammar = $input->getArgument('grammar');
53
        $skeleton = $input->getOption('skeleton');
54
        $class = $input->getOption('class');
55
        $result = $input->getOption('output') ?? \sprintf('.%s%s.php', DIRECTORY_SEPARATOR, $class);
56
57
        $context = new Context(\basename($grammar));
58
        $context->className = $class;
59
60
        $this->generate($context, $grammar, $skeleton, $result);
61
        $output->writeln('<info>OK</info>');
62
    }
63
64
    /**
65
     * @param InputInterface $input
66
     *
67
     * @return void
68
     */
69
    private function validateInput(InputInterface $input): void
70
    {
71
        $skeleton = $input->getOption('skeleton');
72
        if ($skeleton === null || !\file_exists($skeleton)) {
73
            throw new InvalidOptionException(\sprintf('The skeleton file "%s" is not found', $skeleton));
74
        }
75
76
        $grammar = $input->getArgument('grammar');
77
        if (!\file_exists($grammar)) {
78
            throw new InvalidArgumentException(\sprintf('The grammar file "%s" is not found', $grammar));
79
        }
80
    }
81
82
    /**
83
     * @param Context $context
84
     * @param string  $grammar
85
     * @param string  $skeleton
86
     * @param string  $result
87
     *
88
     * @return void
89
     */
90
    private function generate(Context $context, string $grammar, string $skeleton, string $result): void
91
    {
92
        $generator = new Generator();
93
94
        try {
95
            $generator->generate($context, \file_get_contents($grammar), \file_get_contents($skeleton), $result);
96
        } catch (\Exception $e) {
97
            throw new RuntimeException($e->getMessage(), $e->getCode(), $e);
98
        }
99
    }
100
}
101