@since 0.7

@param string|string[] $inputValues one or more
@param string $parser Id of the ValueParser to use

@returns Promise of a DataValue object or array of DataValue objects with same keys as values
182772
public function parseAsync( $inputValues, $parser ) {
		$promise = $this->api->getRequestAsync(
			new SimpleRequest(
				'wbparsevalue',
				array(
					'parser' => $parser,
					'values' => implode( '|', $inputValues ),
				)
			)
		);

		return $promise->then(
			function ( $result ) use ( $inputValues ) {
				if ( is_array( $inputValues ) ) {
					$indexedResults = array();
					foreach ( $result['results'] as $resultElement ) {
						if ( in_array( $resultElement['raw'], $inputValues ) ) {
							$indexedResults[array_search( $resultElement['raw'], $inputValues )] =
								$this->dataValueDeserializer->deserialize( $resultElement );
						} else {
							throw new RuntimeException( "Failed to match parse results with input data" );
						}
					}

					return $indexedResults;
				} else {
					return $this->dataValueDeserializer->deserialize( $result['results'][0] );
				}
			}
		);
	}
1315766
protected function validator($inputValue)
    {
        if ('' === $inputValue) {
            if ($this->mandatory) {
                $this->addError(
                    $this->getEnvironment()->getTranslator()->translate('mandatory', 'ERR', [$this->strLabel])
                );
            }

            return '';
        }

        $inputValue = \array_map('\Contao\StringUtil::uuidToBin', \array_filter(\explode(',', $inputValue)));

        return $this->multiple ? $inputValue : $inputValue[0];
    }
1352275
public function decode(Parser $parser, Node\Variable $var, $values)
    {
        $single = !is_array($values);
        $values = (array)$values;

        array_walk($values, function(&$v, $k) {
            $v = rawurldecode($v);
        });

        return $single ? reset($values) : $values;
    }
1048389
public function parse(Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);

        $this->maskField = $parser->ArithmeticPrimary();
        $this->deleteDeferredPath($parser, $this->maskField);

        $parser->match(Lexer::T_COMMA);
        $this->findValue = $parser->ArithmeticPrimary();

        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
        $this->parserResult = $parser->getParserResult();
    }
935419
public function setAutocompleterValues($values)
    {
        if (\is_array($values)) {
            $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);

            $callback = static function () use ($values) {
                return $values;
            };
        } elseif ($values instanceof \Traversable) {
            $valueCache = null;
            $callback = static function () use ($values, &$valueCache) {
                return $valueCache ?? $valueCache = iterator_to_array($values, false);
            };
        } elseif (null === $values) {
            $callback = null;
        } else {
            throw new InvalidArgumentException('Autocompleter values can be either an array, "null" or a "Traversable" object.');
        }

        return $this->setAutocompleterCallback($callback);
    }
772299
public function isSelectedValue($dataValue, $userValue)
    {
        if (is_array($userValue) && in_array($dataValue, $userValue)) {
            return true;
        }
        
        return parent::isSelectedValue($dataValue, $userValue);
    }
967049
public function setParser($parser) {
        switch ($parser) {
            case self::PARSER_XML:
            case self::PARSER_XMLDTD:
            case self::PARSER_HTML:
            case self::PARSER_HTML5:
            case self::PARSER_HTML4:
            case self::PARSER_HTML4TR:
                $this->parser = $parser;
                return $this;
            default:
                throw new UnknownParserException('Unknown parser "' . $parser . '"');
        }
    }
