/// <summary> /// Parses the next parameter in the specified <paramref name="expr"/>. /// The returned value will indicate the index in this string following /// the parameter declaration. /// </summary> /// <remarks> /// Parses in the specified <paramref name="expr"/> beginning at the specified /// <paramref name="index"/> a XAML markup extension parameter specification /// of the form /// <code> /// 1) /// [Name]=[Value] /// </code> /// or /// <code> /// 2) /// [Value] /// </code> /// The value itself may be a simple string value or an instantiation of /// another element, surrounded by { and } characters. /// If form 1 is found, the returned parameter /// <paramref name="name"/> will contain the parsed name part, if form 2 is /// found, the <paramref name="name"/> parameter will be null. /// In both forms the <paramref name="value"/> parameter will contain the /// parsed value string. /// </remarks> /// <returns>The index in the <paramref name="expr"/> string following /// the parameter declaration.</returns> private static int ParseParameter(string expr, int index, out string name, out string value) { index = ParserHelper.SkipSpaces(expr, index); if (index >= expr.Length) { throw new XamlParserException("Object instantiation expression '{0}': '=' expected at position {1}", expr, index); } string nameOrValue; index = ParseNameOrValue(expr, index, out nameOrValue); index = ParserHelper.SkipSpaces(expr, index); if (index < expr.Length && expr[index] == '=') { name = nameOrValue; index += 1; index = ParseNameOrValue(expr, index, out value); index = ParserHelper.SkipSpaces(expr, index); } else { name = null; value = nameOrValue; } return(index); }
/// <summary> /// Parses an expression in an attribute value syntax for instantiating an element /// like a markup extension. The specified expression string must not contain /// the starting { and ending } characters. /// </summary> /// <param name="expr">Expression representing an object instantiation. /// This expression has the syntax /// <code> /// Object-Instantiation := [Expression-Name] <[Property]=[Value]<, ...>> /// </code> /// or /// <code> /// Object-Instantiation := [Expression-Name] <[Value]<, ...>> /// </code> /// Every parameter itself can again be a simple value assignment or an /// instantiation of another element. /// In this case, the according value expression has the syntax /// <code> /// [Value]={[Object-Instantiation]} /// </code></param> /// <param name="extensionName">Will be assigned to the name of the element /// instantiate.</param> /// <param name="parameters">Will contain a list of parameter assignments.</param> /// <param name="namedParams">Will contain the information, if the parameters /// are given in a <c>name = value</c> syntax or in a <c>param</c> syntax. /// Mixed syntax forms for different parameters are not supported. /// If no parameters were found, <paramref name="namedParams"/> will be set /// to <c>false</c>.</param> public static void ParseInstantiationExpression(string expr, out string extensionName, out IList <KeyValuePair <string, string> > parameters, out bool namedParams) { parameters = new List <KeyValuePair <string, string> >(); int i = expr.IndexOf(' '); if (i == -1) { extensionName = expr; namedParams = false; } else { extensionName = expr.Substring(0, i); i = ParserHelper.SkipSpaces(expr, i); bool?allNamedParams = null; while (i < expr.Length) { string name; string value; i = ParseParameter(expr, i, out name, out value); parameters.Add(new KeyValuePair <string, string>(name, value)); bool hasName = !string.IsNullOrEmpty(name); if (allNamedParams == null) { allNamedParams = hasName; } else if (allNamedParams.Value != hasName) { throw new XamlParserException("Object instantiation expression '{0}', position {1}: mixed named and unnamed parameters are not allowed", expr, i); } i = ParserHelper.SkipSpaces(expr, i); if (i >= expr.Length) { break; // End of expression reached - all parameters processed } if (expr[i] != ',') { throw new XamlParserException("Object instantiation expression syntax '{0}' is invalid at position {1}", expr, i); } i++; i = ParserHelper.SkipSpaces(expr, i); if (i >= expr.Length) { throw new XamlParserException("Object instantiation expression '{0}': parameter expected at position {1}", expr, i); } } namedParams = (allNamedParams ?? false); // Default when no params were parsed: namedParams == false } }
protected static int ParsePathSegment(IParserContext context, string path, int pos, out IPathSegment result) { pos = ParserHelper.SkipSpaces(path, pos); if (path[pos] == '[') { // Indexer expression object[] indices; pos = ParseIndices(context, path, pos, out indices); result = new IndexerPathSegment(indices); return(pos); } if (path[pos] == '(') { // Attached property int bracket = path.IndexOf(")", pos); if (bracket == -1) { throw new XamlParserException("Path '{0}': ')' expected", path); } int dot = path.IndexOf('.', pos); if (dot == -1 || dot > bracket) { throw new XamlParserException("Path '{0}': Attached property expected", path); } string propertyProvider = path.Substring(pos + 1, dot - pos - 1); string propertyName = path.Substring(dot + 1, bracket - dot - 1); string namespaceURI; context.LookupNamespace(propertyProvider, out propertyProvider, out namespaceURI); result = new AttachedPropertyPathSegment(context, propertyProvider, propertyName, namespaceURI); return(bracket + 1); } // Member int end = path.IndexOfAny(new char[] { '.', '[' }, pos); if (end == -1) { end = path.Length; } result = new MemberPathSegment(path.Substring(pos, end - pos)); if (path.IndexOf('[', pos) == end) { // Index follows member name object[] indices; end = ParseIndices(context, path, end, out indices); ((MemberPathSegment)result).SetIndices(indices); } return(end); }