*/ 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); } }