//声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
abstract class AbstractExpression {
public abstract function interpret(Context $context);
}
//(终结符表达式)实现与文法中的终结符相关联的解释操作。实现抽象表达式中所要求的接口,主要是一个interpret()方法。方法中每一个终结符都有一个具体终结表达式与之相对应。
class TerminalExpression extends AbstractExpression {
public function interpret(Context $context) {
echo '终端解释器<br/>';
}
}
//(非终结符表达式),为文法中的非终结符实现解释操作。对文法中每一条规则R1/R2......Rn都需要一个具体的非终结符表达式类。通过实现抽象表达式的interpret()方法实现解释操作。解释操作以递归方式调用上面所提到的代表R1、R2.。。。。Rn中各个符号的实例变量。
class NonterminalExpression extends AbstractExpression {
public function interpret(Context $context) {
echo '非终端解释器<br/>';
}
}
//包含解释器之外的一些全局信息
class Context {
private $input;
private $output;
public function __get($key) {
return isset($this->$key) ? $this->$key : null;
}
public function __set($key, $value) {
$this->$key = $value;
}
}
$context = new Context();
$list[] = new TerminalExpression();
$list[] = new NonterminalExpression();
$list[] = new TerminalExpression();
$list[] = new TerminalExpression();
foreach($list as $exp) {
$exp->interpret($context);
}
//演奏内容
class PlayContext {
//演奏文本
private $text;
public function __get($key) {
return isset($this->$key) ? $this->$key : null;
}
public function __set($key, $value) {
$this->$key = $value;
}
}
//表达式类
abstract class Expression {
//解释器
public function interpret(PlayContext $context) {
if(strlen($context->text) == 0) {
return;
}
//此方法用于当前的演奏文本第一条命令获得命令字母和其参数值。例如‘O 3 E 0.5 G 0.5 A 3’则playKey为O, 而playValue为3
$playKey = substr($context->text, 0, 1);
$context->text = substr($context->text, 2);
$playValue = substr($context->text, 0, strcspn($context->text, ' '));
$context->text = substr($context->text, strcspn($context->text, ' ') + 1);
$this->execute($playKey, $playValue);
}
//执行
public abstract function execute($key, $vaule);
}
//音符类
class Note extends Expression {
public function execute($key, $value) {
$note = '';
switch($key) {
case 'C':
$note = '1';
break;
case 'D':
$note = '2';
break;
case 'E':
$note = '3';
break;
case 'F':
$note = '4';
break;
case 'G':
$note = '5';
break;
case 'A':
$note = '6';
break;
case 'B':
$note = '7';
break;
}
echo $note;
}
}
//音符类
class Scale extends Expression {
public function execute($key, $value) {
$scale = '';
switch($value) {
case '1':
$scale = '低音';
break;
case '2':
$scale = '中音';
break;
case '3':
$scale = '高音';
break;
}
echo $scale;
}
}
//音速类
class Speed extends Expression {
public function execute($key, $value) {
$speed;
if($value < 500) {
$speed = '快速';
} else if($value >= 1000) {
$speed = '慢速';
} else {
$speed = '中速';
}
echo $speed;
}
}
$context = new PlayContext();
//音乐-上海滩
echo '上海滩<br/>';
$context->text = 'T 500 O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 ';
$expression = null;
try {
while(strlen($context->text) > 0) {
$str = substr($context->text, 0, 1);
switch($str) {
case 'O':
$expression = new Scale();
break;
case 'T':
$expression = new Speed();
break;
case 'C':
case 'D':
case 'E':
case 'G':
case 'A':
case 'B':
case 'P':
$expression = new Note();
break;
}
if(!empty($expression)) {
$expression->interpret($context);
}
}
} catch (Exception $e) {
echo $e->getMessage().'<br/>';
}