3.3. Interpreter
3.3.1. Purpose
For a given language, it defines the representation of its grammar as “No Terminal Expression” and “Terminal Expression”, as well as an interpreter for the sentences of that language.
3.3.2. Examples
An example of a binary logic interpreter, each definition is defined by its own class
3.3.3. UML Diagram
3.3.4. Code
You can also find this code on GitHub
AbstractExp.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Interpreter;
6
7abstract class AbstractExp
8{
9 abstract public function interpret(Context $context): bool;
10}
Context.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Interpreter;
6
7use Exception;
8
9class Context
10{
11 private array $poolVariable;
12
13 public function lookUp(string $name): bool
14 {
15 if (!key_exists($name, $this->poolVariable)) {
16 throw new Exception("no exist variable: $name");
17 }
18
19 return $this->poolVariable[$name];
20 }
21
22 public function assign(VariableExp $variable, bool $val)
23 {
24 $this->poolVariable[$variable->getName()] = $val;
25 }
26}
VariableExp.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Interpreter;
6
7/**
8 * This TerminalExpression
9 */
10class VariableExp extends AbstractExp
11{
12 public function __construct(private string $name)
13 {
14 }
15
16 public function interpret(Context $context): bool
17 {
18 return $context->lookUp($this->name);
19 }
20
21 public function getName(): string
22 {
23 return $this->name;
24 }
25}
AndExp.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Interpreter;
6
7/**
8 * This NoTerminalExpression
9 */
10class AndExp extends AbstractExp
11{
12 public function __construct(private AbstractExp $first, private AbstractExp $second)
13 {
14 }
15
16 public function interpret(Context $context): bool
17 {
18 return $this->first->interpret($context) && $this->second->interpret($context);
19 }
20}
OrExp.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Interpreter;
6
7/**
8 * This NoTerminalExpression
9 */
10class OrExp extends AbstractExp
11{
12 public function __construct(private AbstractExp $first, private AbstractExp $second)
13 {
14 }
15
16 public function interpret(Context $context): bool
17 {
18 return $this->first->interpret($context) || $this->second->interpret($context);
19 }
20}
3.3.5. Test
Tests/InterpreterTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Interpreter\Tests;
6
7use DesignPatterns\Behavioral\Interpreter\AndExp;
8use DesignPatterns\Behavioral\Interpreter\Context;
9use DesignPatterns\Behavioral\Interpreter\OrExp;
10use DesignPatterns\Behavioral\Interpreter\VariableExp;
11use PHPUnit\Framework\TestCase;
12
13class InterpreterTest extends TestCase
14{
15 private Context $context;
16 private VariableExp $a;
17 private VariableExp $b;
18 private VariableExp $c;
19
20 public function setUp(): void
21 {
22 $this->context = new Context();
23 $this->a = new VariableExp('A');
24 $this->b = new VariableExp('B');
25 $this->c = new VariableExp('C');
26 }
27
28 public function testOr()
29 {
30 $this->context->assign($this->a, false);
31 $this->context->assign($this->b, false);
32 $this->context->assign($this->c, true);
33
34 // A ∨ B
35 $exp1 = new OrExp($this->a, $this->b);
36 $result1 = $exp1->interpret($this->context);
37
38 $this->assertFalse($result1, 'A ∨ B must false');
39
40 // $exp1 ∨ C
41 $exp2 = new OrExp($exp1, $this->c);
42 $result2 = $exp2->interpret($this->context);
43
44 $this->assertTrue($result2, '(A ∨ B) ∨ C must true');
45 }
46
47 public function testAnd()
48 {
49 $this->context->assign($this->a, true);
50 $this->context->assign($this->b, true);
51 $this->context->assign($this->c, false);
52
53 // A ∧ B
54 $exp1 = new AndExp($this->a, $this->b);
55 $result1 = $exp1->interpret($this->context);
56
57 $this->assertTrue($result1, 'A ∧ B must true');
58
59 // $exp1 ∧ C
60 $exp2 = new AndExp($exp1, $this->c);
61 $result2 = $exp2->interpret($this->context);
62
63 $this->assertFalse($result2, '(A ∧ B) ∧ C must false');
64 }
65}