Parser examples

Example #1 Simple calculator

<?php 

use Parle\{ParserParserExceptionLexerToken};

$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();
    }
}

Example #2 Parse words out from a sentence

<?php

use Parle\{LexerTokenParserParserException};

$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);

User Contributed Notes

andres1gb at gmail dot com 27-Apr-2020 03:45
The second example (word count) calls a method reduceId(), instead of retrieving the value of the reduceId property.
PHP8中文手册 站长在线 整理 版权归PHP文档组所有