Mercurial > pub > ImplabNet
comparison Implab/Automaton/RegularExpressions/Grammar.cs @ 165:e227e78d72e4 ref20160224
DFA refactoring
author | cin |
---|---|
date | Mon, 29 Feb 2016 02:02:17 +0300 |
parents | ec35731ae299 |
children | 92d5278d1b10 |
comparison
equal
deleted
inserted
replaced
164:ec35731ae299 | 165:e227e78d72e4 |
---|---|
1 using Implab; | 1 using Implab; |
2 using System; | 2 using System; |
3 using System.Collections.Generic; | 3 using System.Collections.Generic; |
4 using System.Linq; | 4 using System.Linq; |
5 using System.Text; | |
6 using System.Threading.Tasks; | |
7 | 5 |
8 namespace Implab.Automaton.RegularExpressions { | 6 namespace Implab.Automaton.RegularExpressions { |
9 /// <summary> | 7 /// <summary> |
10 /// Базовый абстрактный класс. Грамматика, позволяет формулировать выражения над алфавитом типа <c>char</c>. | 8 /// Базовый абстрактный класс. Грамматика, позволяет формулировать выражения над алфавитом типа <c>char</c>. |
11 /// </summary> | 9 /// </summary> |
12 public abstract class Grammar<TSymbol, TTag> { | 10 public abstract class Grammar<TSymbol, TTag> { |
13 | 11 |
14 public abstract IAlphabetBuilder<TSymbol> Alphabet { | 12 protected abstract IAlphabetBuilder<TSymbol> AlphabetBuilder { |
15 get; | 13 get; |
16 } | 14 } |
17 | 15 |
18 public SymbolToken<TTag> UnclassifiedToken() { | 16 protected SymbolToken<TTag> UnclassifiedToken() { |
19 return new SymbolToken<TTag>(DFAConst.UNCLASSIFIED_INPUT); | 17 return new SymbolToken<TTag>(DFAConst.UNCLASSIFIED_INPUT); |
20 } | 18 } |
21 | 19 |
22 public void DefineAlphabet(IEnumerable<TSymbol> alphabet) { | 20 protected void DefineAlphabet(IEnumerable<TSymbol> alphabet) { |
23 Safe.ArgumentNotNull(alphabet, "alphabet"); | 21 Safe.ArgumentNotNull(alphabet, "alphabet"); |
24 | 22 |
25 foreach (var ch in alphabet) | 23 foreach (var ch in alphabet) |
26 Alphabet.DefineSymbol(ch); | 24 AlphabetBuilder.DefineSymbol(ch); |
27 } | 25 } |
28 | 26 |
29 public Token<TTag> SymbolToken(TSymbol symbol) { | 27 protected Token<TTag> SymbolToken(TSymbol symbol) { |
30 return Token<TTag>.New(TranslateOrAdd(symbol)); | 28 return Token<TTag>.New(TranslateOrAdd(symbol)); |
31 } | 29 } |
32 | 30 |
33 public Token<TTag> SymbolToken(IEnumerable<TSymbol> symbols) { | 31 protected Token<TTag> SymbolToken(IEnumerable<TSymbol> symbols) { |
34 Safe.ArgumentNotNull(symbols, "symbols"); | 32 Safe.ArgumentNotNull(symbols, "symbols"); |
35 | 33 |
36 return Token<TTag>.New(TranslateOrAdd(symbols).ToArray()); | 34 return Token<TTag>.New(TranslateOrAdd(symbols).ToArray()); |
37 } | 35 } |
38 | 36 |
39 public Token<TTag> SymbolSetToken(params TSymbol[] set) { | 37 protected Token<TTag> SymbolSetToken(params TSymbol[] set) { |
40 return SymbolToken(set); | 38 return SymbolToken(set); |
41 } | 39 } |
42 | 40 |
43 int TranslateOrAdd(TSymbol ch) { | 41 int TranslateOrAdd(TSymbol ch) { |
44 var t = Alphabet.Translate(ch); | 42 var t = AlphabetBuilder.Translate(ch); |
45 if (t == DFAConst.UNCLASSIFIED_INPUT) | 43 if (t == DFAConst.UNCLASSIFIED_INPUT) |
46 t = Alphabet.DefineSymbol(ch); | 44 t = AlphabetBuilder.DefineSymbol(ch); |
47 return t; | 45 return t; |
48 } | 46 } |
49 | 47 |
50 IEnumerable<int> TranslateOrAdd(IEnumerable<TSymbol> symbols) { | 48 IEnumerable<int> TranslateOrAdd(IEnumerable<TSymbol> symbols) { |
51 return symbols.Distinct().Select(TranslateOrAdd); | 49 return symbols.Distinct().Select(TranslateOrAdd); |
52 } | 50 } |
53 | 51 |
54 int TranslateOrDie(TSymbol ch) { | 52 int TranslateOrDie(TSymbol ch) { |
55 var t = Alphabet.Translate(ch); | 53 var t = AlphabetBuilder.Translate(ch); |
56 if (t == DFAConst.UNCLASSIFIED_INPUT) | 54 if (t == DFAConst.UNCLASSIFIED_INPUT) |
57 throw new ApplicationException(String.Format("Symbol '{0}' is UNCLASSIFIED", ch)); | 55 throw new ApplicationException(String.Format("Symbol '{0}' is UNCLASSIFIED", ch)); |
58 return t; | 56 return t; |
59 } | 57 } |
60 | 58 |
61 IEnumerable<int> TranslateOrDie(IEnumerable<TSymbol> symbols) { | 59 IEnumerable<int> TranslateOrDie(IEnumerable<TSymbol> symbols) { |
62 return symbols.Distinct().Select(TranslateOrDie); | 60 return symbols.Distinct().Select(TranslateOrDie); |
63 } | 61 } |
64 | 62 |
65 public Token<TTag> SymbolTokenExcept(IEnumerable<TSymbol> symbols) { | 63 protected Token<TTag> SymbolTokenExcept(IEnumerable<TSymbol> symbols) { |
66 Safe.ArgumentNotNull(symbols, "symbols"); | 64 Safe.ArgumentNotNull(symbols, "symbols"); |
67 | 65 |
68 return Token<TTag>.New( Enumerable.Range(0, Alphabet.Count).Except(TranslateOrDie(symbols)).ToArray() ); | 66 return Token<TTag>.New( Enumerable.Range(0, AlphabetBuilder.Count).Except(TranslateOrDie(symbols)).ToArray() ); |
69 } | 67 } |
70 | 68 |
71 protected CDFADefinition BuildDFA(Token<TTag> lang) { | 69 protected void BuildDFA(Token<TTag> lang, IDFATableBuilder<TTag> dfaTable, IAlphabetBuilder<TSymbol> dfaAlphabet) { |
72 Safe.ArgumentNotNull(lang, "lang"); | 70 Safe.ArgumentNotNull(lang, "lang"); |
71 Safe.ArgumentNotNull(dfaAlphabet, "dfaAlphabet"); | |
73 | 72 |
74 var dfa = new RegularDFADefinition<TSymbol, TTag>(Alphabet, 0); | 73 var dfa = new RegularDFADefinition<TSymbol, TTag>(AlphabetBuilder); |
75 | |
76 var table = new DFATransitionTable<TTag>(); | |
77 | 74 |
78 var builder = new RegularDFABuilder<TTag>(); | 75 var builder = new RegularDFABuilder<TTag>(); |
79 | 76 |
80 lang.Accept( builder ); | 77 lang.Accept( builder ); |
81 | 78 |
82 var initialState = builder.BuildDFA(table); | 79 builder.BuildDFA(dfa); |
83 if (table.IsFinalState(initialState)) | 80 |
81 if (dfa.IsFinalState(dfa.InitialState)) | |
84 throw new ApplicationException("The specified language contains empty token"); | 82 throw new ApplicationException("The specified language contains empty token"); |
85 | 83 |
86 return dfa.Optimize(); | 84 dfa.Optimize(dfaTable, dfaAlphabet); |
85 | |
87 } | 86 } |
88 | 87 |
89 | |
90 | |
91 //protected abstract TGrammar CreateInstance(); | |
92 } | 88 } |
93 | 89 |
94 | 90 |
95 } | 91 } |