965201
public function parse(Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $this->first = $parser->ArithmeticPrimary();
        $parser->match(Lexer::T_AS);
        $parser->match(Lexer::T_IDENTIFIER);
        $this->second = $parser->getLexer()->token['value'];
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
723396
public static function parse(Parser $parser, TokensList $list, array $options = [])
    {
        $ret = empty($options['type']) ? new self() : [];

        /**
         * The last raw expression.
         *
         * @var string
         */
        $lastRaw = '';

        /**
         * The last value.
         *
         * @var string
         */
        $lastValue = '';

        /**
         * Counts brackets.
         *
         * @var int
         */
        $brackets = 0;

        /**
         * Last separator (bracket or comma).
         *
         * @var bool
         */
        $isCommaLast = false;

        for (; $list->idx < $list->count; ++$list->idx) {
            /**
             * Token parsed at this moment.
             *
             * @var Token
             */
            $token = $list->tokens[$list->idx];

            // End of statement.
            if ($token->type === Token::TYPE_DELIMITER) {
                break;
            }

            // Skipping whitespaces and comments.
            if (($token->type === Token::TYPE_WHITESPACE)
                || ($token->type === Token::TYPE_COMMENT)
            ) {
                $lastRaw .= $token->token;
                $lastValue = trim($lastValue) . ' ';
                continue;
            }

            if (($brackets === 0)
                && (($token->type !== Token::TYPE_OPERATOR)
                || ($token->value !== '('))
            ) {
                $parser->error('An opening bracket was expected.', $token);
                break;
            }

            if ($token->type === Token::TYPE_OPERATOR) {
                if ($token->value === '(') {
                    if (++$brackets === 1) { // 1 is the base level.
                        continue;
                    }
                } elseif ($token->value === ')') {
                    if (--$brackets === 0) { // Array ended.
                        break;
                    }
                } elseif ($token->value === ',') {
                    if ($brackets === 1) {
                        $isCommaLast = true;
                        if (empty($options['type'])) {
                            $ret->raw[] = trim($lastRaw);
                            $ret->values[] = trim($lastValue);
                            $lastRaw = $lastValue = '';
                        }
                    }
                    continue;
                }
            }

            if (empty($options['type'])) {
                $lastRaw .= $token->token;
                $lastValue .= $token->value;
            } else {
                $ret[] = $options['type']::parse(
                    $parser,
                    $list,
                    empty($options['typeOptions']) ? [] : $options['typeOptions']
                );
            }
        }

        // Handling last element.
        //
        // This is treated differently to treat the following cases:
        //
        //           => array()
        //      (,)  => array('', '')
        //      ()   => array()
        //      (a,) => array('a', '')
        //      (a)  => array('a')
        //
        $lastRaw = trim($lastRaw);
        if ((empty($options['type']))
            && ((strlen($lastRaw) > 0) || ($isCommaLast))
        ) {
            $ret->raw[] = $lastRaw;
            $ret->values[] = trim($lastValue);
        }

        return $ret;
    }
1277194
public function getValidFormValues($getSubmits = false) {

		if(is_null($this->requestValues)) {

			throw new HtmlFormException('Values can not be evaluated. No request bound.', HtmlFormException::NO_REQUEST_BOUND);

		}

		$tmp = new ValuesBag();

		foreach($this->elements as $name => $e) {

			if(is_array($e)) {

				$vals = [];

				foreach($e as $ndx => $elem) {

					if(!$elem->isValid()) {
						continue;
					}

					// @todo since elements in an array are all of same type they don't need to be checked individually
					
					if($elem->canSubmit() && !$getSubmits) {
						continue;
					}

					if($elem instanceof CheckboxElement && !in_array($elem->getValue(), $this->requestValues->get($name, []))) {
						continue;
					}

					$vals[$ndx] = $elem->getModifiedValue();
				}

				$tmp->set($name, $vals);

			}

			else {

				if(
					$e->canSubmit() && !$getSubmits ||
					!$e->isValid() ||
					$e instanceof CheckboxElement && !$this->requestValues->get($name)
				) {
					continue;
				}

				$tmp->set($name, $e->getModifiedValue());

			}
		}

		return $tmp;

	}
991175
public static function parser(ParserInterface $parser = null)
	{
		if($parser) {
			static::$parser = $parser;
		}
		elseif(!static::$parser) {
			static::$parser = new Annotation\KeyValuePairParser;
		}

		return static::$parser;
	}
999543
private function evaluate(
        ClassArgumentObject $inputSource,
        ClassArgumentObject $matcher,
        ServerRequestInterface $httpRequest
    ) {
        return $matcher->getInstance()->match(
            $inputSource->getInstance()->getValue($httpRequest, $inputSource->getArgument()),
            $matcher->getArgument()
        );
    }
315634
public static function parse(Tokenizer $tokenizer, PdfParser $parser)
    {
        $result = [];

        // Recurse into this function until we reach the end of the array.
        while (($token = $tokenizer->getNextToken()) !== ']') {
            if ($token === false || ($value = $parser->readValue($token)) === false) {
                return false;
            }

            $result[] = $value;
        }

        $v = new self;
        $v->value = $result;

        return $v;
    }
514151
public static function parse(Parser $parser, TokensList $list, array $options = [])
    {
        $ret = new self();

        /**
         * State of parser.
         *
         * @var int
         */
        $state = 0;

        /**
         * Syntax type (type 0 or type 1).
         *
         * @var int
         */
        $type = 0;

        ++$list->idx; // Skip 'CASE'

        for (; $list->idx < $list->count; ++$list->idx) {
            /**
             * Token parsed at this moment.
             *
             * @var Token
             */
            $token = $list->tokens[$list->idx];

            // Skipping whitespaces and comments.
            if (($token->type === Token::TYPE_WHITESPACE)
                || ($token->type === Token::TYPE_COMMENT)
            ) {
                continue;
            }

            if ($state === 0) {
                if ($token->type === Token::TYPE_KEYWORD) {
                    switch ($token->keyword) {
                        case 'WHEN':
                            ++$list->idx; // Skip 'WHEN'
                            $new_condition = Condition::parse($parser, $list);
                            $type = 1;
                            $state = 1;
                            $ret->conditions[] = $new_condition;
                            break;
                        case 'ELSE':
                            ++$list->idx; // Skip 'ELSE'
                            $ret->else_result = Expression::parse($parser, $list);
                            $state = 0; // last clause of CASE expression
                            break;
                        case 'END':
                            $state = 3; // end of CASE expression
                            ++$list->idx;
                            break 2;
                        default:
                            $parser->error('Unexpected keyword.', $token);
                            break 2;
                    }
                } else {
                    $ret->value = Expression::parse($parser, $list);
                    $type = 0;
                    $state = 1;
                }
            } elseif ($state === 1) {
                if ($type === 0) {
                    if ($token->type === Token::TYPE_KEYWORD) {
                        switch ($token->keyword) {
                            case 'WHEN':
                                ++$list->idx; // Skip 'WHEN'
                                $new_value = Expression::parse($parser, $list);
                                $state = 2;
                                $ret->compare_values[] = $new_value;
                                break;
                            case 'ELSE':
                                ++$list->idx; // Skip 'ELSE'
                                $ret->else_result = Expression::parse($parser, $list);
                                $state = 0; // last clause of CASE expression
                                break;
                            case 'END':
                                $state = 3; // end of CASE expression
                                ++$list->idx;
                                break 2;
                            default:
                                $parser->error('Unexpected keyword.', $token);
                                break 2;
                        }
                    }
                } else {
                    if ($token->type === Token::TYPE_KEYWORD
                        && $token->keyword === 'THEN'
                    ) {
                        ++$list->idx; // Skip 'THEN'
                        $new_result = Expression::parse($parser, $list);
                        $state = 0;
                        $ret->results[] = $new_result;
                    } elseif ($token->type === Token::TYPE_KEYWORD) {
                        $parser->error('Unexpected keyword.', $token);
                        break;
                    }
                }
            } elseif ($state === 2) {
                if ($type === 0) {
                    if ($token->type === Token::TYPE_KEYWORD
                        && $token->keyword === 'THEN'
                    ) {
                        ++$list->idx; // Skip 'THEN'
                        $new_result = Expression::parse($parser, $list);
                        $ret->results[] = $new_result;
                        $state = 1;
                    } elseif ($token->type === Token::TYPE_KEYWORD) {
                        $parser->error('Unexpected keyword.', $token);
                        break;
                    }
                }
            }
        }

        if ($state !== 3) {
            $parser->error(
                'Unexpected end of CASE expression',
                $list->tokens[$list->idx - 1]
            );
        } else {
            // Parse for alias of CASE expression
            $asFound = false;
            for (; $list->idx < $list->count; ++$list->idx) {
                $token = $list->tokens[$list->idx];

                // End of statement.
                if ($token->type === Token::TYPE_DELIMITER) {
                    break;
                }
                
                // Skipping whitespaces and comments.
                if (($token->type === Token::TYPE_WHITESPACE)
                    || ($token->type === Token::TYPE_COMMENT)
                ) {
                    continue;
                }

                // Handle optional AS keyword before alias
                if ($token->type === Token::TYPE_KEYWORD
                    && $token->keyword === 'AS') {
                    if ($asFound || ! empty($ret->alias)) {
                        $parser->error('Potential duplicate alias of CASE expression.', $token);
                        break;
                    }
                    $asFound = true;
                    continue;
                }

                if ($asFound
                    && $token->type === Token::TYPE_KEYWORD
                    && ($token->flags & Token::FLAG_KEYWORD_RESERVED || $token->flags & Token::FLAG_KEYWORD_FUNCTION)) {
                    $parser->error('An alias expected after AS but got ' . $token->value, $token);
                    $asFound = false;
                    break;
                }

                if ($asFound
                    || $token->type === Token::TYPE_STRING
                    || ($token->type === Token::TYPE_SYMBOL && ! $token->flags & Token::FLAG_SYMBOL_VARIABLE)
                    || $token->type === Token::TYPE_NONE
                ) {
                    // An alias is expected (the keyword `AS` was previously found).
                    if (! empty($ret->alias)) {
                        $parser->error('An alias was previously found.', $token);
                        break;
                    }
                    $ret->alias = $token->value;
                    $asFound = false;

                    continue;
                }

                break;
            }
            if ($asFound) {
                $parser->error('An alias was expected after AS.', $list->tokens[$list->idx - 1]);
            }

            $ret->expr = self::build($ret);
        }

        --$list->idx;

        return $ret;
    }
670755
public function _setArray($values, $name, $parse_commas = true)
    {
        if (is_string($values) && $parse_commas && strpos($values, ',')) {
            $values = explode(',', $values);
        }
        if (!is_array($values)) {
            $values = array($values);
        }
        if (!isset($this->args[$name])) {
            $this->args[$name] = array();
        }
        $this->args[$name] = array_merge($this->args[$name], $values);

        return $this;
    }
678651
public static function parse(Parser $parser, TokensList $list, array $options = [])
    {
        $ret = new self();

        /**
         * The ID that will be assigned to duplicate options.
         *
         * @var int
         */
        $lastAssignedId = count($options) + 1;

        /**
         * The option that was processed last time.
         *
         * @var array
         */
        $lastOption = null;

        /**
         * The index of the option that was processed last time.
         *
         * @var int
         */
        $lastOptionId = 0;

        /**
         * Counts brackets.
         *
         * @var int
         */
        $brackets = 0;

        /**
         * The state of the parser.
         *
         * Below are the states of the parser.
         *
         *      0 ---------------------[ option ]----------------------> 1
         *
         *      1 -------------------[ = (optional) ]------------------> 2
         *
         *      2 ----------------------[ value ]----------------------> 0
         *
         * @var int
         */
        $state = 0;

        for (; $list->idx < $list->count; ++$list->idx) {
            /**
             * Token parsed at this moment.
             *
             * @var Token
             */
            $token = $list->tokens[$list->idx];

            // End of statement.
            if ($token->type === Token::TYPE_DELIMITER) {
                break;
            }

            // Skipping comments.
            if ($token->type === Token::TYPE_COMMENT) {
                continue;
            }

            // Skipping whitespace if not parsing value.
            if (($token->type === Token::TYPE_WHITESPACE) && ($brackets === 0)) {
                continue;
            }

            if ($lastOption === null) {
                $upper = strtoupper($token->token);
                if (isset($options[$upper])) {
                    $lastOption = $options[$upper];
                    $lastOptionId = is_array($lastOption) ?
                        $lastOption[0] : $lastOption;
                    $state = 0;

                    // Checking for option conflicts.
                    // For example, in `SELECT` statements the keywords `ALL`
                    // and `DISTINCT` conflict and if used together, they
                    // produce an invalid query.
                    //
                    // Usually, tokens can be identified in the array by the
                    // option ID, but if conflicts occur, a generated option ID
                    // is used.
                    //
                    // The first pseudo duplicate ID is the maximum value of the
                    // real options (e.g.  if there are 5 options, the first
                    // fake ID is 6).
                    if (isset($ret->options[$lastOptionId])) {
                        $parser->error(
                            sprintf(
                                Translator::gettext('This option conflicts with "%1$s".'),
                                is_array($ret->options[$lastOptionId])
                                ? $ret->options[$lastOptionId]['name']
                                : $ret->options[$lastOptionId]
                            ),
                            $token
                        );
                        $lastOptionId = $lastAssignedId++;
                    }
                } else {
                    // There is no option to be processed.
                    break;
                }
            }

            if ($state === 0) {
                if (! is_array($lastOption)) {
                    // This is a just keyword option without any value.
                    // This is the beginning and the end of it.
                    $ret->options[$lastOptionId] = $token->value;
                    $lastOption = null;
                    $state = 0;
                } elseif (($lastOption[1] === 'var') || ($lastOption[1] === 'var=')) {
                    // This is a keyword that is followed by a value.
                    // This is only the beginning. The value is parsed in state
                    // 1 and 2. State 1 is used to skip the first equals sign
                    // and state 2 to parse the actual value.
                    $ret->options[$lastOptionId] = [
                        // @var string The name of the option.
                        'name' => $token->value,
                        // @var bool Whether it contains an equal sign.
                        //           This is used by the builder to rebuild it.
                        'equals' => $lastOption[1] === 'var=',
                        // @var string Raw value.
                        'expr' => '',
                        // @var string Processed value.
                        'value' => '',
                    ];
                    $state = 1;
                } elseif ($lastOption[1] === 'expr' || $lastOption[1] === 'expr=') {
                    // This is a keyword that is followed by an expression.
                    // The expression is used by the specialized parser.

                    // Skipping this option in order to parse the expression.
                    ++$list->idx;
                    $ret->options[$lastOptionId] = [
                        // @var string The name of the option.
                        'name' => $token->value,
                        // @var bool Whether it contains an equal sign.
                        //           This is used by the builder to rebuild it.
                        'equals' => $lastOption[1] === 'expr=',
                        // @var Expression The parsed expression.
                        'expr' => '',
                    ];
                    $state = 1;
                }
            } elseif ($state === 1) {
                $state = 2;
                if ($token->token === '=') {
                    $ret->options[$lastOptionId]['equals'] = true;
                    continue;
                }
            }

            // This is outside the `elseif` group above because the change might
            // change this iteration.
            if ($state === 2) {
                if ($lastOption[1] === 'expr' || $lastOption[1] === 'expr=') {
                    $ret->options[$lastOptionId]['expr'] = Expression::parse(
                        $parser,
                        $list,
                        empty($lastOption[2]) ? [] : $lastOption[2]
                    );
                    $ret->options[$lastOptionId]['value']
                        = $ret->options[$lastOptionId]['expr']->expr;
                    $lastOption = null;
                    $state = 0;
                } else {
                    if ($token->token === '(') {
                        ++$brackets;
                    } elseif ($token->token === ')') {
                        --$brackets;
                    }

                    $ret->options[$lastOptionId]['expr'] .= $token->token;

                    if (! ((($token->token === '(') && ($brackets === 1))
                        || (($token->token === ')') && ($brackets === 0)))
                    ) {
                        // First pair of brackets is being skipped.
                        $ret->options[$lastOptionId]['value'] .= $token->value;
                    }

                    // Checking if we finished parsing.
                    if ($brackets === 0) {
                        $lastOption = null;
                    }
                }
            }
        }

        /*
         * We reached the end of statement without getting a value
         * for an option for which a value was required
         */
        if ($state === 1
            && $lastOption
            && ($lastOption[1] === 'expr'
            || $lastOption[1] === 'var'
            || $lastOption[1] === 'var='
            || $lastOption[1] === 'expr=')
        ) {
            $parser->error(
                sprintf(
                    'Value/Expression for the option %1$s was expected.',
                    $ret->options[$lastOptionId]['name']
                ),
                $list->tokens[$list->idx - 1]
            );
        }

        if (empty($options['_UNSORTED'])) {
            ksort($ret->options);
        }

        --$list->idx;

        return $ret;
    }
847638
public static function parse(Parser $parser, TokensList $list, array $options = [])
    {
        $ret = [];

        $expr = new self();

        /**
         * The state of the parser.
         *
         * Below are the states of the parser.
         *
         *      0 -----------------------[ ( ]------------------------> 1
         *
         *      1 --------------------[ CONSTRAINT ]------------------> 1
         *      1 -----------------------[ key ]----------------------> 2
         *      1 -------------[ constraint / column name ]-----------> 2
         *
         *      2 --------------------[ data type ]-------------------> 3
         *
         *      3 ---------------------[ options ]--------------------> 4
         *
         *      4 --------------------[ REFERENCES ]------------------> 4
         *
         *      5 ------------------------[ , ]-----------------------> 1
         *      5 ------------------------[ ) ]-----------------------> 6 (-1)
         *
         * @var int
         */
        $state = 0;

        for (; $list->idx < $list->count; ++$list->idx) {
            /**
             * Token parsed at this moment.
             *
             * @var Token
             */
            $token = $list->tokens[$list->idx];

            // End of statement.
            if ($token->type === Token::TYPE_DELIMITER) {
                break;
            }

            // Skipping whitespaces and comments.
            if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
                continue;
            }

            if ($state === 0) {
                if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
                    $state = 1;
                } else {
                    $parser->error(
                        'An opening bracket was expected.',
                        $token
                    );

                    break;
                }
            } elseif ($state === 1) {
                if ($token->type === Token::TYPE_KEYWORD && $token->keyword === 'CONSTRAINT') {
                    $expr->isConstraint = true;
                } elseif (($token->type === Token::TYPE_KEYWORD) && ($token->flags & Token::FLAG_KEYWORD_KEY)) {
                    $expr->key = Key::parse($parser, $list);
                    $state = 4;
                } elseif ($token->type === Token::TYPE_SYMBOL || $token->type === Token::TYPE_NONE) {
                    $expr->name = $token->value;
                    if (! $expr->isConstraint) {
                        $state = 2;
                    }
                } elseif ($token->type === Token::TYPE_KEYWORD) {
                    if ($token->flags & Token::FLAG_KEYWORD_RESERVED) {
                        // Reserved keywords can't be used
                        // as field names without backquotes
                        $parser->error(
                            'A symbol name was expected! '
                            . 'A reserved keyword can not be used '
                            . 'as a column name without backquotes.',
                            $token
                        );

                        return $ret;
                    }

                    // Non-reserved keywords are allowed without backquotes
                    $expr->name = $token->value;
                    $state = 2;
                } else {
                    $parser->error(
                        'A symbol name was expected!',
                        $token
                    );

                    return $ret;
                }
            } elseif ($state === 2) {
                $expr->type = DataType::parse($parser, $list);
                $state = 3;
            } elseif ($state === 3) {
                $expr->options = OptionsArray::parse($parser, $list, static::$FIELD_OPTIONS);
                $state = 4;
            } elseif ($state === 4) {
                if ($token->type === Token::TYPE_KEYWORD && $token->keyword === 'REFERENCES') {
                    ++$list->idx; // Skipping keyword 'REFERENCES'.
                    $expr->references = Reference::parse($parser, $list);
                } else {
                    --$list->idx;
                }
                $state = 5;
            } elseif ($state === 5) {
                if (! empty($expr->type) || ! empty($expr->key)) {
                    $ret[] = $expr;
                }
                $expr = new self();
                if ($token->value === ',') {
                    $state = 1;
                } elseif ($token->value === ')') {
                    $state = 6;
                    ++$list->idx;
                    break;
                } else {
                    $parser->error(
                        'A comma or a closing bracket was expected.',
                        $token
                    );
                    $state = 0;
                    break;
                }
            }
        }

        // Last iteration was not saved.
        if (! empty($expr->type) || ! empty($expr->key)) {
            $ret[] = $expr;
        }

        if (($state !== 0) && ($state !== 6)) {
            $parser->error(
                'A closing bracket was expected.',
                $list->tokens[$list->idx - 1]
            );
        }

        --$list->idx;

        return $ret;
    }