phplrt/phplrt

View on GitHub
README.md

Summary

Maintainability
Test Coverage
<p align="center">
    <a href="https://phplrt.org/">
        <img src="https://avatars.githubusercontent.com/u/49816277?s=256&v=4" width="128" alt="Phplrt" />
    </a>
</p>
<p align="center">
    <a href="https://packagist.org/packages/phplrt/phplrt"><img src="https://poser.pugx.org/phplrt/phplrt/require/php?style=for-the-badge" alt="PHP 8.1+"></a>
    <a href="https://packagist.org/packages/phplrt/phplrt"><img src="https://poser.pugx.org/phplrt/phplrt/version?style=for-the-badge" alt="Latest Stable Version"></a>
    <a href="https://packagist.org/packages/phplrt/phplrt"><img src="https://poser.pugx.org/phplrt/phplrt/v/unstable?style=for-the-badge" alt="Latest Unstable Version"></a>
    <a href="https://packagist.org/packages/phplrt/phplrt"><img src="https://poser.pugx.org/phplrt/phplrt/downloads?style=for-the-badge" alt="Total Downloads"></a>
    <a href="https://raw.githubusercontent.com/phplrt/phplrt/master/LICENSE.md"><img src="https://poser.pugx.org/phplrt/phplrt/license?style=for-the-badge" alt="License MIT"></a>
</p>
<p align="center">
    <a href="https://github.com/phplrt/phplrt/actions"><img src="https://github.com/phplrt/phplrt/workflows/build/badge.svg?branch=3.x&event=push"></a>
</p>

## Introduction

The phplrt is a set of tools for programming languages recognition. The library 
provides lexer, parser, grammar compiler, library for working with errors, 
text analysis and so on.

## Installation

Phplrt is available as composer repository and can be 
installed using the following command in a root of your project:

```bash
$ composer require phplrt/phplrt
```

More detailed installation instructions [are here](https://phplrt.org/docs/installation).

## Documentation

- https://phplrt.org

## Quick Start

First, we will create the grammar for our parser. 

> You can read more about the grammar syntax [here](https://phplrt.org/docs/compiler/grammar).

```php
<?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
<?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).

```php
file_put_contents(__DIR__ . '/grammar.php', (string)$compiler->build());
```

This file will contain your compiled data that can be used in your custom parser.

```php
use Phplrt\Lexer\Lexer;
use Phplrt\Parser\Parser;
use Phplrt\Parser\BuilderInterface;
use Phplrt\Parser\Context;

$data = require __DIR__ . '/grammar.php';

// Create Lexer from compiled data
$lexer = new Lexer($data['tokens']['default'], $data['skip']);

// 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 => new class($data['reducers']) implements BuilderInterface {
        public function __construct(private array $reducers) {}

        public function build(Context $context, $result)
        {
            $state = $context->getState();

            return isset($this->reducers[$state])) 
                ? $this->reducers[$state]($context, $result)
                : $result
            ;
        }
    }
]);

// Now we are ready to parse any code using the compiled grammar

$parser->parse(' ..... ');
```