Parsing

Directives Registry

The directives registry tells Forte which @word sequences to recognize as Blade directives and how they relate structurally, such as whether they open blocks, close blocks, require arguments, or act as conditions. Forte ships with a default set that covers built-in Blade directives, and you can extend it with your own.

#Default Directives

Directives::withDefaults() creates a registry pre-loaded from Forte's bundled JSON definitions. It covers every standard Blade directive (@if, @foreach, @section, @yield, etc.):

1<?php
2
3use Forte\Parser\Directives\Directives;
4
5$registry = Directives::withDefaults();
6
7$registry->isDirective('if'); // true
8$registry->isDirective('foreach'); // true
9$registry->isDirective('yield'); // true
10$registry->isDirective('custom'); // false

To see all registered directive names, use allDirectives. It returns an associative array keyed by directive name:

1<?php
2
3use Forte\Parser\Directives\Directives;
4
5$registry = Directives::withDefaults();
6$all = $registry->allDirectives();

#Querying the Registry

Use getDirective to retrieve a DiscoveredDirective for a specific name. It returns null for unknown directives:

1<?php
2
3use Forte\Parser\Directives\ArgumentRequirement;
4use Forte\Parser\Directives\Directives;
5use Forte\Parser\Directives\StructureRole;
6
7$registry = Directives::withDefaults();
8$if = $registry->getDirective('if');
9
10$if->name; // "if"
11$if->role; // StructureRole::Opening
12$if->args; // ArgumentRequirement::Required
13$if->isCondition; // true
14$if->terminators; // ["elseif", "endif"]
15
16$registry->getDirective('nonexistent'); // null

The registry also provides convenience methods for querying directive relationships:

1<?php
2
3use Forte\Parser\Directives\Directives;
4
5$registry = Directives::withDefaults();
6
7$registry->isCondition('if'); // true
8$registry->isCondition('foreach'); // false
9
10$registry->isPaired('foreach'); // true (has exactly one terminator)
11$registry->isPaired('yield'); // false (standalone)
12$registry->isPaired('if'); // false (has multiple terminators: elseif, endif)
13
14$registry->getTerminator('foreach'); // "endforeach"
15$registry->getTerminators('if'); // ["elseif", "endif"]

#Accept-All Mode

When you want Forte to parse any @word pattern as a directive, even custom ones it doesn't know about, use accept-all mode. This is useful for lenient parsing or when the full set of directives isn't known ahead of time:

1<?php
2
3use Forte\Parser\Directives\Directives;
4
5$registry = Directives::acceptAll();
6
7$registry->acceptsAllDirectives(); // true
8$registry->isDirective('anything'); // true
9$registry->isDirective('custom'); // true

Empty registry
Directives::acceptAll creates an empty registry with accept-all enabled. Because no directive definitions are loaded, structural analysis (block pairing for @if...@endif, etc.) will not work. If you need both accept-all and block pairing, call setAcceptAll(true) on a registry created with withDefaults() instead.

You can also toggle accept-all on an existing registry:

1<?php
2
3$registry = Directives::withDefaults();
4$registry->setAcceptAll(true);
5
6$registry->isDirective('anything'); // true

#Registering Custom Directives

Use registerDirective to add a directive that Forte doesn't know about. The directive will be registered with Optional arguments and no structural role:

1<?php
2
3use Forte\Parser\Directives\ArgumentRequirement;
4use Forte\Parser\Directives\Directives;
5use Forte\Parser\Directives\StructureRole;
6
7$registry = Directives::withDefaults();
8$registry->registerDirective('myDirective');
9
10$registry->isDirective('mydirective'); // true (names are lowercased)
11
12$custom = $registry->getDirective('mydirective');
13$custom->args; // ArgumentRequirement::Optional
14$custom->role; // StructureRole::None
15$custom->isCondition; // false
16$custom->terminators; // []

Directive names are normalized to lowercase. Registering 'myDirective' stores it as 'mydirective'.

If you need Forte to recognize directives registered in Laravel's Blade compiler, use syncLaravelDirectives on a registry that's part of your ParserOptions:

1<?php
2
3use Forte\Parser\Directives\Directives;
4
5$registry = Directives::withDefaults();
6$registry->syncLaravelDirectives();

#DiscoveredDirective

Each entry in the registry is a DiscoveredDirective with these public properties:

Property Type Description
name string The lowercased directive name (without @)
args ArgumentRequirement Whether arguments are required, optional, or not allowed
role StructureRole The directive's structural role in block nesting
isCondition bool Whether this is a condition directive (@if, @unless, etc.)
terminators string[] Names of directives that can terminate this one
terminator ?string The primary terminator (last in the list)

#ArgumentRequirement

The ArgumentRequirement enum describes whether a directive accepts parenthesized arguments:

Case Meaning Example
Required Arguments are mandatory @if ($condition)
Optional Arguments are allowed but not required @php or @php($var)
NotAllowed Arguments are not permitted @endif

#StructureRole

The StructureRole enum describes how a directive participates in block nesting:

Case Meaning Example
Opening Opens a new block @if, @foreach
Closing Closes a block @endif, @endforeach
Intermediate Appears between open and close @else
Mixed Can act as both closer and opener @elseif
None No structural role, standalone @yield, @include
1<?php
2
3use Forte\Parser\Directives\ArgumentRequirement;
4use Forte\Parser\Directives\StructureRole;
5
6// ArgumentRequirement cases
7ArgumentRequirement::Required; // Arguments mandatory
8ArgumentRequirement::Optional; // Arguments allowed
9ArgumentRequirement::NotAllowed; // No arguments
10
11// StructureRole cases
12StructureRole::Opening; // Opens a block
13StructureRole::Closing; // Closes a block
14StructureRole::Intermediate; // Between open/close
15StructureRole::Mixed; // Opens and closes
16StructureRole::None; // Standalone

#See also

  • Documents: Parse templates using the configured registry
  • Directives: Working with directive nodes in the AST
  • Parser Options: Passing a custom registry to Forte::parse()