Skip to content

Instantly share code, notes, and snippets.

@GDmac
Created September 25, 2012 19:04
Show Gist options
  • Save GDmac/3783791 to your computer and use it in GitHub Desktop.
Save GDmac/3783791 to your computer and use it in GitHub Desktop.
LOCO parser library MatchParser
<?php
class MatchParser extends MonoParser {
private $first;
private $second;
public function __construct($internals, $first, $second, $callback = null) {
if($internals[$first] !== $internals[$second]) {
throw new GrammarException("Can't create a ".get_class()." first and second should be the same type");
}
$this->first = $first;
$this->second = $second;
$this->string = "new ".get_class()."(".serialiseArray($internals).")";
parent::__construct($internals, $callback);
}
// Default callback (this should be used rarely) returns all arguments as
// an array. In the majority of cases the user should specify a callback.
public function defaultCallback() {
return func_get_args();
}
public function getResult($string, $i = 0) {
$j = $i;
$args = array();
foreach($this->internals as $parser) {
$match = $parser->match($string, $j);
$j = $match["j"];
$args[] = $match["value"];
}
if($args[$this->first] !== $args[$this->second]) {
throw new ParseFailureException("first and second don't match", $i, $string);
}
return array("j" => $j, "args" => $args);
}
// First-set is built up as follows...
function firstSet() {
$firstSet = array();
foreach($this->internals as $internal) {
// The first $internal is always in the first-set
$firstSet[] = $internal;
// If $internal was nullable, then the next internal in the
// list is also in the first-set, so continue the loop.
// Otherwise we are done.
if(!$internal->nullable) {
break;
}
}
return $firstSet;
}
// only nullable if everything in the list is nullable
public function evaluateNullability() {
foreach($this->internals as $internal) {
if(!$internal->nullable) {
return false;
}
}
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment