/// <summary>Attempts to parse key values from the specified text.</summary> /// <param name='text'>Text to parse (not null).</param> /// <param name="allowNamedValues">Set to true if the parser should accept named values /// so syntax like Name='value'. If this is false, the parsing will fail on such constructs.</param> /// <param name="allowNull">Set to true if the parser should accept null values. /// If set to false, the parser will fail on null values.</param> /// <param name='instance'>After invocation, the parsed key instance.</param> /// <param name="enableUriTemplateParsing">Whether Uri template parsing is enabled.</param> /// <returns> /// true if the key instance was parsed; false if there was a /// syntactic error. /// </returns> /// <remarks> /// The returned instance contains only string values. To get typed values, a call to /// TryConvertValues is necessary. /// </remarks> private static bool TryParseFromUri(string text, bool allowNamedValues, bool allowNull, out SegmentArgumentParser instance, bool enableUriTemplateParsing) { Debug.Assert(text != null, "text != null"); Dictionary <string, string> namedValues = null; List <string> positionalValues = null; // parse keys just like function parameters ExpressionLexer lexer = new ExpressionLexer("(" + text + ")", true, false); UriQueryExpressionParser exprParser = new UriQueryExpressionParser(ODataUriParserSettings.DefaultFilterLimit /* default limit for parsing key value */, lexer); var tmp = (new FunctionCallParser(lexer, exprParser)).ParseArgumentListOrEntityKeyList(); if (lexer.CurrentToken.Kind != ExpressionTokenKind.End) { instance = null; return(false); } if (tmp.Length == 0) { instance = Empty; return(true); } string valueText = null; foreach (FunctionParameterToken t in tmp) { valueText = null; LiteralToken literalToken = t.ValueToken as LiteralToken; if (literalToken != null) { valueText = literalToken.OriginalText; // disallow "{...}" if enableUriTemplateParsing is false (which could have been seen as valid function parameter, e.g. array notation) if (!enableUriTemplateParsing && UriTemplateParser.IsValidTemplateLiteral(valueText)) { instance = null; return(false); } } else { DottedIdentifierToken dottedIdentifierToken = t.ValueToken as DottedIdentifierToken; // for enum if (dottedIdentifierToken != null) { valueText = dottedIdentifierToken.Identifier; } } if (valueText != null) { if (t.ParameterName == null) { if (namedValues != null) { instance = null; // We cannot mix named and non-named values. return(false); } CreateIfNull(ref positionalValues); positionalValues.Add(valueText); } else { if (positionalValues != null) { instance = null; // We cannot mix named and non-named values. return(false); } CreateIfNull(ref namedValues); namedValues.Add(t.ParameterName, valueText); } } else { instance = null; return(false); } } instance = new SegmentArgumentParser(namedValues, positionalValues, false, enableUriTemplateParsing); return(true); }
/// <summary> /// Whether given token is valid for keyPropertyValue, allow Uri template {key} if template parsing is enabled /// </summary> /// <param name="token">The literal token to be evaluated.</param> /// <param name="enableUriTemplateParsing">Whether Uri template parsing is enabled.</param> /// <returns>Whether token is valid for keyPropertyValue.</returns> private static bool IsKeyValueToken(ExpressionToken token, bool enableUriTemplateParsing) { return(token.IsKeyValueToken || (enableUriTemplateParsing && UriTemplateParser.IsValidTemplateLiteral(token.Text))); }