TypeReferenceParser.cs
174 lines
| 4.9 KiB
| text/x-csharp
|
CSharpLexer
cin
|
r267 | using System; | |
using System.Collections.Generic; | |||
using System.Text.RegularExpressions; | |||
namespace Implab.ServiceHost.Unity { | |||
cin
|
r268 | internal class TypeReferenceParser { | |
cin
|
r267 | enum TokenType { | |
None, | |||
Word, | |||
Dot, | |||
Comma, | |||
OpenList, | |||
CloseList, | |||
cin
|
r277 | OpenArray, | |
CloseArray, | |||
cin
|
r267 | Eof | |
} | |||
cin
|
r277 | readonly Regex _tokens = new Regex(@"([\w\+]+)|\s*([\.{},\[\]])\s*"); | |
cin
|
r267 | ||
TokenType m_token; | |||
string m_tokenValue; | |||
int m_pos; | |||
cin
|
r268 | int m_tokenPos; | |
cin
|
r267 | readonly string m_text; | |
TokenType Token { get { return m_token; } } | |||
string TokenValue { get { return m_tokenValue; } } | |||
cin
|
r268 | int TokenPos { get { return m_tokenPos; } } | |
cin
|
r267 | public TypeReferenceParser(string text) { | |
Safe.ArgumentNotEmpty(text, nameof(text)); | |||
m_text = text; | |||
} | |||
bool ReadToken() { | |||
if (m_pos >= m_text.Length) { | |||
m_token = TokenType.Eof; | |||
m_tokenValue = null; | |||
return false; | |||
} | |||
var m = _tokens.Match(m_text, m_pos); | |||
if (m.Success) { | |||
cin
|
r268 | m_tokenPos = m_pos; | |
cin
|
r267 | m_pos += m.Length; | |
if (m.Groups[1].Success) { | |||
m_token = TokenType.Word; | |||
m_tokenValue = m.Groups[1].Value; | |||
} else if (m.Groups[2].Success) { | |||
m_tokenValue = null; | |||
switch (m.Groups[2].Value) { | |||
case "{": | |||
m_token = TokenType.OpenList; | |||
break; | |||
case "}": | |||
m_token = TokenType.CloseList; | |||
break; | |||
case ".": | |||
m_token = TokenType.Dot; | |||
break; | |||
case ",": | |||
m_token = TokenType.Comma; | |||
break; | |||
cin
|
r277 | case "[": | |
m_token = TokenType.OpenArray; | |||
break; | |||
case "]": | |||
m_token = TokenType.CloseArray; | |||
break; | |||
cin
|
r267 | } | |
} | |||
return true; | |||
} | |||
throw new FormatException($"Failed to parse '{m_text}' at pos {m_pos}"); | |||
} | |||
cin
|
r268 | public TypeReference Parse() { | |
var result = ReadTypeReference(); | |||
cin
|
r277 | if (Token != TokenType.Eof) | |
cin
|
r268 | ThrowUnexpectedToken(); | |
return result; | |||
cin
|
r267 | } | |
string[] ReadTypeName() { | |||
var parts = new List<string>(); | |||
string current = null; | |||
bool stop = false; | |||
while ((!stop) && ReadToken()) { | |||
switch (Token) { | |||
case TokenType.Word: | |||
if (current != null) | |||
ThrowUnexpectedToken(); | |||
current = TokenValue; | |||
break; | |||
case TokenType.Dot: | |||
if (current == null) | |||
ThrowUnexpectedToken(); | |||
parts.Add(current); | |||
current = null; | |||
break; | |||
default: | |||
stop = true; | |||
break; | |||
} | |||
} | |||
if (current != null) | |||
parts.Add(current); | |||
if (parts.Count == 0) | |||
return null; | |||
return parts.ToArray(); | |||
} | |||
TypeReference ReadTypeReference() { | |||
var parts = ReadTypeName(); | |||
if (parts == null) | |||
return null; | |||
var typeReference = new TypeReference { | |||
cin
|
r268 | Namespace = string.Join(".", parts, 0, parts.Length - 1), | |
TypeName = parts[parts.Length - 1] | |||
}; | |||
cin
|
r267 | ||
switch (Token) { | |||
case TokenType.OpenList: | |||
typeReference.GenericParameters = ReadTypeReferenceList(); | |||
cin
|
r268 | if (Token != TokenType.CloseList) | |
cin
|
r267 | ThrowUnexpectedToken(); | |
cin
|
r268 | ReadToken(); | |
cin
|
r267 | break; | |
} | |||
return typeReference; | |||
} | |||
cin
|
r277 | int CountDimentions() { | |
return 0; | |||
} | |||
cin
|
r267 | TypeReference[] ReadTypeReferenceList() { | |
cin
|
r268 | var list = new List<TypeReference>(); | |
cin
|
r267 | ||
cin
|
r268 | do { | |
var typeReference = ReadTypeReference(); | |||
list.Add(typeReference); | |||
} while (Token == TokenType.Comma); | |||
return list.ToArray(); | |||
cin
|
r267 | } | |
void ThrowUnexpectedToken() { | |||
cin
|
r268 | throw new FormatException($"Unexpected '{Token}' at pos {TokenPos}: -->{m_text.Substring(TokenPos, Math.Min(m_text.Length - TokenPos, 10))}"); | |
cin
|
r267 | } | |
} | |||
} |