PHP code example of ryangjchandler / lexical

1. Go to this page and download the library: Download ryangjchandler/lexical library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

ryangjchandler / lexical example snippets


enum TokenType
{
    case Number;
    case Add;
    case Subtract;
    case Multiply;
    case Divide;
}

enum TokenType
{
    #[Regex("[0-9]+")]
    case Number;
    
    #[Literal("+")]
    case Add;
    
    #[Literal("-")]
    case Subtract;
    
    #[Literal("*")]
    case Multiply;

    #[Literal("/")]
    case Divide;
}

$lexer = (new LexicalBuilder)
    ->readTokenTypesFrom(TokenType::class)
    ->build();

$tokens = $lexer->tokenise('1+2'); // -> [[TokenType::Number, '1', Span(0, 1)], [TokenType::Add, '+', Span(1, 2)], [TokenType::Number, '2', Span(2, 3)]]

#[Lexer(skip: "[ \t\n\f]+")]
enum TokenType
{
    // ...
}

try {
    $tokens = $lexer->tokenise();
} catch (UnexpectedCharacterException $e) {
    dd($e->character, $e->position);
}

enum TokenType
{
    // ...

    #[Error]
    case Error;
}

$tokens = $lexer->tokenise('1 % 2'); // -> [[TokenType::Number, '1'], [TokenType::Error, '%'], [TokenType::Number, '2']]

class Token
{
    public function __construct(
        public readonly TokenType $type,
        public readonly string $literal,
        public readonly Span $span,
    ) {}
}

$lexer = (new LexicalBuilder)
    ->readTokenTypesFrom(TokenType::class)
    ->produceTokenUsing(fn (TokenType $type, string $literal, Span $span) => new Token($type, $literal, $span))
    ->build();

$lexer->tokenise('1 + 2'); // -> [Token { type: TokenType::Number, literal: "1" }, ...]

use RyanChandler\Lexical\Attributes\Custom;
use RyanChandler\Lexical\InputSource;

enum Literals
{
    #[Custom(StringTokenProducer::class)]
    case String;
}

class StringTokenProducer implements TokenProducerInterface
{
    public function produce(InputSource $source): ?string
    {
        // 
    }
}

class StringTokenProducer implements TolerantTokenProducerInterface
{
    public function canProduce(InputSource $source): int|false
    {
        $matches = $source->match('/"/', PREG_OFFSET_CAPTURE);

        if (! $matches) {
            return false;
        }

        return $matches[0][1];
    }

    public function produce(InputSource $source): ?string
    {
        // If we're not looking at a double quote, return since we can't produce a token here.
        if ($source->current() !== '"') {
            return null;
        }

        // Place an offset marker in case we need to rewind at any point.
        $source->mark();

        // Consume the " character.
        $token = $source->consume();

        while ($source->current() !== '"') {
            // If we reach the end of the file before we find a closing double-quote,
            // we can rewind to the marker and return early.
            if ($source->isEof()) {
                $source->rewind();

                return null;
            }

            // Consume the current character.
            $token .= $source->consume();
        }

        // If we reach this point, we must be at a double-quote character since the
        // loop above has finished and we haven't returned yet.
        $token .= $source->consume();

        // Return the consumed text and let the Lexer handle the rest.
        return $token;
    }
}