<?php 
/** 
 * This file contains the TextParser class. 
 *  
 * PHP Version 5.3 
 *  
 * @category Text 
 * @package  TextParser 
 * @author   Gonzalo Chumillas <gonzalo@soloproyectos.com> 
 * @license  https://raw.github.com/soloproyectos/core/master/LICENSE BSD 2-Clause License 
 * @link     https://github.com/soloproyectos/core 
 */ 
namespace com\soloproyectos\common\text\parser; 
use com\soloproyectos\common\text\parser\exception\TextParserException; 
use com\soloproyectos\common\text\tokenizer\TextTokenizer; 
 
/** 
 * class TextParser 
 *  
 * This class is for parsing purpose. 
 *  
 * @category Text 
 * @package  TextParser 
 * @author   Gonzalo Chumillas <gonzalo@soloproyectos.com> 
 * @license  https://raw.github.com/soloproyectos/core/master/LICENSE BSD 2-Clause License 
 * @link     https://github.com/soloproyectos/core 
 */ 
abstract class TextParser extends TextTokenizer 
{ 
    /** 
     * Non-geedy parsing. 
     * This flag indicates that we want to perform a "non-greedy" parsing. This flag 
     * is similar to the PCRE_UNGREEDY modifier in regular expressions. 
     */ 
    const UNGREEDY = 0x4; 
     
    /** 
     * String to be parsed or a TextParser object. 
     * @var string|TextParser 
     */ 
    private $_target; 
     
    /** 
     * Flags. 
     * @var integer 
     */ 
    private $_flags; 
     
    /** 
     * Constructor. 
     *  
     * @param string|TextParser $target Target object 
     * @param integer           $flags  Flags (default is 0, accepts: 
     *                                  TextParser::UNGREEDY) 
     */ 
    public function __construct($target, $flags = 0) 
    { 
        $this->_target = $target; 
        $this->_flags = $flags; 
         
        if ($this->_target instanceof Parser) { 
            parent::__construct($target->getString(), $flags); 
            $this->offset = $target->getOffset(); 
        } else { 
            parent::__construct($target, $flags); 
        } 
    } 
     
    /** 
     * Evaluates an expression. 
     *  
     * This function is called by the 'TextParser::parse()' function. 
     *  
     * @see TextParser::parse() 
     * @return mixed 
     */ 
    abstract protected function evaluate(); 
     
    /** 
     * Parses a string. 
     *  
     * <p>This function parses a string and throws an exception if unsuccessful. For 
     * example:</p> 
     *  
     * <pre>// parses a string 
     * $p = new MyCustomParser($string); 
     * try { 
     *     $info = $p->parse(); 
     * } catch(TextParserException $e) { 
     *     echo $e->getPrintableMessage(); 
     * } 
     *  
     * if (!$info) { 
     *     echo "This is not a valid expressión"; 
     * } else { 
     *     print_r($info); 
     * } 
     * </pre> 
     *  
     * @param string $string String target (default is "") 
     *  
     * @throws Exception 
     * @return mixed 
     */ 
    public function parse($string = "") 
    { 
        $this->offset = 0; 
        $this->string = func_num_args() > 0 ? $string : $this->string; 
         
        $ungreedy = TextParser::UNGREEDY & $this->_flags; 
        $ret = $this->evaluate(); 
         
        if ($ret) { 
            if ($this->_target instanceof TextParser) { 
                $this->_target->setOffset($this->offset); 
            } elseif (!$ungreedy && !$this->end()) { 
                throw new TextParserException("Unrecognized expression", $this); 
            } 
        } 
         
        return $ret; 
    } 
     
    /** 
     * Does the next thing satisfies a given method? 
     *  
     * Matches the string against a function and moves the offset forward if the 
     * function returns true. 
     *  
     * @param string $methodName Method name 
     *  
     * @throws TextParserException 
     * @return mixed 
     */ 
    protected function is($methodName /*, $arg1, $arg2, $arg3 ... */) 
    { 
        if (!method_exists($this, $methodName)) { 
            throw new TextParserException( 
                "The method `$methodName` does not exist" 
            ); 
        } 
         
        if (!is_callable(array($this, $methodName))) { 
            throw new TextParserException( 
                "The method `$methodName` is inaccessible" 
            ); 
        } 
         
        // saves offset 
        $offset = $this->offset; 
         
        // calls user function 
        $ret = call_user_func_array( 
            array($this, $methodName), 
            array_slice(func_get_args(), 1) 
        ); 
         
        // restores offset 
        if (!$ret) { 
            $this->offset = $offset; 
        } 
         
        return $ret; 
    } 
} 
 
 |