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 ')' |
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();