private List BuildSyntaxSpans()

in src/Trinity.VSExtension/TrinityVSExtension/EditorExtension/TSL/TSLParser.cs [347:501]


        private List<TSLSyntaxSpan> BuildSyntaxSpans(List<TSLTokenSpan> tokenSpanList, ITextSnapshot snapshot)
        {
            List<TSLSyntaxSpan> results = new List<TSLSyntaxSpan>();
            int cursor = 0;
            int length = tokenSpanList.Count;

            TSLNameDictionary dict = new TSLNameDictionary();

            TSLTokenSpan cTokenSpan;

            #region helper routines
            Action<TSLTokenSpan, TSLSyntaxSpanType> makeSingleTokenSpan = (token, syntaxSpanType) =>
                {
                    results.Add(new TSLSyntaxSpan(token.span, syntaxSpanType));
                };
            Action<TSLTokenSpan, TSLTokenSpan, TSLSyntaxSpanType> makeSpan = (token, endToken, syntaxSpanType) =>
                {
                    var rangeSpan = new SnapshotSpan(token.span.Start, endToken.span.End);
                    results.Add(new TSLSyntaxSpan(rangeSpan, syntaxSpanType));
                };
            Func<WrappedTokenType, bool> findSymbol = (type) => { while (++cursor < length) if (tokenSpanList[cursor].token == type) return true; return false; };
            Func<TSLTokenSpan> nextSymbol = () => { if (cursor + 1 < length)return tokenSpanList[cursor + 1]; else return null; };
            Action<TSLSyntaxSpanType> captureBlock = (type) =>
            {
                if (!findSymbol(WrappedTokenType.T_LCURLY))
                    return;
                var start = tokenSpanList[cursor];
                if (!findSymbol(WrappedTokenType.T_RCURLY))
                    return;
                var end = tokenSpanList[cursor];
                makeSpan(start, end, type);
            };
            Func<String> captureName = () =>
                {
                    var nToken = nextSymbol();
                    if (nToken == null || nToken.token != WrappedTokenType.T_IDENTIFIER)
                    {
                        return null;
                    }

                    return nToken.span.GetText();
                };
            Func<String> captureCellName = () =>
                {
                    var nToken = nextSymbol();
                    if (nToken != null && nToken.token == WrappedTokenType.T_STRUCT)
                    {
                        ++cursor;
                        nToken = nextSymbol();
                    }
                    if (nToken == null || nToken.token != WrappedTokenType.T_IDENTIFIER)
                    {
                        return null;
                    }

                    return nToken.span.GetText();
                };
            Action<string> addStruct = (name) =>
                {
                    if (name == null)
                        return;
                    dict.structs.Add(name);
                };
            Action<string> addCell = (name) =>
                {
                    if (name == null)
                        return;
                    dict.cells.Add(name);
                };
            Action<string> addProtocol = (name) =>
                {
                    if (name == null)
                        return;
                    dict.protocols.Add(name);
                };
            Action<string> addEnum = (name) =>
                {
                    if (name == null)
                        return;
                    dict.enums.Add(name);
                };
            Action captureAttributeSet = () =>
            {
                var start = tokenSpanList[cursor];
                if (!findSymbol(WrappedTokenType.T_RSQUARE))
                    return;
                var end = tokenSpanList[cursor];
                makeSpan(start, end, TSLSyntaxSpanType.AttributeSet);
            };

            tokenSpanList.RemoveAll(tokenSpan =>
                {
                    if (TSLSyntaxDefinition.isComment(tokenSpan.token))
                    {
                        makeSingleTokenSpan(tokenSpan, TSLSyntaxSpanType.Comments);
                        --length;
                        return true;
                    }
                    return false;
                });
            #endregion

            //TODO hierarchical scanning, and formal description of rules

            /* First round, scan {} blocks */
            for (cursor = 0; cursor < length; ++cursor)
            {
                cTokenSpan = tokenSpanList[cursor];
                switch (cTokenSpan.token)
                {
                    case WrappedTokenType.T_INCLUDE:
                        if (findSymbol(WrappedTokenType.T_SEMICOLON))
                            makeSpan(cTokenSpan, tokenSpanList[cursor], TSLSyntaxSpanType.IncludeBlock);
                        break;
                    case WrappedTokenType.T_TRINITY_SETTINGS:
                        captureBlock(TSLSyntaxSpanType.TrinitySettingBlock);
                        break;
                    case WrappedTokenType.T_CELL:
                        addCell(captureCellName());
                        captureBlock(TSLSyntaxSpanType.StructBlock);
                        break;
                    case WrappedTokenType.T_PROXY:
                    case WrappedTokenType.T_SERVER:
                    case WrappedTokenType.T_MODULE:
                        captureBlock(TSLSyntaxSpanType.ProtocolGroupBlock);
                        break;
                    case WrappedTokenType.T_STRUCT:
                        addStruct(captureName());
                        captureBlock(TSLSyntaxSpanType.StructBlock);
                        break;
                    case WrappedTokenType.T_PROTOCOL:
                        addProtocol(captureName());
                        captureBlock(TSLSyntaxSpanType.ProtocolBlock);
                        break;
                    case WrappedTokenType.T_ENUM:
                        addEnum(captureName());
                        captureBlock(TSLSyntaxSpanType.EnumBlock);
                        //TODO enum span
                        break;
                }
            }

            /* Second round, scan [] blocks */
            for (cursor = 0; cursor < length; ++cursor)
            {
                cTokenSpan = tokenSpanList[cursor];
                if (cTokenSpan.token == WrappedTokenType.T_LSQUARE)
                {
                    captureAttributeSet();
                }
            }

            SetNameDictionary(dict);
            return results;
        }