You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
61 lines
1.3 KiB
61 lines
1.3 KiB
<?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);
|
|
}
|
|
}
|
|
|