-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resolve properties assigned in current function as if they were simpl…
…e vars With context and stuff
- Loading branch information
Showing
5 changed files
with
269 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
<?php | ||
namespace LocalLib\Lexer; | ||
|
||
use Lib\Utils\Fp; | ||
|
||
class Lexeme | ||
{ | ||
private $regex; | ||
private $name; | ||
private $constraints = []; | ||
/** @var callable|null */ | ||
private $dataPreprocessor = null; | ||
|
||
public function __construct($name, $regex) | ||
{ | ||
$this->regex = $regex; | ||
$this->name = $name; | ||
//$this->preprocessDataRemoveNumericKeys(); | ||
//$this->preprocessDataReturnOnlyToken(); | ||
$this->preprocessDataReturnDefault(); | ||
} | ||
|
||
private function passesConstraints($context) | ||
{ | ||
$passesConstraint = function($constraint) use ($context) {return $constraint($context);}; | ||
return Fp::all($passesConstraint, $this->constraints); | ||
} | ||
|
||
public function hasConstraint(callable $constraint) | ||
{ | ||
$this->constraints[] = $constraint; | ||
return $this; | ||
} | ||
|
||
public function hasPreviousLexemeConstraint($lexemes) | ||
{ | ||
$constraint = function($context) use ($lexemes) { | ||
$previousLexeme = array_pop($context['lexemes']); | ||
return in_array($previousLexeme['lexeme'], $lexemes); | ||
}; | ||
return $this->hasConstraint($constraint); | ||
} | ||
|
||
public function preprocessData(callable $dataPreprocessor) | ||
{ | ||
$this->dataPreprocessor = $dataPreprocessor; | ||
return $this; | ||
} | ||
|
||
public function preprocessDataFilterTokens($tokens) | ||
{ | ||
$dataPreprocessor = function($data) use ($tokens) { | ||
$result = []; | ||
foreach ($tokens as $token) { | ||
$result[$token] = $data[$token] ?? null; | ||
} | ||
return $result; | ||
}; | ||
return $this->preprocessData($dataPreprocessor); | ||
} | ||
|
||
public function preprocessDataEmpty() | ||
{ | ||
$dataPreprocessor = function($data){return $data;}; | ||
return $this->preprocessData($dataPreprocessor); | ||
} | ||
|
||
public function preprocessDataRemoveNumericKeys() | ||
{ | ||
$dataPreprocessor = function($data){ | ||
$result = []; | ||
foreach ($data as $key => $value) { | ||
if (!is_integer($key)) { | ||
$result[$key] = $value; | ||
} | ||
} | ||
return $result; | ||
}; | ||
return $this->preprocessData($dataPreprocessor); | ||
} | ||
|
||
public function preprocessDataReturnOnlyToken() | ||
{ | ||
$dataPreprocessor = function($data) { | ||
$result = []; | ||
foreach ($data as $key => $value) { | ||
if (!is_integer($key)) { | ||
$result[$key] = $value; | ||
} | ||
} | ||
|
||
if (count($result) === 1) { | ||
return array_pop($result); | ||
} else { | ||
return null; | ||
} | ||
}; | ||
return $this->preprocessData($dataPreprocessor); | ||
} | ||
|
||
public function preprocessDataReturnDefault() | ||
{ | ||
$dataPreprocessor = function($data) { | ||
$result = []; | ||
foreach ($data as $key => $value) { | ||
if (!is_integer($key)) { | ||
$result[$key] = $value; | ||
} | ||
} | ||
|
||
if (count($result) === 1) { | ||
return array_pop($result); | ||
} elseif (count($result) > 1) { | ||
return $result; | ||
} else { | ||
return null; | ||
} | ||
}; | ||
return $this->preprocessData($dataPreprocessor); | ||
} | ||
|
||
public function match($text, $context = null) | ||
{ | ||
$dataPreprocessor = $this->dataPreprocessor; | ||
if (preg_match($this->regex, $text, $matches) && $this->passesConstraints($context) && $matches[0] !== '') { | ||
return [ | ||
'lexeme' => $this->name, | ||
'data' => $dataPreprocessor($matches), | ||
'textLeft' => mb_substr($text, mb_strlen($matches[0])), | ||
]; | ||
} else { | ||
return null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<?php | ||
namespace LocalLib\Lexer; | ||
|
||
use Lib\Utils\Fp; | ||
|
||
class Lexer | ||
{ | ||
private $context; | ||
private $lexemes; | ||
private $logger; | ||
|
||
public function __construct($lexemes) | ||
{ | ||
$this->lexemes = $lexemes; | ||
} | ||
|
||
public function setLog($log) | ||
{ | ||
$this->logger = $log; | ||
|
||
return $this; | ||
} | ||
|
||
public function log($msg, $data = null) | ||
{ | ||
$log = $this->logger; | ||
if ($log) { | ||
$log($msg, $data); | ||
} | ||
} | ||
|
||
private function matchLexeme($text) | ||
{ | ||
foreach ($this->lexemes as $lexeme) { | ||
$r = $lexeme->match($text, $this->context); | ||
if ($r) { | ||
return $r; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
public function lex($text) | ||
{ | ||
$this->context = [ | ||
'text' => $text, | ||
'lexemes' => [], | ||
]; | ||
|
||
while(true){ | ||
$lexeme = $this->matchLexeme($this->context['text']); | ||
if ($lexeme) { | ||
$this->log('Lexeme: '.$lexeme['lexeme'], $lexeme); | ||
$this->context['text'] = $lexeme['textLeft']; | ||
$this->context['lexemes'][] = $lexeme; | ||
} else { | ||
$this->log('ERROR: '.$this->context['text']); | ||
break; | ||
} | ||
} | ||
|
||
// Not sure if appropriate | ||
$removeTextLeft = function($data){unset($data['textLeft']); return $data;}; | ||
$this->context['lexemes'] = Fp::map($removeTextLeft, $this->context['lexemes']); | ||
return $this->context; | ||
} | ||
} |