APPENDIX B ■ A SIMPLE PARSER
As you can see, this is just a simple stack, a convenient noticeboard for parsers to work with. It
performs a similar job to that of the context class used in the Interpreter pattern, but it is not the same
class.
Notice that the Scanner does not itself work with a file or string. Instead it requires a Reader object.
This would allow me to easily to swap in different sources of data. Here is the Reader interface and an
implementation: StringReader:
namespace gi\parse;
abstract class Reader {
abstract function getChar();
abstract function getPos();
abstract function pushBackChar();
}
class StringReader extends Reader {
private $in;
private $pos;
function __construct( $in ) {
$this->in = $in;
$this->pos = 0;
}
function getChar() {
if ( $this->pos >= strlen( $this->in ) ) {
return false;
}
$char = substr( $this->in, $this->pos, 1 );
$this->pos++;
return $char;
}
function getPos() {
return $this->pos;
}
function pushBackChar() {
$this->pos--;
}
function string() {
return $this->in;
}
}
This simply reads from a string one character at a time. I could easily provide a file-based version, of
course.
Perhaps the best way to see how the Scanner might be used is to use it. Here is some code to break
up the example statement into tokens:
$context = new \gi\parse\Context();
$user_in = "\$input equals '4' or \$input equals 'four'";