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;
}