Changeset 1776
- Timestamp:
- 05/08/09 16:40:43 (16 years ago)
- Location:
- trunk/sources/HeuristicLab.Persistence
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Persistence/3.3/Auxiliary/TypeStringBuilder.cs
r1703 r1776 1 1 using System; 2 2 using System.Text; 3 using System.Text.RegularExpressions; 4 using System.Reflection.Emit; 5 using System.Collections.Generic; 3 6 4 7 namespace HeuristicLab.Persistence.Auxiliary { 5 8 6 internal static class TypeStringBuilder { 9 public class ParseError : Exception { 10 public ParseError(string message) : base(message) { } 11 } 12 13 public class TypeNameParser { 14 15 /* 16 TypeSpec := SimpleTypeSpec '&'? 17 18 SimpleTypeSpec := (IDENTIFIER '.')* 19 (IDENTIFIER '+')* 20 IDENTIFIER 21 ( '`\d+[' Generics ']' )? 22 (\*|\[(\d+\.\.\d+|\d+\.\.\.|(|\*)(,(|\*))*)\])* 23 (',\s*' IDENTIFIER (',\s*' AssemblyProperty)* )? 24 25 Generics := '[' SimpleTypeSpec ']' (',[' SimpleTypeSpec ']') 26 27 AssemblyProperty := 'Version=' Version 28 | 'PublicKey(Token)?=[a-fA-F0-9]+' 29 | 'Culture=[a-zA-F0-9]+' 30 31 Version := '\d+\.\d+\.\d+\.\d+)' 32 33 IDENTIFIER = [a-zA-Z][a-ZA-Z0-9]* 34 */ 35 36 37 class Token { 38 private static Dictionary<string, string> tokens = 39 new Dictionary<string, string> { 40 {"&", "AMPERSAND"}, 41 {".", "DOT"}, 42 {"+", "PLUS"}, 43 {",", "COMMA"}, 44 {"[", "OPEN_BRACKET"}, 45 {"]", "CLOSE_BRACKET"}, 46 {"*", "ASTERISK"}, 47 {" ", "SPACE"}, 48 {"=", "EQUALS"}, 49 {"`", "BACKTICK"} }; 50 private static Regex NumberRegex = new Regex("^\\d+$"); 51 private static Regex TokenRegex = new Regex("[&.+,\\[\\]* =`]|\\d+|[a-zA-Z][a-zA-Z0-9]*"); 52 public string Name { get; private set; } 53 public string Value { get; private set; } 54 public int? Number { get; private set; } 55 private Token(string value) { 56 if (tokens.ContainsKey(value)) { 57 Name = tokens[value]; 58 } else if (NumberRegex.IsMatch(value)) { 59 Number = int.Parse(value); 60 } else { 61 Value = value; 62 } 63 } 64 public static IEnumerable<Token> Tokenize(string s) { 65 foreach (Match m in TokenRegex.Matches(s)) { 66 yield return new Token(m.Value); 67 } 68 } 69 public override string ToString() { 70 if (Name != null) 71 return "Token(" + Name + ")"; 72 if (Value != null) 73 return "\"" + Value + "\""; 74 if (Number != null) 75 return Number.ToString(); 76 return "<empty>"; 77 } 78 } 79 80 Queue<Token> tokens; 81 82 private TypeNameParser(string s) { 83 tokens = new Queue<Token>(Token.Tokenize(s)); 84 } 85 86 public static string StripVersion(string s) { 87 TypeNameParser p = new TypeNameParser(s); 88 return p.TransformTypeSpec(); 89 } 90 91 92 private string TransformTypeSpec() { 93 string result = TransformSimpleTypeSpec(); 94 if (ConsumeToken("AMPERSAND")) { 95 return result + "&"; 96 } else { 97 return result; 98 } 99 } 100 101 private string TransformSimpleTypeSpec() { 102 List<string> nameSpace = new List<string>(); 103 nameSpace.Add(ConsumeIdentifier()); 104 while (ConsumeToken("DOT")) 105 nameSpace.Add(ConsumeIdentifier()); 106 List<string> typeName = new List<string>(); 107 if (nameSpace.Count > 0) { 108 typeName.Add(nameSpace[nameSpace.Count - 1]); 109 nameSpace.RemoveAt(nameSpace.Count - 1); 110 } 111 while (ConsumeToken("PLUS")) 112 typeName.Add(ConsumeIdentifier()); 113 string genericString = ""; 114 if (ConsumeToken("BACKTICK")) { 115 string number = ConsumeNumber().ToString(); 116 ConsumeToken("OPEN_BRACKET", true); 117 string generics = TransformGenerics(); 118 ConsumeToken("CLOSE_BRACKET", true); 119 genericString = "`" + number + "[" + generics + "]"; 120 } 121 StringBuilder pointerOrArray = new StringBuilder(); 122 while (true) { 123 if (ConsumeToken("ASTERSIK")) { 124 pointerOrArray.Append("*"); 125 } else if (ConsumeToken("OPEN_BRACKET")) { 126 ParseDimension(pointerOrArray); 127 while (ConsumeToken("COMMA")) { 128 pointerOrArray.Append(","); 129 ParseDimension(pointerOrArray); 130 } 131 ConsumeToken("CLOSE_BRACKET", true); 132 } else { 133 break; 134 } 135 } 136 string assembly = ""; 137 if (ConsumeComma()) { 138 assembly = ConsumeIdentifier(); 139 while (ConsumeComma()) { 140 TransformAssemblyProperty(); 141 } 142 } 143 return string.Join(".", nameSpace.ToArray()) + "." + 144 string.Join("+", typeName.ToArray()) + 145 genericString + 146 pointerOrArray.ToString() + 147 ", " + 148 assembly; 149 } 150 151 private void ParseDimension(StringBuilder sb) { 152 if (ConsumeToken("ASTERSIK")) { 153 sb.Append("*"); 154 } else if (CanConsumeNumber()) { 155 sb.Append(ConsumeNumber()); 156 ConsumeToken("DOT", true); 157 ConsumeToken("DOT", true); 158 if (ConsumeToken("DOT")) { 159 sb.Append("..."); 160 } else { 161 sb.Append("..").Append(ConsumeNumber()); 162 } 163 } 164 } 165 166 private string TransformGenerics() { 167 ConsumeToken("OPEN_BRACKET", true); 168 List<string> typenames = new List<string>(); 169 typenames.Add(TransformSimpleTypeSpec()); 170 ConsumeToken("CLOSE_BRACKET", true); 171 while (ConsumeToken("COMMA")) { 172 ConsumeToken("OPEN_BRACKET", true); 173 typenames.Add(TransformSimpleTypeSpec()); 174 ConsumeToken("CLOSE_BRACKET", true); 175 } 176 return "[" + string.Join("],[", typenames.ToArray()) + "]"; 177 } 178 179 private string TransformAssemblyProperty() { 180 if (ConsumeIdentifier("Version")) { 181 ConsumeToken("EQUALS", true); 182 TransformVersion(); 183 } else if (ConsumeIdentifier("PublicKey")) { 184 ConsumeToken("EQUALS", true); 185 ConsumeIdentifier(); 186 } else if (ConsumeIdentifier("PublicKeyToken")) { 187 ConsumeToken("EQUALS", true); 188 ConsumeIdentifier(); 189 } else if (ConsumeIdentifier("Culture")) { 190 ConsumeToken("EQUALS", true); 191 ConsumeIdentifier(); 192 } else if (ConsumeIdentifier("Custom")) { 193 ConsumeToken("EQUALS", true); 194 ConsumeIdentifier(); 195 } else { 196 throw new ParseError(String.Format( 197 "Invalid assembly property \"{0}\"", 198 tokens.Peek().ToString())); 199 } 200 return ""; 201 } 202 private string TransformVersion() { 203 ConsumeNumber(); 204 ConsumeToken("DOT"); 205 ConsumeNumber(); 206 ConsumeToken("DOT"); 207 ConsumeNumber(); 208 ConsumeToken("DOT"); 209 ConsumeNumber(); 210 return ""; 211 } 212 213 private bool CanConsumeNumber() { 214 if (tokens.Count == 0) 215 return false; 216 return tokens.Peek().Number != null; 217 } 218 219 private int ConsumeNumber() { 220 if (tokens.Count == 0) 221 throw new ParseError("End of input while expecting number"); 222 if (tokens.Peek().Number != null) 223 return (int)tokens.Dequeue().Number; 224 throw new ParseError(string.Format( 225 "Number expected, found \"{0}\" instead", 226 tokens.Peek().ToString())); 227 } 228 229 private bool ConsumeIdentifier(string value) { 230 if (tokens.Count == 0) 231 return false; 232 if (tokens.Peek().Value == value) { 233 tokens.Dequeue(); 234 return true; 235 } else { 236 return false; 237 } 238 } 239 240 private string ConsumeIdentifier() { 241 if (tokens.Count == 0) 242 throw new ParseError("End of input while expecting identifier"); 243 if (tokens.Peek().Value != null) 244 return tokens.Dequeue().Value; 245 throw new ParseError(String.Format( 246 "Identifier expected, found \"{0}\" instead", 247 tokens.Peek().ToString())); 248 } 249 250 private bool ConsumeComma() { 251 if (ConsumeToken("COMMA")) { 252 while (ConsumeToken("SPACE")) ; 253 return true; 254 } else { 255 return false; 256 } 257 } 258 259 private bool ConsumeToken(string name) { 260 return ConsumeToken(name, false); 261 } 262 263 private bool ConsumeToken(string name, bool force) { 264 if (tokens.Count == 0) 265 if (force) 266 throw new ParseError(String.Format( 267 "end of input while expecting token \"{0}\"", 268 name)); 269 else 270 return false; 271 if (tokens.Peek().Name == name) { 272 tokens.Dequeue(); 273 return true; 274 } else if (force) { 275 throw new ParseError(String.Format( 276 "expected \"{0}\" found \"{1}\"", 277 name, 278 tokens.Peek().ToString())); 279 } else { 280 return false; 281 } 282 } 283 284 } 285 286 public class TypeName { 287 public bool IsReference { get; private set; } 288 public bool IsArray { get { return Dimension.Length > 0; } } 289 public bool IsPointer { get; private set; } 290 public bool IsGeneric { get { return GenericArgs.Count > 0; } } 291 public List<TypeName> GenericArgs { get; private set; } 292 public string Dimension { get; private set; } 293 public string ClassName { get; private set; } 294 public string Namespace { get; private set; } 295 public string AssemblyNmae { get; private set; } 296 public string AssemblyAttribues { get; private set; } 297 public TypeName(string typeName) { 298 } 299 } 300 301 public static class TypeStringBuilder { 7 302 8 303 internal static void BuildDeclaringTypeChain(Type type, StringBuilder sb) { … … 32 327 } 33 328 329 public static string StripVersion(string typename) { 330 return TypeNameParser.StripVersion(typename); 331 } 332 34 333 } 35 334 -
trunk/sources/HeuristicLab.Persistence/UnitTests/UseCases.cs
r1734 r1776 14 14 using HeuristicLab.Persistence.Default.Xml.Primitive; 15 15 using HeuristicLab.Persistence.Default.Decomposers; 16 using HeuristicLab.Persistence.Auxiliary; 16 17 17 18 namespace HeuristicLab.Persistence.UnitTest { … … 522 523 } 523 524 525 [TestMethod] 526 public void TestTypeStringConversion() { 527 string version = TypeStringBuilder.StripVersion(typeof(List<int>[]).AssemblyQualifiedName); 528 Assert.AreEqual(version, typeof(List<int>[]).VersionInvariantName()); 529 } 530 524 531 [ClassInitialize] 525 532 public static void Initialize(TestContext testContext) { 526 533 ConfigurationService.Instance.Reset(); 527 } 528 } 534 } 535 } 529 536 }
Note: See TracChangeset
for help on using the changeset viewer.