Quick Start
First, we will create the grammar for our parser.
You can read more about the grammar syntax here.
<?php
use Phplrt\Compiler\Compiler;
$compiler = new Compiler();
$compiler->load(<<<EBNF
%token T_DIGIT \d
%token T_PLUS \+
%token T_MINUS \-
%token T_POW \*
%token T_DIV /
%skip T_WHITESPACE \s+
#Expression
: <T_DIGIT> (Operator() <T_DIGIT>)*
;
#Operator
: <T_PLUS>
| <T_MINUS>
| <T_POW>
| <T_DIV>
;
EBNF);
Execution
In order to quickly check the performance of what has been written, you can use
the simple parse()
method. As a result, it will output the recognized abstract
syntax tree along with the predefined AST classes which can be converted to their
string representation.
<?php
echo $compiler->parse('2 + 2');
//
// Output:
//
// <Expression offset="0">
// <T_DIGIT offset="0">2</T_DIGIT>
// <Operator offset="2">
// <T_PLUS offset="2">+</T_PLUS>
// </Operator>
// <T_DIGIT offset="4">2</T_DIGIT>
// </Expression>
//
Compilation
After your grammar is ready and tested, it should be compiled. After that,
you no longer need the phplrt/compiler
dependency (see https://phplrt.org/docs/installation#runtime-only).
file_put_contents(__DIR__ . '/grammar.php', (string)$compiler->build());
This file will contain your compiled data that can be used in your custom parser.
use Phplrt\Lexer\Lexer;
use Phplrt\Parser\Parser;
use Phplrt\Parser\BuilderInterface;
use Phplrt\Parser\ContextInterface;
$data = require __DIR__ . '/grammar.php';
// Create Lexer from compiled data.
$lexer = new Lexer($data['tokens']['default'], $data['skip']);
// Create AST builder from compiled data.
$builder = new class($data['reducers']) implements BuilderInterface
{
public function __construct(private array $reducers) {}
public function build(ContextInterface $context, $result)
{
$state = $context->getState();
return isset($this->reducers[$state]))
? $this->reducers[$state]($context, $result)
: $result
;
}
};
// Create Parser from compiled data.
$parser = new Parser($lexer, $data['grammar'], [
// Recognition will start from the specified rule.
Parser::CONFIG_INITIAL_RULE => $data['initial'],
// Rules for the abstract syntax tree builder.
// In this case, we use the data found in the compiled grammar.
Parser::CONFIG_AST_BUILDER => $builder,
]);
// Now we are ready to parse any code using the compiled grammar.
$parser->parse(' ..... ');