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