packages/sql-faker/src/Generation/Token/TerminalMappingRule.php
1<?php
2
3declare(strict_types=1);
4
5namespace SqlFaker\Generation\Token;
6
7use Override;
8
9/**
10 * Maps a direct terminal child of one grammar production to a declared contextual domain.
11 */
12final class TerminalMappingRule implements RewriteRule
13{
14 /**
15 * Binds a structural match and its source-defined replacement independently of dialect dispatch.
16 */
17 public function __construct(
18 private readonly string $scope,
19 private readonly string $from,
20 private readonly string $to,
21 private readonly string $source,
22 ) {
23 }
24
25 /**
26 * Replaces only direct children; identical terminals inside nested expressions remain unchanged.
27 */
28 #[Override]
29 public function rewrite(TerminalSequence $sequence): TerminalSequence
30 {
31 foreach ($sequence->terminals as $index => $terminal) {
32 if ($terminal->name === $this->from && ($terminal->rules[count($terminal->rules) - 1] ?? null) === $this->scope) {
33 $sequence = $sequence->replace($index, 1, [$terminal->replaced($this->to, $this->source)], $this->source);
34 }
35 }
36 return $sequence;
37 }
38}
39