view Implab/Automaton/MapAlphabet.cs @ 222:98eeb63cedb2

sync
author cin
date Tue, 22 Aug 2017 09:34:47 +0300
parents b2b6a6640aa3
children 302ca905c19e
line wrap: on
line source

using System;
using System.Collections.Generic;
using System.Linq;

namespace Implab.Automaton {
    public class MapAlphabet<T> : IAlphabetBuilder<T> {
        readonly Dictionary<T,int> m_map;
        int m_nextCls;
        readonly bool m_supportUnclassified;

        public MapAlphabet(bool supportUnclassified, IEqualityComparer<T> comparer) {
            m_map = comparer != null ? new Dictionary<T, int>(comparer) : new Dictionary<T,int>();
            m_supportUnclassified = supportUnclassified;
            m_nextCls = supportUnclassified ? 1 : 0;
        }

        #region IAlphabetBuilder implementation

        public int DefineSymbol(T symbol) {
            int cls;
            return m_map.TryGetValue(symbol, out cls) ? cls : DefineSymbol(symbol, m_nextCls);
        }

        public int DefineSymbol(T symbol, int cls) {
            Safe.ArgumentAssert(cls >= 0, "cls");

            m_nextCls = Math.Max(cls + 1, m_nextCls);
            m_map.Add(symbol, cls);
            return cls;
        }

        public int DefineClass(IEnumerable<T> symbols) {
            return DefineClass(symbols, m_nextCls);
        }

        public int DefineClass(IEnumerable<T> symbols, int cls) {
            Safe.ArgumentAssert(cls >= 0, "cls");
            Safe.ArgumentNotNull(symbols, "symbols");

            m_nextCls = Math.Max(cls + 1, m_nextCls);

            foreach (var symbol in symbols)
                m_map[symbol] = cls;
            return cls;
        }

        #endregion

        #region IAlphabet implementation

        public int Translate(T symbol) {
            int cls;
            if (m_map.TryGetValue(symbol, out cls))
                return cls;
            if (!m_supportUnclassified)
                throw new ArgumentOutOfRangeException("symbol", "The specified symbol isn't in the alphabet");
            return AutomatonConst.UNCLASSIFIED_INPUT;
        }

        public int Count {
            get {
                return m_nextCls;
            }
        }

        public bool Contains(T symbol) {
            return m_supportUnclassified || m_map.ContainsKey(symbol);
        }


        public IEnumerable<T> GetSymbols(int cls) {
            Safe.ArgumentAssert(!m_supportUnclassified || cls > 0, "cls");
            return m_map.Where(p => p.Value == cls).Select(p => p.Key);
        }
        #endregion

        public IEnumerable<KeyValuePair<T,int>> Mappings {
            get {
                return m_map;
            }
        }
    }
}