解析器模式:解析脚本的语言解析器。
php源于c语言,其实是用c语言解析了php脚本,那么php有是如何解析其他语言的呢,看看面向对象的魅力所在吧。
现在解析这样一句话:
$input equals "4" or $input equals "four"
$input是变量,equals是等于操作符,or和and是布尔操作符。这个语言成为MarkLogic。这里不讨论输入的问题,只讨论这句话的输出问题
首先创建一个表达式基类
abstract class Expression{
private static $keycount=0;
private $key;
abstract function interpret(InterpreterContext $content);
function getKey()
{
if( !isset($this->key))
{
self::$keycount++;
$this->key = self::$keycount;
}
return $this->key;
}
}
然后做文字扩展和解析器
class LiteralExpression extends Expression{
private $value;
function __construct( $value )
{
$this->value = $value;
}
function interpret(InterpreterContext $content){
$content->replace($this,$this->value);
}
}
class InterpreterContext{
private $expressionstore = array();
function replace(Expression $exp,$value)
{
$this->expressionstore[$exp->getKey()]=$value;
$this->expressionstore[$exp->getKey()]."\n";
}
function lookup(Expression $exp)
{
return $this->expressionstore[$exp->getKey()];
}
}
然后做变量和布尔表达式扩展
class VariableExpression extends Expression{
private $name;
private $val;
function __construct($name,$val=null)
{
$this->name = $name;
$this->val = $val;
}
function interpret(InterpreterContext $context){
if(! is_null($this->val))
{
$context->replace($this,$this->val);
$this->val = null;
}
}
function setValue($value)
{
$this->val = $value;
}
function getKey(){
return $this->name;
}
}
abstract class OperatorExpression extends Expression{
protected $l_op;
protected $r_op;
function __construct(Expression $lp,Expression $rp)
{
$this->l_op = $lp;
$this->r_op = $rp;
}
function interpret(InterpreterContext $context){
$this->l_op->interpret($context);
$this->r_op->interpret($context);
$result_l = $context->lookup($this->l_op);
$result_r = $context->lookup($this->r_op);
$this->doInterpret($context,$result_l,$result_r);
}
protected abstract function doInterpret(InterpreterContext $context,
$result_l,
$result_r);
}
class EqualsExpression extends OperatorExpression{
protected function doInterpret(InterpreterContext $context, $result_l, $result_r){
$context->replace($this,$result_l == $result_r);
}
}
class BoolOrExpression extends OperatorExpression{
protected function doInterpret(InterpreterContext $context, $result_l, $result_r){
$context->replace($this,$result_l || $result_r);
}
}
class BoolAndExpression extends OperatorExpression{
protected function doInterpret(InterpreterContext $context, $result_l, $result_r){
$context->replace($this,$result_l && $result_r);
}
}
下面运行一下:
$context = new InterpreterContext();
$input = new VariableExpression('input');
$statement = new BoolOrExpression(new EqualsExpression( $input,new LiteralExpression('four')), new EqualsExpression( $input,new LiteralExpression('4')));
foreach(array('four','4','52') as $val){
$input->setValue($val);
print "$val:\n";
$statement->interpret( $context );
if($context->lookup($statement)){
print "top marks\n\n";
} else{
print "dunce hat on\n\n";
}
}
结果如下:
four:
top marks
4:
top marks
52:
dunce hat on
其中array('four','4','52')分别作为input的value,和LiteralExpression比较,如果有问题讨论就可以私聊