TranslationScheme::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Remorhaz\UniLex\Example\Brainfuck\Grammar;
6
7
use Remorhaz\UniLex\Example\Brainfuck\Exception;
8
use Remorhaz\UniLex\Example\Brainfuck\Command\LoopCommand;
9
use Remorhaz\UniLex\Example\Brainfuck\Command\OutputCommand;
10
use Remorhaz\UniLex\Example\Brainfuck\Runtime;
11
use Remorhaz\UniLex\Example\Brainfuck\Command\SetCommandIndexCommand;
12
use Remorhaz\UniLex\Example\Brainfuck\Command\ShiftDataIndexCommand;
13
use Remorhaz\UniLex\Example\Brainfuck\Command\ShiftDataValueCommand;
14
use Remorhaz\UniLex\Grammar\SDD\TranslationSchemeInterface;
15
use Remorhaz\UniLex\Parser\Production;
16
use Remorhaz\UniLex\Parser\Symbol;
17
use Remorhaz\UniLex\Lexer\Token;
18
use Throwable;
19
20
class TranslationScheme implements TranslationSchemeInterface
21
{
22
    private $runtime;
23
24
    public function __construct(Runtime $runtime)
25
    {
26
        $this->runtime = $runtime;
27
    }
28
29
    /**
30
     * @param Production $production
31
     * @throws Exception
32
     */
33
    public function applyProductionActions(Production $production): void
34
    {
35
        $hash = "{$production->getHeader()->getSymbolId()}.{$production->getIndex()}";
36
        switch ($hash) {
37
            case SymbolType::NT_LOOP . ".0":
38
                try {
39
                    $loopCommand = $production
40
                        ->getSymbol(0)
41
                        ->getAttribute('loop_command');
42
                } catch (Throwable $e) {
43
                    throw new Exception("Loop start command not found", 0, $e);
44
                }
45
                if (!$loopCommand instanceof LoopCommand) {
46
                    throw new Exception("Invalid loop start command");
47
                }
48
                $command = new SetCommandIndexCommand($this->runtime, $loopCommand->getIndex());
49
                $this->runtime->addCommand($command);
50
                $loopCommand->setEndLoopIndex($command->getIndex());
51
                break;
52
        }
53
    }
54
55
    public function applySymbolActions(Production $production, int $symbolIndex): void
56
    {
57
    }
58
59
    /**
60
     * @param Symbol $symbol
61
     * @param Token $token
62
     * @throws Exception
63
     */
64
    public function applyTokenActions(Symbol $symbol, Token $token): void
65
    {
66
        switch ($token->getType()) {
67
            case TokenType::NEXT:
68
                $command = new ShiftDataIndexCommand($this->runtime, 1);
69
                $this->runtime->addCommand($command);
70
                break;
71
72
            case TokenType::PREV:
73
                $command = new ShiftDataIndexCommand($this->runtime, -1);
74
                $this->runtime->addCommand($command);
75
                break;
76
77
            case TokenType::INC:
78
                $command = new ShiftDataValueCommand($this->runtime, 1);
79
                $this->runtime->addCommand($command);
80
                break;
81
82
            case TokenType::DEC:
83
                $command = new ShiftDataValueCommand($this->runtime, -1);
84
                $this->runtime->addCommand($command);
85
                break;
86
87
            case TokenType::OUTPUT:
88
                $command = new OutputCommand($this->runtime);
89
                $this->runtime->addCommand($command);
90
                break;
91
92
            case TokenType::LOOP:
93
                $command = new LoopCommand($this->runtime);
94
                $this->runtime->addCommand($command);
95
                try {
96
                    $symbol->setAttribute('loop_command', $command);
97
                } catch (Throwable $e) {
98
                    throw new Exception("Failed to setup loop calculation");
99
                }
100
                break;
101
        }
102
    }
103
}
104