using Implab;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace Implab.Automaton {
///
/// Indexed alphabet is the finite set of symbols where each symbol has a zero-based unique index.
///
///
/// Indexed alphabets are usefull in bulting efficient translations from source alphabet
/// to the input alphabet of the automaton. It's assumed that the index to the symbol match
/// is well known and documented.
///
public abstract class IndexedAlphabetBase : IAlphabetBuilder {
int m_nextId = 1;
readonly int[] m_map;
protected IndexedAlphabetBase(int mapSize) {
m_map = new int[mapSize];
}
protected IndexedAlphabetBase(int[] map) {
Debug.Assert(map != null && map.Length > 0);
Debug.Assert(map.All(x => x >= 0));
m_map = map;
m_nextId = map.Max() + 1;
}
public int DefineSymbol(T symbol) {
var index = GetSymbolIndex(symbol);
if (m_map[index] == DFAConst.UNCLASSIFIED_INPUT)
m_map[index] = m_nextId++;
return m_map[index];
}
public int DefineSymbol(T symbol, int cls) {
var index = GetSymbolIndex(symbol);
m_map[index] = cls;
m_nextId = Math.Max(cls + 1, m_nextId);
return cls;
}
public int DefineClass(IEnumerable symbols) {
return DefineClass(symbols, m_nextId);
}
public int DefineClass(IEnumerable symbols, int cls) {
Safe.ArgumentNotNull(symbols, "symbols");
symbols = symbols.Distinct();
foreach (var symbol in symbols)
m_map[GetSymbolIndex(symbol)] = cls;
m_nextId = Math.Max(cls + 1, m_nextId);
return cls;
}
public virtual int Translate(T symbol) {
return m_map[GetSymbolIndex(symbol)];
}
public int Count {
get { return m_nextId; }
}
public bool Contains(T symbol) {
return true;
}
public abstract int GetSymbolIndex(T symbol);
public abstract IEnumerable InputSymbols { get; }
///
/// Gets the translation map from the index of the symbol to it's class this is usefull for the optimized input symbols transtaion.
///
/// The translation map.
public int[] GetTranslationMap() {
return m_map;
}
}
}