PHPackages                             yui-ezic/z99-lexer - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. yui-ezic/z99-lexer

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

yui-ezic/z99-lexer
==================

Php lexer for Z99 (own Pascal-like programming language).

15PHP

Since Apr 26Pushed 6y ago1 watchersCompare

[ Source](https://github.com/Yui-Ezic/Z99Lexer)[ Packagist](https://packagist.org/packages/yui-ezic/z99-lexer)[ RSS](/packages/yui-ezic-z99-lexer/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

PHP lexer for Z99
=================

[](#php-lexer-for-z99)

Z99 is Pascal-like programming language developed for education purposes. Example of program written on Z99

```
program first
var i: int;
    sum, value : real;
begin
    sum = 0.0;
    i = 1;
    repeat
        read (value);
        sum = sum + value;
        write(i, sum);
        i = i + 1;
    until i  dgt - digit
> chr - character
> def - default
> WS - white space

[![gra3231 tmp](https://user-images.githubusercontent.com/21062493/76415790-8971a680-63a2-11ea-9a0b-93469e8555a0.png)](https://user-images.githubusercontent.com/21062493/76415790-8971a680-63a2-11ea-9a0b-93469e8555a0.png)

For convenience, all final states begin with a minus and are highlighted in blue. 0 is start state.

Create own grammar
------------------

[](#create-own-grammar)

Firstly create the start State.

```
$fsm->addStart(0);
```

Than several intermediate state

```
$fsm->addState(1);
$fsm->addState(2);
```

And add final state which has callback function which handle the substring and adds token to tokens table. The last argument tells the lexer when it's move to the initial state whether to take the next character or not.

```
$keywords = [
    'program', 'var', 'begin',
    'read', 'write', 'repeat',
    'until', 'if', 'then', 'fi'
];
$types = ['int', 'real', 'bool'];
$boolConstants = ['true', 'false'];

$fsm->addFinalState(-2,
    static function (LexerWriterInterface $writer, string $string, int $line)
    use ($keywords, $types, $boolConstants) {
        $index = null;
        $string = substr($string, 0, -1);
        if (in_array($string, $keywords, true)) {
            $token = 'Keyword';
        } elseif (in_array($string, $types, true)) {
            $token = 'Type';
        } elseif (in_array($string, $boolConstants, true)) {
            $token = 'BoolConst';
        } else {
            $token = 'Ident';
            $index = $writer->addIdentifier($string);
        }

        $writer->addToken($line, $string, $token, $index);
    }, false);

$fsm->addFinalState('error',
    static function (LexerWriterInterface $writer, string $string, int $line) {
        throw new LexerException('Unknown char.', $string, $line);
    });
```

Then adds triggers (edges of graph)

```
$fsm->addTrigger(TriggerTypes::LETTER, 0, 1);
$fsm->addTrigger(FSM::DEFAULT_STATE, 0, 'error');

$fsm->addTrigger(TriggerTypes::LETTER, 1, 1);
$fsm->addTrigger(FSM::DEFAULT_STATE, 1, -2);
$fsm->addTrigger(TriggerTypes::DIGIT, 1, 2);

$fsm->addTrigger(FSM::DEFAULT_STATE, 2, -2);
$fsm->addTrigger(TriggerTypes::LETTER, 2, 2);
$fsm->addTrigger(TriggerTypes::DIGIT, 2, 2);
```

And display the graph of states

```
$fsm->visualize();
```

[![gra283B tmp](https://user-images.githubusercontent.com/21062493/76421275-15d49700-63ac-11ea-9c3f-cdabe7a79033.png)](https://user-images.githubusercontent.com/21062493/76421275-15d49700-63ac-11ea-9c3f-cdabe7a79033.png)

Lexer
-----

[](#lexer)

To create tables of tokens, constants and identifiers you need to create Lexer class which receives CharStreamInterface and FSM with our grammar.

```
$stream = new FileStream('example.z99'); // implements CharStreamInterface
$lexer = new Lexer($stream, $fsm);

```

And run a `tokenize()` method

```
try {
    $lexer->tokenize();

    foreach ($lexer->getTokens() as $token) {
        echo $token . PHP_EOL;
    }

    foreach ($lexer->getConstants() as $const) {
        echo $const . PHP_EOL;
    }

    foreach ($lexer->getIdentifiers() as $identifier) {
        echo $identifier . PHP_EOL;
    }

} catch (LexerException $e) {
    echo $e->getMessage() .
        "\n With string: '" . $e->getString() . '\'' .
        "\n in line " . $e->getLine();
}
```

###  Health Score

18

—

LowBetter than 8% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity5

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity34

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/89aacdaef1050f6553a5aeb96c0e0feef5f81421e3309c7f3cb36964c84c6a35?d=identicon)[Yui-Ezic](/maintainers/Yui-Ezic)

---

Top Contributors

[![Yui-Ezic](https://avatars.githubusercontent.com/u/21062493?v=4)](https://github.com/Yui-Ezic "Yui-Ezic (16 commits)")

### Embed Badge

![Health badge](/badges/yui-ezic-z99-lexer/health.svg)

```
[![Health](https://phpackages.com/badges/yui-ezic-z99-lexer/health.svg)](https://phpackages.com/packages/yui-ezic-z99-lexer)
```

###  Alternatives

[robholmes/term-extractor

Term Extractor - a PHP port of Topia's Term Extractor

185.5k](/packages/robholmes-term-extractor)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
