PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1
APPENDIX B ■ A SIMPLE PARSER

object. If the raw code does not parse, the compile() method throws an exception. Otherwise, it retrieves
the result of compilation as left on the Scanner object’s Context. As you will see shortly, this should be an
Expression object. This result is stored in a property called $interpreter.
The evaluate() method makes a value available to the Expression tree. It does this by predefining a
VariableExpression object named input and registering it with the Context object that is then passed to
the main Expression object. As with variables such as $_REQUEST in PHP, this $input variable is always
available to MarkLogic coders.


■Note See Chapter 11 for more about the VariableExpression class that is part of the Interpreter pattern


example.


The evaluate() method calls the Expression::interpret() method to generate a final result.
Remember, you need to retrieve interpreter results from the Context object.
So far, you have seen how to parse text and how to build a grammar. You also saw in Chapter 11 how
to use the Interpreter pattern to combine Expression objects and process a query. You have not yet seen,
though, how to relate the two processes. How do you get from a parse tree to the interpreter? The answer
lies in the Handler objects that can be associated with Parser objects using Parser::setHandler(). Let’s
take a look at the way to manage variables. I associate a VariableHandler with the Parser in the
variable() method:


$variable->setHandler( new VariableHandler() );


Here is the Handler interface:

namespace gi\parse;


interface Handler {
function handleMatch( Parser $parser,
Scanner $scanner );
}


And here is VariableHandler:

class VariableHandler implements \gi\parse\Handler {
function handleMatch( \gi\parse\Parser $parser, \gi\parse\Scanner $scanner ) {
$varname = $scanner->getContext()->popResult();
$scanner->getContext()->pushResult( new VariableExpression( $varname ) );
}
}


If the Parser with which VariableHandler is associated matches on a scan operation, then
handleMatch() is called. By definition, the last item on the stack will be the name of the variable. I
remove this and replace it with a new VariableExpression object with the correct name. Similar
principles are used to create EqualsExpression objects, LiteralExpression objects, and so on.
Here are the remaining handlers:


class StringLiteralHandler implements \gi\parse\Handler {
function handleMatch( \gi\parse\Parser $parser, \gi\parse\Scanner $scanner ) {
$value = $scanner->getContext()->popResult();
$scanner->getContext()->pushResult( new LiteralExpression( $value ) );
}

Free download pdf