comparison Implab/Automaton/EnumAlphabet.cs @ 164:ec35731ae299 ref20160224

Almost complete DFA refactoring
author cin
date Thu, 25 Feb 2016 02:11:13 +0300
parents 0526412bbb26
children c32688129f14
comparison
equal deleted inserted replaced
163:419aa51b04fd 164:ec35731ae299
10 /// Алфавит символами которого являются элементы перечислений. 10 /// Алфавит символами которого являются элементы перечислений.
11 /// </summary> 11 /// </summary>
12 /// <typeparam name="T">Тип перечислений</typeparam> 12 /// <typeparam name="T">Тип перечислений</typeparam>
13 public class EnumAlphabet<T> : IndexedAlphabetBase<T> where T : struct, IConvertible { 13 public class EnumAlphabet<T> : IndexedAlphabetBase<T> where T : struct, IConvertible {
14 [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] 14 [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
15 static readonly T[] _symbols; 15 static readonly Lazy<T[]> _symbols = new Lazy<T[]>(GetSymbols);
16 static readonly EnumAlphabet<T> _fullAlphabet;
17 16
18 [SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] 17 [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
19 static EnumAlphabet() { 18 static readonly Lazy<EnumAlphabet<T>> _fullAlphabet = new Lazy<EnumAlphabet<T>>(CreateEnumAlphabet);
19
20 static EnumAlphabet<T> CreateEnumAlphabet() {
21 var symbols = _symbols.Value;
22
23 if (
24 symbols[symbols.Length - 1].ToInt32(CultureInfo.InvariantCulture) >= symbols.Length
25 || symbols[0].ToInt32(CultureInfo.InvariantCulture) != 0
26 )
27 throw new InvalidOperationException("The specified enumeration must be zero-based and continuously numbered");
28
29 return new EnumAlphabet<T>(symbols.Select(x => x.ToInt32(CultureInfo.InvariantCulture)).ToArray());
30 }
31
32 static T[] GetSymbols() {
20 if (!typeof(T).IsEnum) 33 if (!typeof(T).IsEnum)
21 throw new InvalidOperationException("Invalid generic parameter, enumeration is required"); 34 throw new InvalidOperationException("Invalid generic parameter, enumeration is required");
22 35
23 if (Enum.GetUnderlyingType(typeof(T)) != typeof(Int32)) 36 if (Enum.GetUnderlyingType(typeof(T)) != typeof(Int32))
24 throw new InvalidOperationException("Only enums based on Int32 are supported"); 37 throw new InvalidOperationException("Only enums based on Int32 are supported");
25 38
26 _symbols = ((T[])Enum.GetValues(typeof(T))) 39 return ((T[])Enum.GetValues(typeof(T)))
27 .OrderBy(x => x.ToInt32(CultureInfo.InvariantCulture)) 40 .OrderBy(x => x.ToInt32(CultureInfo.InvariantCulture))
28 .ToArray(); 41 .ToArray();
29
30 if (
31 _symbols[_symbols.Length - 1].ToInt32(CultureInfo.InvariantCulture) >= _symbols.Length
32 || _symbols[0].ToInt32(CultureInfo.InvariantCulture) != 0
33 )
34 throw new InvalidOperationException("The specified enumeration must be zero-based and continuously numbered");
35
36 _fullAlphabet = new EnumAlphabet<T>(_symbols.Select(x => x.ToInt32(CultureInfo.InvariantCulture)).ToArray());
37 } 42 }
38
39
40 43
41 public static EnumAlphabet<T> FullAlphabet { 44 public static EnumAlphabet<T> FullAlphabet {
42 get { 45 get {
43 return _fullAlphabet; 46 return _fullAlphabet.Value;
44 } 47 }
45 } 48 }
46 49
47 50
48 public EnumAlphabet() 51 public EnumAlphabet()
49 : base(_symbols.Length) { 52 : base(_symbols.Value.Length) {
50 } 53 }
51 54
52 public EnumAlphabet(int[] map) 55 public EnumAlphabet(int[] map)
53 : base(map) { 56 : base(map) {
54 Debug.Assert(map.Length == _symbols.Length); 57 Debug.Assert(map.Length == _symbols.Value.Length);
55 } 58 }
56 59
57 60
58 public override int GetSymbolIndex(T symbol) { 61 public override int GetSymbolIndex(T symbol) {
59 return symbol.ToInt32(CultureInfo.InvariantCulture); 62 return symbol.ToInt32(CultureInfo.InvariantCulture);
60 } 63 }
61 64
62 public override IEnumerable<T> InputSymbols { 65 public override IEnumerable<T> InputSymbols {
63 get { return _symbols; } 66 get { return _symbols.Value; }
64 } 67 }
65 68
66 } 69 }
67 } 70 }