final class Derivation
Restricted visibility: declared "@visibility root". Code outside that scope must not name this declaration.

Derives terminals from a common grammar while reserving enough steps to finish the remaining form.

Properties§

public ?DerivationTrace $trace = null

Occurrences from the most recent derivation, including empty productions.

Methods§

public function __construct(
    private Grammar $grammar,
    private Generator $faker,
    private TerminationAnalyzer $analyzer,
    ?CompletionCosts $completion = null,
    private Closure(int): ?int|null $choose = null,
)

Parameters

$grammarGrammarGrammar being walked
$fakerGeneratorSource of the choices the walk makes freely
$analyzerTerminationAnalyzerAnswers what a production still costs to finish
$completion?CompletionCosts
$chooseClosure(int): ?int|nullOptional choice policy; null results choose the shortest completion
Test cases 18
Calls 2
public function of(string $startSymbol, GenerationPlan<bool> $plan): list<Terminal>

Walks from one symbol until nothing but terminals is left.

Parameters

$startSymbolstringSymbol the walk begins at
$planGenerationPlan<bool>Plan directing the walk

Returns

list<Terminal> Terminals the walk arrived at

Throws

GenerationException When the grammar, the plan, or the step budget leaves no production to take
Test cases 7
Called from 1
Calls 13
public function affordable(
    non-empty-list<Production> $alternatives,
    Production $remainder,
): non-empty-list<Production>

Keeps only the alternatives the walk can still afford to finish.

What is left of the form behind the symbol being rewritten has to be derived too, so the budget an alternative may spend is the step limit less what has been spent and less what the remainder will cost.

Parameters

$alternativesnon-empty-list<Production>Alternatives the grammar and the plan both allow
$remainderProductionWhat the walk still has to derive behind this symbol

Returns

non-empty-list<Production> Alternatives that still leave room to finish

Throws

GenerationException When none of them fits in the remaining budget
Test cases 6
Calls 5
public function selectProduction(
    non-empty-list<Production> $alternatives,
    GenerationPlan<bool> $plan,
): Production

Answers which of the alternatives the walk takes.

Up to the plan's depth the choice is free. Past it the walk is trying to finish, so it takes whichever alternative gets there in the fewest steps, and among equals whichever writes the least.

Parameters

$alternativesnon-empty-list<Production>Alternatives the walk may still take
$planGenerationPlan<bool>Plan directing the walk

Returns

Production Alternative to rewrite with
Test cases 5
Called from 1
Calls 6
public function alternatives(
    NonTerminal $nonTerminal,
    GenerationPlan<bool> $plan,
    int $occurrence,
): non-empty-list<Production>

Finds realizable alternatives satisfying the plan at this occurrence.

Parameters

$nonTerminalNonTerminal
$planGenerationPlan<bool>Plan directing the walk
$occurrenceint

Returns

non-empty-list<Production>

Throws

GenerationException When no alternative satisfies the grammar and plan
Test cases 8
Called from 1
Calls 10
public function completable(
    non-empty-list<Production> $alternatives,
    list<Symbol> $form,
    int $index,
    GenerationPlan<bool> $plan,
    array<string, int> $occurrences = [],
): non-empty-list<Production>

Reserves a complete non-empty continuation when required, independently of lexical handler availability.

Parameters

$alternativesnon-empty-list<Production>
$formlist<Symbol>
$indexint
$planGenerationPlan<bool>
$occurrencesarray<string, int>Occurrences already selected before the pending continuation

Returns

non-empty-list<Production>

Throws

GenerationException When the explicit plan has no affordable completion
Test cases 3
Called from 1
Calls 11
public function affordableCompletion(
    non-empty-list<Production> $alternatives,
    list<Symbol> $form,
    int $index,
    GenerationPlan<bool> $plan,
): non-empty-list<Production>

Checks budget/output lower bounds when the next production is forced; the walk validates subsequent forced steps directly. Looking ahead cannot select a different production here, so it would only repeat the frozen plan's remaining walk.

Parameters

$alternativesnon-empty-list<Production>
$formlist<Symbol>
$indexint
$planGenerationPlan<bool>

Returns

non-empty-list<Production>

Throws

GenerationException When no production can satisfy the remaining budget and output requirement
Test cases 8
Called from 2
Calls 7

Private surface 8§

Implementation details, listed for orientation only.

private const STEP_LIMIT = 5000
private int $steps = 0
private CompletionCosts $completion
private ConstrainedCompletion $constrainedCompletion
private Grammar $grammar
private Generator $faker
private TerminationAnalyzer $analyzer
private Closure(int): ?int|null $choose = null

Test cases 33§

Test cases that cover or call this symbol, from the coverage report and from the analyzed test sources.

Dedicated tests 18
Other tests reaching this symbol 15

Relations§

Instantiated in 1
Method calls 1