diff --git a/Implab/Implab.csproj b/Implab/Implab.csproj --- a/Implab/Implab.csproj +++ b/Implab/Implab.csproj @@ -7,9 +7,6 @@ Library Implab Implab - 8.0.30703 - 2.0 - 0.2 v4.5 @@ -184,6 +181,8 @@ + + diff --git a/Implab/Parsing/DFADefinition.cs b/Implab/Parsing/DFADefinition.cs --- a/Implab/Parsing/DFADefinition.cs +++ b/Implab/Parsing/DFADefinition.cs @@ -5,28 +5,20 @@ using System.Diagnostics; using System.Linq; namespace Implab.Parsing { - public class DFADefinition : IDFADefinition { - readonly List m_states; + public class DFADefinition : IDFADefinition { + readonly List> m_states; public const int INITIAL_STATE = 1; public const int UNREACHEBLE_STATE = 0; - DFAStateDescriptior[] m_statesArray; + DFAStateDescriptior[] m_statesArray; readonly int m_alpabetSize; public DFADefinition(int alphabetSize) { - m_states = new List(); + m_states = new List>(); m_alpabetSize = alphabetSize; - m_states.Add(new DFAStateDescriptior()); - } - - public DFAStateDescriptior[] States { - get { - if (m_statesArray == null) - m_statesArray = m_states.ToArray(); - return m_statesArray; - } + m_states.Add(new DFAStateDescriptior()); } public bool InitialStateIsFinal { @@ -37,7 +29,7 @@ namespace Implab.Parsing { public int AddState() { var index = m_states.Count; - m_states.Add(new DFAStateDescriptior { + m_states.Add(new DFAStateDescriptior { final = false, transitions = new int[AlphabetSize] }); @@ -46,10 +38,10 @@ namespace Implab.Parsing { return index; } - public int AddState(int[] tag) { + public int AddState(TTag[] tag) { var index = m_states.Count; bool final = tag != null && tag.Length != 0; - m_states.Add(new DFAStateDescriptior { + m_states.Add(new DFAStateDescriptior { final = final, transitions = new int[AlphabetSize], tag = final ? tag : null @@ -58,15 +50,41 @@ namespace Implab.Parsing { return index; } - public void DefineTransition(int s1,int s2, int symbol) { - Safe.ArgumentInRange(s1, 0, m_states.Count-1, "s1"); - Safe.ArgumentInRange(s2, 0, m_states.Count-1, "s2"); - Safe.ArgumentInRange(symbol, 0, AlphabetSize-1, "symbol"); + public void DefineTransition(TState s1, TState s2, TInput symbol) { + int is1 = StateAlphabet.Translate(s1); + int is2 = StateAlphabet.Translate(s2); + int isym = InputAlphabet.Translate(symbol); - m_states[s1].transitions[symbol] = s2; + Safe.ArgumentAssert(is1 != 0, "s1"); + Safe.ArgumentAssert(is2 != 0, "s2"); + Safe.ArgumentAssert(isym != 0, "symbol"); + + m_states[is1].transitions[isym] = is2; } - protected IDFADefinition Optimize(Func, IDFADefinition> dfaFactory,IAlphabet sourceAlphabet, IAlphabet minimalAlphabet) { + #region IDFADefinition implementation + + public DFAStateDescriptior[] GetTransitionTable() { + if (m_statesArray == null) + m_statesArray = m_states.ToArray(); + return m_statesArray; + } + + public IAlphabet InputAlphabet { + get { + throw new NotImplementedException(); + } + } + + public IAlphabet StateAlphabet { + get { + throw new NotImplementedException(); + } + } + + #endregion + + protected IDFADefinition<> Optimize(Func, IDFADefinition> dfaFactory,IAlphabet sourceAlphabet, IAlphabet minimalAlphabet) { Safe.ArgumentNotNull(dfaFactory, "dfaFactory"); Safe.ArgumentNotNull(minimalAlphabet, "minimalAlphabet"); diff --git a/Implab/Parsing/DFAStateDescriptor.cs b/Implab/Parsing/DFAStateDescriptor.cs --- a/Implab/Parsing/DFAStateDescriptor.cs +++ b/Implab/Parsing/DFAStateDescriptor.cs @@ -5,9 +5,9 @@ using System.Text; using System.Threading.Tasks; namespace Implab.Parsing { - public struct DFAStateDescriptior { + public struct DFAStateDescriptior { public bool final; - public int[] tag; + public TTag[] tag; public int[] transitions; } } diff --git a/Implab/Parsing/IAlphabet.cs b/Implab/Parsing/IAlphabet.cs --- a/Implab/Parsing/IAlphabet.cs +++ b/Implab/Parsing/IAlphabet.cs @@ -12,43 +12,31 @@ namespace Implab.Parsing { /// /// Алфавит является сюрьективным отображением множества символов в множество индексов, это позволяет сократить размер таблицы переходов автомата /// для входных символов, которые для него не различимы. - /// Далее символами алфавита будем называть классы исходных символов. /// /// Тип символов. public interface IAlphabet { /// - /// Количество символов в алфавите. + /// Количество классов символов в алфавите. /// int Count { get; } - /// - /// Добавляет новый символ в алфавит, если символ уже был добавлен, то - /// возвращается ранее сопоставленный с символом класс. - /// - /// Символ для добавления. - /// Индекс класса, который попоставлен с символом. - int DefineSymbol(TSymbol symbol); + /// - /// Доабвляем класс символов. Множеству указанных исходных символов - /// будет сопоставлен символ в алфавите. - /// - /// Множестов исходных символов - /// Идентификатор символа алфавита. - int DefineClass(IEnumerable symbols); - /// - /// Создает карту обратного сопоставления символа алфавита и сопоставленным + /// Создает карту обратного сопоставления класса символов алфавита и сопоставленным /// ему исходным символам. /// /// List[] CreateReverseMap(); + /// /// Создает новый алфавит на основе текущего, горппируя его сиволы в более /// крупные непересекающиеся классы символов. /// /// Новый, пустой алфавит, в котором быдут определены классы. /// Множество классов символов текущего алфавита. - /// Карта для перехода символов текущего - /// алфавита к символам нового. - int[] Reclassify(IAlphabet newAlphabet, IEnumerable> classes); + /// Карта для перехода классов текущего + /// алфавита к классам нового. + /// Ползволяет укрупнить алфавит, объединив классы в текущем алфавите. Используется при оптимизации автомата. + int[] Reclassify(IAlphabetBuilder newAlphabet, IEnumerable> classes); /// /// Преобразует входной символ в индекс символа из алфавита. diff --git a/Implab/Parsing/IAlphabetBuilder.cs b/Implab/Parsing/IAlphabetBuilder.cs new file mode 100644 --- /dev/null +++ b/Implab/Parsing/IAlphabetBuilder.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace Implab.Parsing { + public interface IAlphabetBuilder : IAlphabet { + /// + /// Добавляет новый символ в алфавит, если символ уже был добавлен, то + /// возвращается ранее сопоставленный с символом класс. + /// + /// Символ для добавления. + /// Индекс класса, который попоставлен с символом. + int DefineSymbol(TSymbol symbol); + /// + /// Доабвляем класс символов. Множеству указанных исходных символов + /// будет сопоставлен символ в алфавите. + /// + /// Множестов исходных символов + /// Идентификатор символа алфавита. + int DefineClass(IEnumerable symbols); + + + + } +} + diff --git a/Implab/Parsing/IDFADefinition.cs b/Implab/Parsing/IDFADefinition.cs --- a/Implab/Parsing/IDFADefinition.cs +++ b/Implab/Parsing/IDFADefinition.cs @@ -6,34 +6,56 @@ using System.Threading.Tasks; namespace Implab.Parsing { /// - /// Интерфейс для определения ДКА, позволяет добавить состояния и определить переходы. + /// Полностью описывает DFA автомат, его поведение, состояние и входные символы. /// - public interface IDFADefinition { + /// + /// class MyAutomaton { + /// int m_current; + /// readonly DFAStateDescriptor[] m_automaton; + /// readonly IAlphabet m_commands; + /// + /// public MyAutomaton(IDFADefinition<MyCommands,MyStates,string> definition) { + /// m_current = definition.StateAlphabet.Translate(MyStates.Initial); + /// m_automaton = definition.GetTransitionTable(); + /// m_commands = definition.InputAlphabet; + /// } + /// + /// // defined a method which will move the automaton to the next state + /// public void Move(MyCommands cmd) { + /// // use transition map to determine the next state + /// var next = m_automaton[m_current].transitions[m_commands.Translate(cmd)]; + /// + /// // validate that we aren't in the unreachable state + /// if (next == DFAConst.UNREACHABLE_STATE) + /// throw new InvalidOperationException("The specified command is invalid"); + /// + /// // if everything is ok + /// m_current = next; + /// } + /// } + /// + public interface IDFADefinition { /// - /// Добавляет состояние в автомат. - /// - /// Индекс добавленного состояния. - int AddState(); - /// - /// Добавляет конечное состояние с указанными метками, если метки не заданы, то - /// добавленное состояние не будет конечным. + /// Алфавит входных символов /// - /// Метки состояния. - /// Индекс добавленного состояния. - int AddState(int[] tags); + /// The input alphabet. + IAlphabet InputAlphabet { + get; + } + /// - /// Определяет переход между состояниями. + /// Алфавит состояний автомата /// - /// Исходное состояние. - /// Конечное состояние. - /// Входной символ. - void DefineTransition(int s1, int s2, int input); + /// The state alphabet. + IAlphabet StateAlphabet { + get; + } + /// - /// Размер входного алфавита. + /// Таблица переходов состояний автомата /// - /// - /// Размер входного алфавита определяет количество возможных выходов из одного состояния. - /// - int AlphabetSize { get; } + /// The transition table. + DFAStateDescriptior[] GetTransitionTable(); + } } diff --git a/Implab/Parsing/IDFADefinitionBuilder.cs b/Implab/Parsing/IDFADefinitionBuilder.cs new file mode 100644 --- /dev/null +++ b/Implab/Parsing/IDFADefinitionBuilder.cs @@ -0,0 +1,9 @@ +using System; + +namespace Implab.Parsing { + public interface IDFADefinitionBuilder : IDFADefinition { + + + } +} + diff --git a/Implab/Safe.cs b/Implab/Safe.cs --- a/Implab/Safe.cs +++ b/Implab/Safe.cs @@ -9,6 +9,11 @@ namespace Implab { public static class Safe { + public static void ArgumentAssert(bool condition, string paramName) { + if (!condition) + throw new ArgumentException("The parameter is invalid", paramName); + } + public static void ArgumentMatch(string value, string paramName, Regex rx) { if (rx == null) throw new ArgumentNullException("rx");