Skip to content

Instantly share code, notes, and snippets.

@pope
Created January 26, 2011 03:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pope/796171 to your computer and use it in GitHub Desktop.
Save pope/796171 to your computer and use it in GitHub Desktop.
A simple scanner that uses regular expressions to parse strings
<?php
class Scanner
{
private $_scans;
private $_idx;
public function __construct(array $scans)
{
$this->_scans = array();
foreach ($scans as $regex => $callback) {
$regex = '/(^' . $regex . ')/';
$this->_scans[$regex] = $callback;
}
}
public function scan($str)
{
$idx = 0;
$cont = true;
do {
$cont = false;
foreach ($this->_scans as $regex => $callback) {
$matches = array();
if (preg_match($regex, substr($str, $idx), $matches)) {
$idx += strlen($matches[0]);
if (is_callable($callback)) {
call_user_func($callback, $this, $matches[0]);
}
$cont = true;
break;
}
}
} while ($cont);
// Was this successfully parsed?
return ($idx === strlen($str));
}
}
// if __name__ == "__main__":
if (!debug_backtrace()) {
class Tokenizer
{
public $tokens;
public function __construct()
{
$this->tokens = array();
}
public function identifier(Scanner $scanner, $token)
{
$this->tokens[] = "(IDENT, $token)";
}
public function operator(Scanner $scanner, $token)
{
$this->tokens[] = "(OPERATOR, $token)";
}
public function digit(Scanner $scanner, $token)
{
$this->tokens[] = "(DIGIT, $token)";
}
public function endStmnt(Scanner $scanner, $token)
{
$this->tokens[] = 'END_STATEMENT';
}
}
$tokenizer = new Tokenizer;
$scanner = new Scanner(
array(
'[a-zA-Z_]\w*' => array($tokenizer, 'identifier'),
'[+\-*=]' => array($tokenizer, 'operator'),
'[0-9]+(\.[0-9]+)?' => array($tokenizer, 'digit'),
';' => array($tokenizer, 'endStmnt'),
'\s+' => null
)
);
$res = $scanner->scan('foo = 5.5 * 30; bar = bar - 60;');
if ($res) { echo "TRUE\n"; } else { echo "FALSE\n"; }
echo join("\n", $tokenizer->tokens);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment