/// <summary> /// 填充 DFA 的数据。 /// </summary> /// <param name="grammar">词法分析器使用的语法。</param> /// <param name="useTrailing">是否用到了向前看。</param> private void FillDfa(Grammar <T> grammar, out bool useTrailing) { // 构造 DFA。 Nfa nfa = BuildNfa(grammar, out useTrailing); int headCnt = this.contextCount * 2; Dfa dfa = nfa.BuildDfa(headCnt); dfa.Minimize(headCnt); // 获取 DFA 的数据。 this.charClass = dfa.CharClass.GetCharClassMap(); this.stateCount = dfa.Count; this.states = new StateData[stateCount]; this.charClassCount = dfa.CharClass.Count; for (int i = 0; i < this.stateCount; i++) { DfaState state = dfa[i]; int[] transitions = new int[charClassCount]; for (int j = 0; j < charClassCount; j++) { DfaState target = state[j]; if (target == null) { transitions[j] = Constants.DeadState; } else { transitions[j] = target.Index; } } states[i] = new StateData(transitions, state.SymbolIndex); } }
/// <summary> /// 初始化 <see cref="DfaState"/> 类的新实例。 /// </summary> /// <param name="dfa">状态所在的 DFA。</param> /// <param name="index">状态的索引。</param> public DfaState(Dfa dfa, int index) { this.Dfa = dfa; this.Index = index; this.transitions = new DfaState[dfa.CharClass.Count]; }
/// <summary> /// 根据当前的 NFA 构造 DFA,采用子集构造法。 /// </summary> /// <param name="headCnt">头节点的个数。</param> internal Dfa BuildDfa(int headCnt) { Dfa dfa = new Dfa(charClass); // DFA 和 NFA 的状态映射表,DFA 的一个状态对应 NFA 的一个状态集合。 Dictionary <DfaState, HashSet <NfaState> > stateMap = new Dictionary <DfaState, HashSet <NfaState> >(); // 由 NFA 状态集合到对应的 DFA 状态的映射表(与上表互逆)。 Dictionary <HashSet <NfaState>, DfaState> dfaStateMap = new Dictionary <HashSet <NfaState>, DfaState>(SetEqualityComparer <NfaState> .Default); Stack <DfaState> stack = new Stack <DfaState>(); // 添加头节点。 for (int i = 0; i < headCnt; i++) { DfaState head = dfa.NewState(); head.SymbolIndex = new int[0]; HashSet <NfaState> headStates = EpsilonClosure(Enumerable.Repeat(this[i], 1)); stateMap.Add(head, headStates); dfaStateMap.Add(headStates, head); stack.Push(head); } int charClassCnt = charClass.Count; while (stack.Count > 0) { DfaState state = stack.Pop(); HashSet <NfaState> stateSet = stateMap[state]; // 遍历字符类。 for (int i = 0; i < charClassCnt; i++) { // 对于 NFA 中的每个转移,寻找 Move 集合。 HashSet <NfaState> set = Move(stateSet, i); if (set.Count > 0) { set = EpsilonClosure(set); DfaState newState; if (!dfaStateMap.TryGetValue(set, out newState)) { // 添加新状态. newState = dfa.NewState(); stateMap.Add(newState, set); dfaStateMap.Add(set, newState); stack.Push(newState); // 合并符号索引。 newState.SymbolIndex = set.Where(s => s.SymbolIndex != Constants.None) .Select(s => { if (s.StateType == NfaStateType.TrailingHead) { return(int.MaxValue - s.SymbolIndex); } else { return(s.SymbolIndex); } }).OrderBy(idx => idx).ToArray(); } // 添加 DFA 的转移。 state[i] = newState; } } } return(dfa); }