&reftitle.examples;

## Lexer examples

### Tokenize comma separated integer list

    <?php

    use Parle\Token;
    use Parle\Lexer;
    use Parle\LexerException;

    /* name => id */
    $token = array(
            "COMMA" => 1,
            "CRLF" => 2,
            "DECIMAL" => 3,
    );
    /* id => name */
    $tokenIdToName = array_flip($token);

    $lex = new Lexer;
    $lex->push("[\x2c]", $token["COMMA"]);
    $lex->push("[\r][\n]", $token["CRLF"]);
    $lex->push("[\d]+", $token["DECIMAL"]);
    $lex->build();

    $in = "0,1,2\r\n3,42,5\r\n6,77,8\r\n";

    $lex->consume($in);

    do {
            $lex->advance();
            $tok = $lex->getToken();

            if (Token::UNKNOWN == $tok->id) {
                    throw new LexerException("Unknown token '{$tok->value}' at offset {$lex->marker}.");
            }

            echo "TOKEN: ", $tokenIdToName[$tok->id], PHP_EOL;
    } while (Token::EOI != $tok->id);

### Tokenize assign statement

    <?php

    use Parle\{Token, Lexer};

    $lex = new Lexer;

    $lex->push("\$[a-zA-Z_][a-zA-Z0-9_]*", 1);
    $lex->push("=", 2);
    $lex->push("\d+", 3);
    $lex->push(";", 4);

    $lex->build();

    $lex->consume('$x = 42; $y = 24;');

    do {
        $lex->advance();
        $tok = $lex->getToken();
        var_dump($tok);
    } while (Token::EOI != $tok->id);

## Parser examples

### Simple calculator

    <?php

    use Parle\{Parser, ParserException, Lexer, Token};

    $p = new Parser;
    $p->token("INTEGER");
    $p->left("'+' '-' '*' '/'");

    $p->push("start", "exp");
    $prod_add = $p->push("exp", "exp '+' exp");
    $prod_sub = $p->push("exp", "exp '-' exp");
    $prod_mul = $p->push("exp", "exp '*' exp");
    $prod_div = $p->push("exp", "exp '/' exp");
    $p->push("exp", "INTEGER"); /* Production index unused. */

    $p->build();

    $lex = new Lexer;
    $lex->push("[+]", $p->tokenId("'+'"));
    $lex->push("[-]", $p->tokenId("'-'"));
    $lex->push("[*]", $p->tokenId("'*'"));
    $lex->push("[/]", $p->tokenId("'/'"));
    $lex->push("\\d+", $p->tokenId("INTEGER"));
    $lex->push("\\s+", Token::SKIP);

    $lex->build();

    $exp = array(
        "1 + 1",
        "33 / 10",
        "100 * 45",
        "17 - 45",
    );

    foreach ($exp as $in) {
        if (!$p->validate($in, $lex)) {
            throw new ParserException("Failed to validate input");
        }

        $p->consume($in, $lex);

        while (Parser::ACTION_ERROR != $p->action && Parser::ACTION_ACCEPT != $p->action) {
            switch ($p->action) {
                case Parser::ACTION_ERROR:
                    throw new ParserException("Parser error");
                    break;
                case Parser::ACTION_SHIFT:
                case Parser::ACTION_GOTO:
                case Parser::ACTION_ACCEPT:
                    break;
                case Parser::ACTION_REDUCE:
                    switch ($p->reduceId) {
                        case $prod_add:
                            $l = $p->sigil(0);
                            $r = $p->sigil(2);
                            echo "$l + $r = " . ($l + $r) . "\n";
                            break;
                        case $prod_sub:
                            $l = $p->sigil(0);
                            $r = $p->sigil(2);
                            echo "$l - $r = " . ($l - $r) . "\n";
                            break;
                        case $prod_mul:
                            $l = $p->sigil(0);
                            $r = $p->sigil(2);
                            echo "$l * $r = " . ($l * $r) . "\n";
                            break;
                        case $prod_div:
                            $l = $p->sigil(0);
                            $r = $p->sigil(2);
                        echo "$l / $r = " . ($l / $r) . "\n";
                            break;
                }
                break;
            }
            $p->advance();
        }
    }

### Parse words out from a sentence

    <?php

    use Parle\{Lexer, Token, Parser, ParserException};

    $p = new Parser;
    $p->token("WORD");
    $p->push("START", "SENTENCE");
    $p->push("SENTENCE", "WORDS");
    $prod_word_0 = $p->push("WORDS", "WORDS WORD");
    $prod_word_1 = $p->push("WORDS", "WORD");
    $p->build();

    $lex = new Lexer;
    $lex->push("[^\s]{-}[\.,\:\;\?]+", $p->tokenId("WORD"));
    $lex->push("[\s\.,\:\;\?]+", Token::SKIP);
    $lex->build();

    $in = "Dis-moi où est ton papa?";
    $p->consume($in, $lex);
    do {
        switch ($p->action) {
        case Parser::ACTION_ERROR:
            throw new ParserException("Error");
            break;
        case Parser::ACTION_SHIFT:
        case Parser::ACTION_GOTO:
            /* var_dump($p->trace());*/
            break;
        case Parser::ACTION_REDUCE:
            $rid = $p->reduceId();
            if ($rid == $prod_word_1) {
                var_dump($p->sigil(0));
            } if ($rid == $prod_word_0) {
                var_dump($p->sigil(1));
            }
            break;
        }
        $p->advance();
    } while (Parser::ACTION_ACCEPT != $p->action);