PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1

APPENDIX B ■ A SIMPLE PARSER


The idea behind this use of the Composite pattern is that a client can build up a grammar in code
that closely matches EBNF notation. Table B–1 shows the parallels between these classes and EBNF
fragments.


Table B–1. Composite Parsers and EBNF


Class EBNF Example Description

AlternationParse orExpr | andExpr Either one or another

SequenceParse 'and' operand A list (all required in order)

RepetitionParse ( eqExpr )* Zero or more required

Now to build some client code to implement the mini-language. As a reminder, here is the EBNF
fragment I presented in Chapter 11:


expr ::= operand (orExpr | andExpr )
operand ::= ( '(' expr ')' | | variable ) ( eqExpr )

orExpr ::= 'or' operand
andExpr ::= 'and' operand
eqExpr ::= 'equals' operand
variable ::= '$'


This simple class builds up a grammar based on this fragment and runs it:

class MarkParse {
private $expression;
private $operand;
private $interpreter;
private $context;


function __construct( $statement ) {
$this->compile( $statement );
}


function evaluate( $input ) {
$icontext = new InterpreterContext();
$prefab = new VariableExpression('input', $input );
// add the input variable to Context
$prefaB–>interpret( $icontext );


$this->interpreter->interpret( $icontext );
$result = $icontext->lookup( $this->interpreter );
return $result;
}


function compile( $statement_str ) {
// build parse tree
$context = new \gi\parse\Context();
$scanner = new \gi\parse\Scanner(
new \gi\parse\StringReader($statement_str), $context );
$statement = $this->expression();

Free download pdf