コード例 #1
0
        internal static string GetPropertyName(this SourceValueInfo info)
        {
            switch (info.type)
            {
            case SourceValueType.Direct:
                return(null);

            case SourceValueType.Property:
                var propertyName = info.name?.Trim();
                if (propertyName != null && propertyName.StartsWith("(") && propertyName.EndsWith(")"))
                {
                    var indexOfDot = propertyName.LastIndexOf(".");
                    if (indexOfDot < 0)
                    {
                        return(propertyName.Substring(1, propertyName.Length - 2));
                    }
                    return(propertyName.Substring(indexOfDot + 1, propertyName.Length - indexOfDot - 2));
                }
                return(propertyName);

            case SourceValueType.Indexer:
                return("Item");

            default:
                throw new InvalidOperationException("Unexpected SourceValueType.");
            }
        }
コード例 #2
0
        internal static string GetTypeName(this SourceValueInfo info)
        {
            var propertyName = info.name?.Trim();

            if (propertyName != null && propertyName.StartsWith("(") && propertyName.EndsWith(")"))
            {
                var indexOfDot = propertyName.LastIndexOf(".");
                if (indexOfDot < 0)
                {
                    return(null);
                }
                return(propertyName.Substring(1, indexOfDot - 1));
            }
            return(null);
        }
コード例 #3
0
        void AddProperty()
        {
            int start = _index;
            int level = 0;

            // include leading dots in the path (for XLinq)
            while (_index < _n && _path[_index] == '.')
            {
                ++_index;
            }

            while (_index < _n && (level > 0 || SpecialChars.IndexOf(_path[_index]) < 0))
            {
                if (_path[_index] == '(')
                {
                    ++level;
                }
                else if (_path[_index] == ')')
                {
                    --level;
                }

                ++_index;
            }

            if (level > 0)
            {
                SetError(Resources.UnmatchedParen, _path.Substring(start));
                return;
            }

            if (level < 0)
            {
                SetError(Resources.UnmatchedParen, _path.Substring(0, _index));
                return;
            }

            string name = _path.Substring(start, _index - start).Trim();

            SourceValueInfo info = (name.Length > 0)
                                ? new SourceValueInfo(SourceValueType.Property, _drillIn, name)
                                : new SourceValueInfo(SourceValueType.Direct, _drillIn, (string)null);

            _al.Add(info);

            StartNewLevel();
        }
コード例 #4
0
        // Each level of the path consists of
        //      a property or indexer:
        //                  .propname
        //                  /propname
        //                  [index]
        //                  /[index]
        //          (The . or / is optional in the very first level.)
        // The parser is a finite-state machine with two states corresponding
        // to the two-character lookahead above, plus two more states for the begining
        // and end.  The state transistions are done explicitly in the code below.
        //
        // The parser returns a 0-length array if it finds a syntax error.
        // It sets the Error property, so the caller can find out what happened.

        public SourceValueInfo[] Parse(string path)
        {
            _path = (path != null) ? path.Trim() : String.Empty;
            _n    = _path.Length;

            if (_n == 0)
            {
                // When no path string is specified, use value directly and do not drill-in. (same as Path=".")
                // ClrBindingWorker needs this information to tell XmlBindingWorker about collectionMode.
                return(new SourceValueInfo[] { new SourceValueInfo(SourceValueType.Direct, DrillIn.Never, (string)null) });
            }

            _index   = 0;
            _drillIn = DrillIn.IfNeeded;

            _al.Clear();
            Error  = null;
            _state = State.Init;

            while (_state != State.Done)
            {
                char c = (_index < _n) ? _path[_index] : NullChar;
                if (Char.IsWhiteSpace(c))
                {
                    ++_index;
                    continue;
                }

                switch (_state)
                {
                case State.Init:
                    switch (c)
                    {
                    case '/':
                    case '.':
                    case NullChar:
                        _state = State.DrillIn;
                        break;

                    default:
                        _state = State.Prop;
                        break;
                    }
                    break;

                case State.DrillIn:
                    switch (c)
                    {
                    case '/':
                        _drillIn = DrillIn.Always;
                        ++_index;
                        break;

                    case '.':
                        _drillIn = DrillIn.Never;
                        ++_index;
                        break;

                    case '[':
                    case NullChar:
                        break;

                    default:
                        SetError(Resources.InvalidPathSyntax, _path.Substring(0, _index), _path.Substring(_index));
                        return(EmptyInfo);
                    }
                    _state = State.Prop;
                    break;

                case State.Prop:
                    bool isIndexer = false;
                    switch (c)
                    {
                    case '[':
                        isIndexer = true;
                        break;

                    default:
                        break;
                    }

                    if (isIndexer)
                    {
                        AddIndexer();
                    }
                    else
                    {
                        AddProperty();
                    }

                    break;
                }
            }


            SourceValueInfo[] result;

            if (Error == null)
            {
                result = new SourceValueInfo[_al.Count];
                _al.CopyTo(result);
            }
            else
            {
                result = EmptyInfo;
            }

            return(result);
        }
