diff Implab/Automaton/EnumAlphabet.cs @ 162:0526412bbb26 ref20160224

DFA refactoring
author cin
date Wed, 24 Feb 2016 08:39:53 +0300
parents
children ec35731ae299
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/Automaton/EnumAlphabet.cs	Wed Feb 24 08:39:53 2016 +0300
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Implab.Automaton {
+    /// <summary>
+    /// Алфавит символами которого являются элементы перечислений.
+    /// </summary>
+    /// <typeparam name="T">Тип перечислений</typeparam>
+    public class EnumAlphabet<T> : IndexedAlphabetBase<T> where T : struct, IConvertible {
+        [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")]
+        static readonly T[] _symbols;
+        static readonly EnumAlphabet<T> _fullAlphabet;
+
+        [SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
+        static EnumAlphabet() {
+            if (!typeof(T).IsEnum)
+                throw new InvalidOperationException("Invalid generic parameter, enumeration is required");
+
+            if (Enum.GetUnderlyingType(typeof(T)) != typeof(Int32))
+                throw new InvalidOperationException("Only enums based on Int32 are supported");
+
+            _symbols = ((T[])Enum.GetValues(typeof(T)))
+                .OrderBy(x => x.ToInt32(CultureInfo.InvariantCulture))
+                .ToArray();
+
+            if (
+                _symbols[_symbols.Length - 1].ToInt32(CultureInfo.InvariantCulture) >= _symbols.Length
+                || _symbols[0].ToInt32(CultureInfo.InvariantCulture) != 0
+            )
+                throw new InvalidOperationException("The specified enumeration must be zero-based and continuously numbered");
+
+            _fullAlphabet = new EnumAlphabet<T>(_symbols.Select(x => x.ToInt32(CultureInfo.InvariantCulture)).ToArray());
+        }
+
+        
+
+        public static EnumAlphabet<T> FullAlphabet {
+            get {
+                return _fullAlphabet;
+            }
+        }
+
+
+        public EnumAlphabet()
+            : base(_symbols.Length) {
+        }
+
+        public EnumAlphabet(int[] map)
+            : base(map) {
+            Debug.Assert(map.Length == _symbols.Length);
+        }
+
+
+        public override int GetSymbolIndex(T symbol) {
+            return symbol.ToInt32(CultureInfo.InvariantCulture);
+        }
+
+        public override IEnumerable<T> InputSymbols {
+            get { return _symbols; }
+        }
+
+    }
+}