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()