@@ -0,0 +1,25 | |||||
|
1 | using System; | |||
|
2 | using System.Collections.Generic; | |||
|
3 | ||||
|
4 | namespace Implab.Parsing { | |||
|
5 | public interface IAlphabetBuilder<TSymbol> : IAlphabet<TSymbol> { | |||
|
6 | /// <summary> | |||
|
7 | /// Добавляет новый символ в алфавит, если символ уже был добавлен, то | |||
|
8 | /// возвращается ранее сопоставленный с символом класс. | |||
|
9 | /// </summary> | |||
|
10 | /// <param name="symbol">Символ для добавления.</param> | |||
|
11 | /// <returns>Индекс класса, который попоставлен с символом.</returns> | |||
|
12 | int DefineSymbol(TSymbol symbol); | |||
|
13 | /// <summary> | |||
|
14 | /// Доабвляем класс символов. Множеству указанных исходных символов | |||
|
15 | /// будет сопоставлен символ в алфавите. | |||
|
16 | /// </summary> | |||
|
17 | /// <param name="symbols">Множестов исходных символов</param> | |||
|
18 | /// <returns>Идентификатор символа алфавита.</returns> | |||
|
19 | int DefineClass(IEnumerable<TSymbol> symbols); | |||
|
20 | ||||
|
21 | ||||
|
22 | ||||
|
23 | } | |||
|
24 | } | |||
|
25 |
@@ -0,0 +1,9 | |||||
|
1 | using System; | |||
|
2 | ||||
|
3 | namespace Implab.Parsing { | |||
|
4 | public interface IDFADefinitionBuilder<TInput, TState, TTag> : IDFADefinition<TInput, TState, TTag> { | |||
|
5 | ||||
|
6 | ||||
|
7 | } | |||
|
8 | } | |||
|
9 |
@@ -7,9 +7,6 | |||||
7 | <OutputType>Library</OutputType> |
|
7 | <OutputType>Library</OutputType> | |
8 | <RootNamespace>Implab</RootNamespace> |
|
8 | <RootNamespace>Implab</RootNamespace> | |
9 | <AssemblyName>Implab</AssemblyName> |
|
9 | <AssemblyName>Implab</AssemblyName> | |
10 | <ProductVersion>8.0.30703</ProductVersion> |
|
|||
11 | <SchemaVersion>2.0</SchemaVersion> |
|
|||
12 | <ReleaseVersion>0.2</ReleaseVersion> |
|
|||
13 | <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
|
10 | <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | |
14 | </PropertyGroup> |
|
11 | </PropertyGroup> | |
15 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|
12 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |
@@ -184,6 +181,8 | |||||
184 | <Compile Include="Parsing\DFADefinition.cs" /> |
|
181 | <Compile Include="Parsing\DFADefinition.cs" /> | |
185 | <Compile Include="Parsing\IndexedAlphabetBase.cs" /> |
|
182 | <Compile Include="Parsing\IndexedAlphabetBase.cs" /> | |
186 | <Compile Include="Parsing\CharAlphabet.cs" /> |
|
183 | <Compile Include="Parsing\CharAlphabet.cs" /> | |
|
184 | <Compile Include="Parsing\IAlphabetBuilder.cs" /> | |||
|
185 | <Compile Include="Parsing\IDFADefinitionBuilder.cs" /> | |||
187 | </ItemGroup> |
|
186 | </ItemGroup> | |
188 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> |
|
187 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> | |
189 | <ItemGroup /> |
|
188 | <ItemGroup /> |
@@ -5,28 +5,20 using System.Diagnostics; | |||||
5 | using System.Linq; |
|
5 | using System.Linq; | |
6 |
|
6 | |||
7 | namespace Implab.Parsing { |
|
7 | namespace Implab.Parsing { | |
8 | public class DFADefinition : IDFADefinition { |
|
8 | public class DFADefinition<TInput, TState, TTag> : IDFADefinition<TInput, TState, TTag> { | |
9 | readonly List<DFAStateDescriptior> m_states; |
|
9 | readonly List<DFAStateDescriptior<TTag>> m_states; | |
10 |
|
10 | |||
11 | public const int INITIAL_STATE = 1; |
|
11 | public const int INITIAL_STATE = 1; | |
12 | public const int UNREACHEBLE_STATE = 0; |
|
12 | public const int UNREACHEBLE_STATE = 0; | |
13 |
|
13 | |||
14 | DFAStateDescriptior[] m_statesArray; |
|
14 | DFAStateDescriptior<TTag>[] m_statesArray; | |
15 | readonly int m_alpabetSize; |
|
15 | readonly int m_alpabetSize; | |
16 |
|
16 | |||
17 | public DFADefinition(int alphabetSize) { |
|
17 | public DFADefinition(int alphabetSize) { | |
18 | m_states = new List<DFAStateDescriptior>(); |
|
18 | m_states = new List<DFAStateDescriptior<TTag>>(); | |
19 | m_alpabetSize = alphabetSize; |
|
19 | m_alpabetSize = alphabetSize; | |
20 |
|
20 | |||
21 | m_states.Add(new DFAStateDescriptior()); |
|
21 | m_states.Add(new DFAStateDescriptior<TTag>()); | |
22 | } |
|
|||
23 |
|
||||
24 | public DFAStateDescriptior[] States { |
|
|||
25 | get { |
|
|||
26 | if (m_statesArray == null) |
|
|||
27 | m_statesArray = m_states.ToArray(); |
|
|||
28 | return m_statesArray; |
|
|||
29 | } |
|
|||
30 | } |
|
22 | } | |
31 |
|
23 | |||
32 | public bool InitialStateIsFinal { |
|
24 | public bool InitialStateIsFinal { | |
@@ -37,7 +29,7 namespace Implab.Parsing { | |||||
37 |
|
29 | |||
38 | public int AddState() { |
|
30 | public int AddState() { | |
39 | var index = m_states.Count; |
|
31 | var index = m_states.Count; | |
40 | m_states.Add(new DFAStateDescriptior { |
|
32 | m_states.Add(new DFAStateDescriptior<TTag> { | |
41 | final = false, |
|
33 | final = false, | |
42 | transitions = new int[AlphabetSize] |
|
34 | transitions = new int[AlphabetSize] | |
43 | }); |
|
35 | }); | |
@@ -46,10 +38,10 namespace Implab.Parsing { | |||||
46 | return index; |
|
38 | return index; | |
47 | } |
|
39 | } | |
48 |
|
40 | |||
49 |
public int AddState( |
|
41 | public int AddState(TTag[] tag) { | |
50 | var index = m_states.Count; |
|
42 | var index = m_states.Count; | |
51 | bool final = tag != null && tag.Length != 0; |
|
43 | bool final = tag != null && tag.Length != 0; | |
52 | m_states.Add(new DFAStateDescriptior { |
|
44 | m_states.Add(new DFAStateDescriptior<TTag> { | |
53 | final = final, |
|
45 | final = final, | |
54 | transitions = new int[AlphabetSize], |
|
46 | transitions = new int[AlphabetSize], | |
55 | tag = final ? tag : null |
|
47 | tag = final ? tag : null | |
@@ -58,15 +50,41 namespace Implab.Parsing { | |||||
58 | return index; |
|
50 | return index; | |
59 | } |
|
51 | } | |
60 |
|
52 | |||
61 |
public void DefineTransition( |
|
53 | public void DefineTransition(TState s1, TState s2, TInput symbol) { | |
62 | Safe.ArgumentInRange(s1, 0, m_states.Count-1, "s1"); |
|
54 | int is1 = StateAlphabet.Translate(s1); | |
63 | Safe.ArgumentInRange(s2, 0, m_states.Count-1, "s2"); |
|
55 | int is2 = StateAlphabet.Translate(s2); | |
64 | Safe.ArgumentInRange(symbol, 0, AlphabetSize-1, "symbol"); |
|
56 | int isym = InputAlphabet.Translate(symbol); | |
65 |
|
57 | |||
66 | m_states[s1].transitions[symbol] = s2; |
|
58 | Safe.ArgumentAssert(is1 != 0, "s1"); | |
|
59 | Safe.ArgumentAssert(is2 != 0, "s2"); | |||
|
60 | Safe.ArgumentAssert(isym != 0, "symbol"); | |||
|
61 | ||||
|
62 | m_states[is1].transitions[isym] = is2; | |||
67 | } |
|
63 | } | |
68 |
|
64 | |||
69 | protected IDFADefinition Optimize<TA>(Func<IAlphabet<TA>, IDFADefinition> dfaFactory,IAlphabet<TA> sourceAlphabet, IAlphabet<TA> minimalAlphabet) { |
|
65 | #region IDFADefinition implementation | |
|
66 | ||||
|
67 | public DFAStateDescriptior<TTag>[] GetTransitionTable() { | |||
|
68 | if (m_statesArray == null) | |||
|
69 | m_statesArray = m_states.ToArray(); | |||
|
70 | return m_statesArray; | |||
|
71 | } | |||
|
72 | ||||
|
73 | public IAlphabet<TInput> InputAlphabet { | |||
|
74 | get { | |||
|
75 | throw new NotImplementedException(); | |||
|
76 | } | |||
|
77 | } | |||
|
78 | ||||
|
79 | public IAlphabet<TState> StateAlphabet { | |||
|
80 | get { | |||
|
81 | throw new NotImplementedException(); | |||
|
82 | } | |||
|
83 | } | |||
|
84 | ||||
|
85 | #endregion | |||
|
86 | ||||
|
87 | protected IDFADefinition<> Optimize<TA>(Func<IAlphabet<TA>, IDFADefinition> dfaFactory,IAlphabet<TA> sourceAlphabet, IAlphabet<TA> minimalAlphabet) { | |||
70 | Safe.ArgumentNotNull(dfaFactory, "dfaFactory"); |
|
88 | Safe.ArgumentNotNull(dfaFactory, "dfaFactory"); | |
71 | Safe.ArgumentNotNull(minimalAlphabet, "minimalAlphabet"); |
|
89 | Safe.ArgumentNotNull(minimalAlphabet, "minimalAlphabet"); | |
72 |
|
90 |
@@ -5,9 +5,9 using System.Text; | |||||
5 | using System.Threading.Tasks; |
|
5 | using System.Threading.Tasks; | |
6 |
|
6 | |||
7 | namespace Implab.Parsing { |
|
7 | namespace Implab.Parsing { | |
8 | public struct DFAStateDescriptior { |
|
8 | public struct DFAStateDescriptior<TTag> { | |
9 | public bool final; |
|
9 | public bool final; | |
10 |
public |
|
10 | public TTag[] tag; | |
11 | public int[] transitions; |
|
11 | public int[] transitions; | |
12 | } |
|
12 | } | |
13 | } |
|
13 | } |
@@ -12,43 +12,31 namespace Implab.Parsing { | |||||
12 | /// <remarks> |
|
12 | /// <remarks> | |
13 | /// <para>Алфавит является сюрьективным отображением множества символов в множество индексов, это позволяет сократить размер таблицы переходов автомата |
|
13 | /// <para>Алфавит является сюрьективным отображением множества символов в множество индексов, это позволяет сократить размер таблицы переходов автомата | |
14 | /// для входных символов, которые для него не различимы.</para> |
|
14 | /// для входных символов, которые для него не различимы.</para> | |
15 | /// <para>Далее символами алфавита будем называть классы исходных символов.</para> |
|
|||
16 | /// </remarks> |
|
15 | /// </remarks> | |
17 | /// <typeparam name="TSymbol">Тип символов.</typeparam> |
|
16 | /// <typeparam name="TSymbol">Тип символов.</typeparam> | |
18 | public interface IAlphabet<TSymbol> { |
|
17 | public interface IAlphabet<TSymbol> { | |
19 | /// <summary> |
|
18 | /// <summary> | |
20 | /// Количество символов в алфавите. |
|
19 | /// Количество классов символов в алфавите. | |
21 | /// </summary> |
|
20 | /// </summary> | |
22 | int Count { get; } |
|
21 | int Count { get; } | |
23 | /// <summary> |
|
22 | ||
24 | /// Добавляет новый символ в алфавит, если символ уже был добавлен, то |
|
|||
25 | /// возвращается ранее сопоставленный с символом класс. |
|
|||
26 | /// </summary> |
|
|||
27 | /// <param name="symbol">Символ для добавления.</param> |
|
|||
28 | /// <returns>Индекс класса, который попоставлен с символом.</returns> |
|
|||
29 | int DefineSymbol(TSymbol symbol); |
|
|||
30 | /// <summary> |
|
23 | /// <summary> | |
31 | /// Доабвляем класс символов. Множеству указанных исходных символов |
|
24 | /// Создает карту обратного сопоставления класса символов алфавита и сопоставленным | |
32 | /// будет сопоставлен символ в алфавите. |
|
|||
33 | /// </summary> |
|
|||
34 | /// <param name="symbols">Множестов исходных символов</param> |
|
|||
35 | /// <returns>Идентификатор символа алфавита.</returns> |
|
|||
36 | int DefineClass(IEnumerable<TSymbol> symbols); |
|
|||
37 | /// <summary> |
|
|||
38 | /// Создает карту обратного сопоставления символа алфавита и сопоставленным |
|
|||
39 | /// ему исходным символам. |
|
25 | /// ему исходным символам. | |
40 | /// </summary> |
|
26 | /// </summary> | |
41 | /// <returns></returns> |
|
27 | /// <returns></returns> | |
42 | List<TSymbol>[] CreateReverseMap(); |
|
28 | List<TSymbol>[] CreateReverseMap(); | |
|
29 | ||||
43 | /// <summary> |
|
30 | /// <summary> | |
44 | /// Создает новый алфавит на основе текущего, горппируя его сиволы в более |
|
31 | /// Создает новый алфавит на основе текущего, горппируя его сиволы в более | |
45 | /// крупные непересекающиеся классы символов. |
|
32 | /// крупные непересекающиеся классы символов. | |
46 | /// </summary> |
|
33 | /// </summary> | |
47 | /// <param name="newAlphabet">Новый, пустой алфавит, в котором быдут определены классы.</param> |
|
34 | /// <param name="newAlphabet">Новый, пустой алфавит, в котором быдут определены классы.</param> | |
48 | /// <param name="classes">Множество классов символов текущего алфавита.</param> |
|
35 | /// <param name="classes">Множество классов символов текущего алфавита.</param> | |
49 |
/// <returns>Карта для перехода |
|
36 | /// <returns>Карта для перехода классов текущего | |
50 |
/// алфавита к |
|
37 | /// алфавита к классам нового.</returns> | |
51 | int[] Reclassify(IAlphabet<TSymbol> newAlphabet, IEnumerable<ICollection<int>> classes); |
|
38 | /// <remarks>Ползволяет укрупнить алфавит, объединив классы в текущем алфавите. Используется при оптимизации автомата.</remarks> | |
|
39 | int[] Reclassify(IAlphabetBuilder<TSymbol> newAlphabet, IEnumerable<ICollection<int>> classes); | |||
52 |
|
40 | |||
53 | /// <summary> |
|
41 | /// <summary> | |
54 | /// Преобразует входной символ в индекс символа из алфавита. |
|
42 | /// Преобразует входной символ в индекс символа из алфавита. |
@@ -6,34 +6,56 using System.Threading.Tasks; | |||||
6 |
|
6 | |||
7 | namespace Implab.Parsing { |
|
7 | namespace Implab.Parsing { | |
8 | /// <summary> |
|
8 | /// <summary> | |
9 | /// Интерфейс для определения ДКА, позволяет добавить состояния и определить переходы. |
|
9 | /// Полностью описывает DFA автомат, его поведение, состояние и входные символы. | |
10 | /// </summary> |
|
10 | /// </summary> | |
11 | public interface IDFADefinition { |
|
11 | /// <example> | |
|
12 | /// class MyAutomaton { | |||
|
13 | /// int m_current; | |||
|
14 | /// readonly DFAStateDescriptor<string>[] m_automaton; | |||
|
15 | /// readonly IAlphabet<MyCommands> m_commands; | |||
|
16 | /// | |||
|
17 | /// public MyAutomaton(IDFADefinition<MyCommands,MyStates,string> definition) { | |||
|
18 | /// m_current = definition.StateAlphabet.Translate(MyStates.Initial); | |||
|
19 | /// m_automaton = definition.GetTransitionTable(); | |||
|
20 | /// m_commands = definition.InputAlphabet; | |||
|
21 | /// } | |||
|
22 | /// | |||
|
23 | /// // defined a method which will move the automaton to the next state | |||
|
24 | /// public void Move(MyCommands cmd) { | |||
|
25 | /// // use transition map to determine the next state | |||
|
26 | /// var next = m_automaton[m_current].transitions[m_commands.Translate(cmd)]; | |||
|
27 | /// | |||
|
28 | /// // validate that we aren't in the unreachable state | |||
|
29 | /// if (next == DFAConst.UNREACHABLE_STATE) | |||
|
30 | /// throw new InvalidOperationException("The specified command is invalid"); | |||
|
31 | /// | |||
|
32 | /// // if everything is ok | |||
|
33 | /// m_current = next; | |||
|
34 | /// } | |||
|
35 | /// } | |||
|
36 | /// </example> | |||
|
37 | public interface IDFADefinition<TInput, TState, TTag> { | |||
12 | /// <summary> |
|
38 | /// <summary> | |
13 | /// Добавляет состояние в автомат. |
|
39 | /// Алфавит входных символов | |
14 | /// </summary> |
|
|||
15 | /// <returns>Индекс добавленного состояния.</returns> |
|
|||
16 | int AddState(); |
|
|||
17 | /// <summary> |
|
|||
18 | /// Добавляет конечное состояние с указанными метками, если метки не заданы, то |
|
|||
19 | /// добавленное состояние не будет конечным. |
|
|||
20 | /// </summary> |
|
40 | /// </summary> | |
21 | /// <param name="tags">Метки состояния.</param> |
|
41 | /// <value>The input alphabet.</value> | |
22 | /// <returns>Индекс добавленного состояния.</returns> |
|
42 | IAlphabet<TInput> InputAlphabet { | |
23 | int AddState(int[] tags); |
|
43 | get; | |
|
44 | } | |||
|
45 | ||||
24 | /// <summary> |
|
46 | /// <summary> | |
25 | /// Определяет переход между состояниями. |
|
47 | /// Алфавит состояний автомата | |
26 | /// </summary> |
|
48 | /// </summary> | |
27 | /// <param name="s1">Исходное состояние.</param> |
|
49 | /// <value>The state alphabet.</value> | |
28 | /// <param name="s2">Конечное состояние.</param> |
|
50 | IAlphabet<TState> StateAlphabet { | |
29 | /// <param name="input">Входной символ.</param> |
|
51 | get; | |
30 | void DefineTransition(int s1, int s2, int input); |
|
52 | } | |
|
53 | ||||
31 | /// <summary> |
|
54 | /// <summary> | |
32 | /// Размер входного алфавита. |
|
55 | /// Таблица переходов состояний автомата | |
33 | /// </summary> |
|
56 | /// </summary> | |
34 | /// <remarks> |
|
57 | /// <returns>The transition table.</returns> | |
35 | /// Размер входного алфавита определяет количество возможных выходов из одного состояния. <see cref="IAlphabet{TSymbol}.Count"/> |
|
58 | DFAStateDescriptior<TTag>[] GetTransitionTable(); | |
36 | /// </remarks> |
|
59 | ||
37 | int AlphabetSize { get; } |
|
|||
38 | } |
|
60 | } | |
39 | } |
|
61 | } |
@@ -9,6 +9,11 namespace Implab | |||||
9 | { |
|
9 | { | |
10 | public static class Safe |
|
10 | public static class Safe | |
11 | { |
|
11 | { | |
|
12 | public static void ArgumentAssert(bool condition, string paramName) { | |||
|
13 | if (!condition) | |||
|
14 | throw new ArgumentException("The parameter is invalid", paramName); | |||
|
15 | } | |||
|
16 | ||||
12 | public static void ArgumentMatch(string value, string paramName, Regex rx) { |
|
17 | public static void ArgumentMatch(string value, string paramName, Regex rx) { | |
13 | if (rx == null) |
|
18 | if (rx == null) | |
14 | throw new ArgumentNullException("rx"); |
|
19 | throw new ArgumentNullException("rx"); |
General Comments 0
You need to be logged in to leave comments.
Login now