Adam Pippin
3 years ago
6 changed files with 0 additions and 509 deletions
@ -1,61 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
namespace App\Cfnpp\Expression; |
|
||||
|
|
||||
/** |
|
||||
* Parse a string into a series of expression tokens. |
|
||||
* |
|
||||
* @author Adam Pippin <hello@adampippin.ca> |
|
||||
*/ |
|
||||
class Parser |
|
||||
{ |
|
||||
/** |
|
||||
* List of class names of tokens this parser will parse. |
|
||||
* |
|
||||
* @var string[] |
|
||||
*/ |
|
||||
public const TOKEN_TYPES = [ |
|
||||
TokenFunction::class, |
|
||||
TokenNumericLiteral::class, |
|
||||
TokenOperator::class, |
|
||||
TokenStringLiteral::class, |
|
||||
TokenVariable::class |
|
||||
]; |
|
||||
|
|
||||
/** |
|
||||
* Parse a string into an expression. |
|
||||
* |
|
||||
* @param string $value |
|
||||
* @return Expression |
|
||||
*/ |
|
||||
public function parse(string $value): Expression |
|
||||
{ |
|
||||
$original_value = $value; |
|
||||
$value .= ' '; |
|
||||
$tokens = []; |
|
||||
while (strlen($value) > 0) |
|
||||
{ |
|
||||
foreach (static::TOKEN_TYPES as $token_class) |
|
||||
{ |
|
||||
if ($token_class::isToken($value)) |
|
||||
{ |
|
||||
$tokens[] = $token_class::getToken($value); |
|
||||
|
|
||||
if (substr($value, 0, 1) != ' ') |
|
||||
{ |
|
||||
throw new \Exception('Incompletely consumed token at offset '.(strlen($original_value) - strlen($value)).' in expression '.$original_value); |
|
||||
} |
|
||||
|
|
||||
$value = substr($value, 1); |
|
||||
continue 2; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
throw new \Exception('Unparseable value at offset '.(strlen($original_value) - strlen($value)).' in expression '.$original_value); |
|
||||
} |
|
||||
|
|
||||
return new Expression($tokens); |
|
||||
} |
|
||||
} |
|
@ -1,90 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
namespace App\Cfnpp\Expression; |
|
||||
|
|
||||
/** |
|
||||
* Token representing a function. |
|
||||
* |
|
||||
* @author Adam Pippin <hello@adampippin.ca> |
|
||||
*/ |
|
||||
class TokenFunction extends Token |
|
||||
{ |
|
||||
/** |
|
||||
* List of valid functions this can parse. |
|
||||
* @var string[] |
|
||||
*/ |
|
||||
public const FUNCTIONS = [ |
|
||||
'concat*', |
|
||||
'concat' |
|
||||
]; |
|
||||
|
|
||||
/** |
|
||||
* Function this token represents. |
|
||||
* @var string |
|
||||
*/ |
|
||||
protected $function; |
|
||||
|
|
||||
/** |
|
||||
* Create a new function token. |
|
||||
* |
|
||||
* @param string $function |
|
||||
*/ |
|
||||
public function __construct($function) |
|
||||
{ |
|
||||
$this->function = $function; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the function this token represents. |
|
||||
* |
|
||||
* @return string |
|
||||
*/ |
|
||||
public function getFunction(): string |
|
||||
{ |
|
||||
return $this->function; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether a function token can be parsed from a stream. |
|
||||
* |
|
||||
* @param string $stream |
|
||||
* @return bool |
|
||||
*/ |
|
||||
public static function isToken(string $stream): bool |
|
||||
{ |
|
||||
foreach (static::FUNCTIONS as $function) |
|
||||
{ |
|
||||
if (strlen($stream) > strlen($function) && |
|
||||
substr($stream, 0, strlen($function)) == $function) |
|
||||
{ |
|
||||
return true; |
|
||||
} |
|
||||
} |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Parse a function token from a stream. |
|
||||
* |
|
||||
* Returns token, and modifies stream to remove all consumed characters |
|
||||
* |
|
||||
* @param string $stream |
|
||||
* @return Token |
|
||||
*/ |
|
||||
public static function getToken(string &$stream): Token |
|
||||
{ |
|
||||
foreach (static::FUNCTIONS as $function) |
|
||||
{ |
|
||||
if (strlen($stream) > strlen($function) && |
|
||||
substr($stream, 0, strlen($function)) == $function) |
|
||||
{ |
|
||||
$function = substr($stream, 0, strlen($function)); |
|
||||
$stream = substr($stream, strlen($function)); |
|
||||
return new TokenFunction($function); |
|
||||
} |
|
||||
} |
|
||||
throw new \Exception('Could not parse function token!'); |
|
||||
} |
|
||||
} |
|
@ -1,87 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
namespace App\Cfnpp\Expression; |
|
||||
|
|
||||
/** |
|
||||
* Token representing a numeric (integer or float) literal. |
|
||||
* |
|
||||
* @author Adam Pippin <hello@adampippin.ca> |
|
||||
*/ |
|
||||
class TokenNumericLiteral extends Token |
|
||||
{ |
|
||||
/** |
|
||||
* Numeric value this token represents. |
|
||||
* @var int|float |
|
||||
*/ |
|
||||
protected $value; |
|
||||
|
|
||||
/** |
|
||||
* Create a new numeric literal. |
|
||||
* |
|
||||
* @param int|float $value |
|
||||
*/ |
|
||||
public function __construct($value) |
|
||||
{ |
|
||||
$this->value = $value; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the value this token represents. |
|
||||
* |
|
||||
* @return int|float |
|
||||
*/ |
|
||||
public function getValue() |
|
||||
{ |
|
||||
return $this->value; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether a numeric token can be parsed from a stream. |
|
||||
* |
|
||||
* @param string $stream |
|
||||
* @return bool |
|
||||
*/ |
|
||||
public static function isToken(string $stream): bool |
|
||||
{ |
|
||||
return is_numeric($stream[0]); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Parse a numeric token from a stream. |
|
||||
* |
|
||||
* Returns token, and modifies stream to remove all consumed characters. |
|
||||
* |
|
||||
* @param string $stream |
|
||||
* @return Token |
|
||||
*/ |
|
||||
public static function getToken(string &$stream): Token |
|
||||
{ |
|
||||
$buffer = ''; |
|
||||
for ($i = 0; $i < strlen($stream); $i++) |
|
||||
{ |
|
||||
if (preg_match('/^[0-9]$/', $stream[$i])) |
|
||||
{ |
|
||||
$buffer .= $stream[$i]; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$stream = substr($stream, strlen($buffer)); |
|
||||
|
|
||||
if (stristr($buffer, '.')) |
|
||||
{ |
|
||||
$buffer = (float)$buffer; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
$buffer = (int)$buffer; |
|
||||
} |
|
||||
|
|
||||
return new TokenNumericLiteral($buffer); |
|
||||
} |
|
||||
} |
|
@ -1,97 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
namespace App\Cfnpp\Expression; |
|
||||
|
|
||||
/** |
|
||||
* Token representing a comparison operator. |
|
||||
* |
|
||||
* @author Adam Pippin <hello@adampippin.ca> |
|
||||
*/ |
|
||||
class TokenOperator extends Token |
|
||||
{ |
|
||||
/** |
|
||||
* List of valid operators this can parse. |
|
||||
* @var string[] |
|
||||
*/ |
|
||||
public const OPERATORS = [ |
|
||||
'eq', |
|
||||
'neq', |
|
||||
'gt', |
|
||||
'gte', |
|
||||
'lt', |
|
||||
'lte', |
|
||||
'and', |
|
||||
'or', |
|
||||
'not' |
|
||||
]; |
|
||||
|
|
||||
/** |
|
||||
* Operator this token represents. |
|
||||
* @var string |
|
||||
*/ |
|
||||
protected $operator; |
|
||||
|
|
||||
/** |
|
||||
* Create a new operator token. |
|
||||
* |
|
||||
* @param string $operator |
|
||||
*/ |
|
||||
public function __construct($operator) |
|
||||
{ |
|
||||
$this->operator = $operator; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the operator this token represents. |
|
||||
* |
|
||||
* @return string |
|
||||
*/ |
|
||||
public function getOperator(): string |
|
||||
{ |
|
||||
return $this->operator; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether a operator token can be parsed from a stream. |
|
||||
* |
|
||||
* @param string $stream |
|
||||
* @return bool |
|
||||
*/ |
|
||||
public static function isToken(string $stream): bool |
|
||||
{ |
|
||||
foreach (static::OPERATORS as $operator) |
|
||||
{ |
|
||||
if (strlen($stream) > strlen($operator) && |
|
||||
substr($stream, 0, strlen($operator)) == $operator) |
|
||||
{ |
|
||||
return true; |
|
||||
} |
|
||||
} |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Parse an operator token from a stream. |
|
||||
* |
|
||||
* Returns token, and modifies stream to remove all consumed characters |
|
||||
* |
|
||||
* @param string $stream |
|
||||
* @return Token |
|
||||
*/ |
|
||||
public static function getToken(string &$stream): Token |
|
||||
{ |
|
||||
foreach (static::OPERATORS as $operator) |
|
||||
{ |
|
||||
if (strlen($stream) > strlen($operator) && |
|
||||
substr($stream, 0, strlen($operator)) == $operator) |
|
||||
{ |
|
||||
$operator = substr($stream, 0, strlen($operator)); |
|
||||
$stream = substr($stream, strlen($operator)); |
|
||||
return new TokenOperator($operator); |
|
||||
} |
|
||||
} |
|
||||
throw new \Exception('Could not parse operator token!'); |
|
||||
} |
|
||||
} |
|
@ -1,95 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
namespace App\Cfnpp\Expression; |
|
||||
|
|
||||
/** |
|
||||
* Token representing a string literal. |
|
||||
* |
|
||||
* @author Adam Pippin <hello@adampippin.ca> |
|
||||
*/ |
|
||||
class TokenStringLiteral extends Token |
|
||||
{ |
|
||||
/** |
|
||||
* Value of the string literal. |
|
||||
* @var string |
|
||||
*/ |
|
||||
protected $value; |
|
||||
|
|
||||
/** |
|
||||
* Create a new string literal token. |
|
||||
* |
|
||||
* @param string $value |
|
||||
*/ |
|
||||
public function __construct(string $value) |
|
||||
{ |
|
||||
$this->value = $value; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the value of the string literal. |
|
||||
* |
|
||||
* @return string |
|
||||
*/ |
|
||||
public function getValue(): string |
|
||||
{ |
|
||||
return $this->value; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether a string token can be parsed from a stream. |
|
||||
* |
|
||||
* @param string $stream |
|
||||
* @return bool |
|
||||
*/ |
|
||||
public static function isToken(string $stream): bool |
|
||||
{ |
|
||||
return $stream[0] == '"'; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Parse a string literal token from a stream. |
|
||||
* |
|
||||
* Returns token, and modifies stream to remove all consumed characters |
|
||||
* |
|
||||
* @param string $stream |
|
||||
* @return Token |
|
||||
*/ |
|
||||
public static function getToken(string &$stream): Token |
|
||||
{ |
|
||||
$buffer = ''; |
|
||||
$in_string = false; |
|
||||
$escaped = false; |
|
||||
|
|
||||
for ($i = 0; $i < strlen($stream); $i++) |
|
||||
{ |
|
||||
if ($escaped) |
|
||||
{ |
|
||||
$buffer .= $stream[$i]; |
|
||||
$escaped = false; |
|
||||
} |
|
||||
elseif ($stream[$i] == '"') |
|
||||
{ |
|
||||
if ($in_string) |
|
||||
{ |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
$in_string = true; |
|
||||
} |
|
||||
elseif ($stream[$i] == '\\') |
|
||||
{ |
|
||||
$escaped = true; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
$buffer .= $stream[$i]; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$stream = substr($stream, $i + 1); |
|
||||
|
|
||||
return new TokenStringLiteral($buffer); |
|
||||
} |
|
||||
} |
|
@ -1,79 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
namespace App\Cfnpp\Expression; |
|
||||
|
|
||||
/** |
|
||||
* Expression token referencing a variable. |
|
||||
* |
|
||||
* @author Adam Pippin <hello@adampippin.ca> |
|
||||
*/ |
|
||||
class TokenVariable extends Token |
|
||||
{ |
|
||||
/** |
|
||||
* Name of the variable this token references. |
|
||||
* @var string |
|
||||
*/ |
|
||||
protected $name; |
|
||||
|
|
||||
/** |
|
||||
* Create a new variable token. |
|
||||
* |
|
||||
* @param string $name |
|
||||
*/ |
|
||||
public function __construct(string $name) |
|
||||
{ |
|
||||
$this->name = $name; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Get the name of the variable this token references. |
|
||||
* |
|
||||
* @return string |
|
||||
*/ |
|
||||
public function getName(): string |
|
||||
{ |
|
||||
return $this->name; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Determine whether a variable name token can be parsed from a stream. |
|
||||
* |
|
||||
* @param string $stream |
|
||||
* @return bool |
|
||||
*/ |
|
||||
public static function isToken(string $stream): bool |
|
||||
{ |
|
||||
return (bool)preg_match('/^[A-Za-z]$/', $stream[0]); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* Parse a variable token from a stream. |
|
||||
* |
|
||||
* Returns token, and modifies stream to remove all consumed characters. |
|
||||
* |
|
||||
* @param string $stream |
|
||||
* @return Token |
|
||||
*/ |
|
||||
public static function getToken(string &$stream): Token |
|
||||
{ |
|
||||
$buffer = ''; |
|
||||
$buffer = $stream[0]; |
|
||||
for ($i = 1; $i < strlen($stream); $i++) |
|
||||
{ |
|
||||
if (preg_match('/^[A-Za-z0-9]$/', $stream[$i])) |
|
||||
{ |
|
||||
$buffer .= $stream[$i]; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
$stream = substr($stream, strlen($buffer)); |
|
||||
|
|
||||
return new TokenVariable($buffer); |
|
||||
} |
|
||||
} |
|
Loading…
Reference in new issue