コード例 #5
0
        void AddIndexer()
        {
            // indexer args are parsed by a (sub-) state machine with four
            // states.  The string is a comma-separated list of params, each
            // of which has two parts:  a "paren string" and a "value string"
            // (both parts are optional).  The character ^ can be used to
            // escape any of the special characters:  comma, parens, ], ^,
            // and white space.

            int start = ++_index;                   // skip over initial [
            int level = 1;                          // level of nested []

            bool escaped   = false;                 // true if current char is escaped
            bool trimRight = false;                 // true if value string has trailing white space

            StringBuilder parenStringBuilder = new StringBuilder();
            StringBuilder valueStringBuilder = new StringBuilder();

            List <IndexerParamInfo> paramList = new List <IndexerParamInfo>(0);

            IndexerState state = IndexerState.BeginParam;

            while (state != IndexerState.Done)
            {
                if (_index >= _n)
                {
                    SetError(Resources.UnmatchedBracket, _path.Substring(start - 1));
                    return;
                }

                Char c = _path[_index++];

                // handle the escape character - set the flag for the next character
                if (c == EscapeChar && !escaped)
                {
                    escaped = true;
                    continue;
                }

                switch (state)
                {
                case IndexerState.BeginParam:                           // look for optional (...)
                    if (escaped)
                    {
                        // no '(', go parse the value
                        state = IndexerState.ValueString;
                        goto case IndexerState.ValueString;
                    }
                    else if (c == '(')
                    {
                        // '(' introduces optional paren string
                        state = IndexerState.ParenString;
                    }
                    else if (Char.IsWhiteSpace(c))
                    {
                        // ignore leading white space
                    }
                    else
                    {
                        // no '(', go parse the value
                        state = IndexerState.ValueString;
                        goto case IndexerState.ValueString;
                    }
                    break;

                case IndexerState.ParenString:                          // parse (...)
                    if (escaped)
                    {
                        // add an escaped character without question
                        parenStringBuilder.Append(c);
                    }
                    else if (c == ')')
                    {
                        // end of (...), start to parse value
                        state = IndexerState.ValueString;
                    }
                    else
                    {
                        // add normal characters inside (...)
                        parenStringBuilder.Append(c);
                    }
                    break;

                case IndexerState.ValueString:                          // parse value
                    if (escaped)
                    {
                        // add an escaped character without question
                        valueStringBuilder.Append(c);
                        trimRight = false;
                    }
                    else if (level > 1)
                    {
                        // inside nested [], add characters without question
                        valueStringBuilder.Append(c);
                        trimRight = false;

                        if (c == ']')
                        {
                            --level;
                        }
                    }
                    else if (Char.IsWhiteSpace(c))
                    {
                        // add white space, but trim it later if it's trailing
                        valueStringBuilder.Append(c);
                        trimRight = true;
                    }
                    else if (c == ',' || c == ']')
                    {
                        // end of current paramater - assemble the two parts
                        string parenString = parenStringBuilder.ToString();
                        string valueString = valueStringBuilder.ToString();
                        if (trimRight)
                        {
                            valueString = valueString.TrimEnd();
                        }

                        // add the parts to the final result
                        paramList.Add(new IndexerParamInfo(parenString, valueString));

                        // reset for the next parameter
                        parenStringBuilder.Length = 0;
                        valueStringBuilder.Length = 0;
                        trimRight = false;

                        // after ',' parse next parameter;  after ']' we're done
                        state = (c == ']') ? IndexerState.Done : IndexerState.BeginParam;
                    }
                    else
                    {
                        // add normal characters
                        valueStringBuilder.Append(c);
                        trimRight = false;

                        // keep track of nested []
                        if (c == '[')
                        {
                            ++level;
                        }
                    }
                    break;
                }

                // after processing each character, clear the escape flag
                escaped = false;
            }

            // assemble the final result
            SourceValueInfo info = new SourceValueInfo(
                SourceValueType.Indexer,
                _drillIn, paramList);

            _al.Add(info);

            StartNewLevel();
        }