BetterReg.php
<?php
// namespace Taeluf;
foreach (scandir(__DIR__) as $file){
if (is_dir(__DIR__.'/'.$file))continue;
require_once(__DIR__.'/'.$file);
}
interface BetterRegInterface {
// to actually call publicly
public function parseReg($regex, $namespace='');
public function matchReg($key,$string,...$args);
// to set/get simple data
public function setRegData($data);
public function setRegParser($parser);
public function getRegParser();
public function getRegData($data);
//extensibility
public function regFunctionFound($function, $namespace);
public function regFunctionCall($function, $namespace);
public function regMatchFound($key, $string, $func, $match,$allMatches);
}
trait BetterRegShorthandsTrait {
public function parse($regex, $namespace=''){
return $this->parseReg($regex,$namespace);
}
public function match($key, $string,...$args){
return $this->matchReg($key,$string,...$args);
}
}
trait BetterRegTrait {
protected $parser;
protected $regexData = [];
public function __construct($dataSet){
$this->setRegData($dataSet);
$this->setRegParser(new \BetterReg\Parser);
}
public function regFunctionFound($function, $namespace){
return $this->regFunctionCall($function,$namespace);
}
public function regFunctionCall($function, $namespace){
$target = 'reg'.ucfirst($function->name);
if (!method_exists($this,$target)){
$func = $function->name;
$class = get_class($this);
throw new \Exception("You must implement '$target' on '$class' to handle regex function '$func'");
}
return $this->$target($namespace,...$function->args);
}
public function regMatchFound($key, $string, $func, $match,$allMatches,$args=[]){
//delegate to function
$info['key']=$key;
$info['string']=$string;
$info['func']=$func;
$info['match'] = $match;
$info['allMatches'] = $allMatches;
$captures = array_slice($match,1);
$ret = $this->$func($info,...$args, ...$captures);
return $ret;
}
public function matchReg($key, $string,...$args){
$regex = $this->getRegData($key);
// echo "\nName:$name\n\n";
$func = preg_replace('/[^a-zA-Z]/','_',$key);
$func = explode('_',$func);
$func = array_map('ucfirst',$func);
$func = implode('_',$func);
$func = 'match'.$func;
if (!method_exists($this, $func)){
$class = get_class($this);
throw new \Exception("You must implement '$func' on '$class' to match '$key'");
}
$didMatch = preg_match_all($regex, $string, $matches, PREG_SET_ORDER);
if (!$didMatch){
return false;
}
foreach ($matches as $key => $match){
$ret[] = $this->regMatchFound($key, $string, $func, $match, $matches, $args);
}
return $ret;
}
public function parseReg($regex,$namespace=''){
$parsed = $this->getRegParser()->parse($regex);
// expecting
// [ 'functions' => [list of functions to call],
// 'sourceReg' => 'long regex string'
// ]
$dirtyReg = $parsed['sourceReg'];
$cleanReg = $parsed['cleanReg'];
foreach ($parsed['functions'] as $f){
// expecting $f to be
// [ 'name'=> 'funcName',
// 'argString'=> 'unparsed, list, of args',
// 'definition' => '::funcName(unparsed, list, of args)'
// 'args' => ['unparsed', 'list', 'of args']
// ]
$replacement = $this->regFunctionFound($f, $namespace);
// echo "Reg:${regex}\n";
// echo " FN:".$f->definition."\n";
// echo " Replacement: $replacement";
// echo "\n";
$dirtyReg = str_replace($f->definition, $replacement, $dirtyReg);
$cleanReg = str_replace($f->definition, $replacement, $cleanReg);
// echo " RegOut: ${regex}\n";
}
return $cleanReg;
}
public function setRegData($data){
$this->data = $data;
}
public function setRegParser($parser){
$this->parser = $parser;
}
public function getRegData($key){
return $this->regData[$key];
}
public function getRegParser(){
return $this->parser;
}
}
class BetterReg implements BetterRegInterface {
use BetterRegTrait;
use BetterRegShorthandsTrait;
}