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