/** * Returns the action with highest priority in the specified * set of states. * * @param set the set of states for which to determine the action */ private Action getAction(StateSet set) { states.reset(set); Action maxAction = null; Out.debug("Determining action of : " + set); while (states.hasMoreElements()) { Action currentAction = action[states.nextElement()]; if (currentAction != null) { if (maxAction == null) { maxAction = currentAction; } else { maxAction = maxAction.getHigherPriority(currentAction); } } } return(maxAction); }
private void increaseSize(int length) { length = Math.Max(length + 1, 4 * p.Length); Out.debug("increasing length to " + length); //$NON-NLS-1$ int[] pn = new int[length]; int[] qn = new int[length]; Array.Copy(p, 0, pn, 0, p.Length); Array.Copy(q, 0, qn, 0, q.Length); p = pn; q = qn; }
public void addRegExp(int regExpNum) { if (Options.DEBUG) { Out.debug("Adding nfa for regexp " + regExpNum + " :" + Out.NL + regExps.getRegExp(regExpNum)); } IntPair nfa = insertNFA(regExps.getRegExp(regExpNum)); IEnumerator lexStates = regExps.getStates(regExpNum).GetEnumerator(); if (!lexStates.MoveNext()) { lexStates = scanner.states.getInclusiveStates(); } lexStates.Reset(); while (lexStates.MoveNext()) { int stateNum = (int)lexStates.Current; if (!regExps.isBOL(regExpNum)) { addEpsilonTransition(2 * stateNum, nfa.start); } addEpsilonTransition(2 * stateNum + 1, nfa.start); } if (regExps.getLookAhead(regExpNum) != null) { IntPair look = insertNFA(regExps.getLookAhead(regExpNum)); addEpsilonTransition(nfa.end, look.start); Action a = regExps.getAction(regExpNum); a.setLookAction(true); isPushback[nfa.end] = true; action[look.end] = a; isFinal[look.end] = true; } else { action[nfa.end] = regExps.getAction(regExpNum); isFinal[nfa.end] = true; } }
/** * Stores a new macro and its definition. * * @param name the name of the new macro * @param definition the definition of the new macro * * @return <code>true</code>, iff the macro name has not been * stored before. */ public bool insert(String name, RegExp definition) { #if DEBUG_TRACE log.WriteLine("insert(String name = \"{0}\", RegExp definition = {1})", name, definition); #endif // DEBUG_TRACE if (Options.DEBUG) { Out.debug("inserting macro " + name + " with definition :" + Out.NL + definition); //$NON-NLS-1$ //$NON-NLS-2$ } used[name] = false; bool new_entry = !macros.ContainsKey(name); macros[name] = definition; return(new_entry); }
public int insert(ArrayList stateList, Action action) { if (Options.DEBUG) { Out.debug("Inserting eofrule with statelist :" + Out.NL + stateList); //$NON-NLS-1$ Out.debug("and action code :" + Out.NL + action.content + Out.NL); //$NON-NLS-1$ } states.Add(stateList); regExps.Add(null); actions.Add(action); BOL.Add(null); look.Add(null); lines.Add(null); return(states.Count - 1); }
public int insert(int line, ArrayList stateList, RegExp regExp, Action action, Boolean isBOL, RegExp lookAhead) { if (Options.DEBUG) { Out.debug("Inserting regular expression with statelist :" + Out.NL + stateList); //$NON-NLS-1$ Out.debug("and action code :" + Out.NL + action.content + Out.NL); //$NON-NLS-1$ Out.debug("expression :" + Out.NL + regExp); //$NON-NLS-1$ } states.Add(stateList); regExps.Add(regExp); actions.Add(action); BOL.Add(isBOL); look.Add(lookAhead); lines.Add(line); return(states.Count - 1); }
public void addTransition(int start, int input, int dest) { Out.debug("Adding transition (" + start + ", " + input + ", " + dest + ")"); int maxS = Math.Max(start, dest) + 1; ensureCapacity(maxS); if (maxS > numStates) { numStates = maxS; } if (table[start][input] != null) { table[start][input].addState(dest); } else { table[start][input] = new StateSet(estSize, dest); } }
public bool [] [] old_minimize() { int i, j; char c; Out.print(numStates + " states before minimization, "); if (numStates == 0) { Out.error(ErrorMessages.ZERO_STATES); throw new GeneratorException(); } if (Options.no_minimize) { Out.println("minimization skipped."); return(null); } // notequiv[i][j] == true <=> state i and state j are equivalent bool [] [] equiv = new bool [numStates] []; // list[i][j] contains all pairs of states that have to be marked "not equivalent" // if states i and j are recognized to be not equivalent StatePairList [] [] list = new StatePairList [numStates] []; // construct a triangular matrix equiv[i][j] with j < i // and mark pairs (final state, not final state) as not equivalent for (i = 1; i < numStates; i++) { list[i] = new StatePairList[i]; equiv[i] = new bool [i]; for (j = 0; j < i; j++) { // i and j are equivalent, iff : // i and j are both final and their actions are equivalent and have same pushback behaviour or // i and j are both not final if (isFinal[i] && isFinal[j] && (isPushback[i] == isPushback[j]) && (isLookEnd[i] == isLookEnd[j])) { equiv[i][j] = action[i].isEquiv(action[j]) && !Options.emit_csharp; // C# #line directives get messed up by merged states } else { equiv[i][j] = !isFinal[j] && !isFinal[i] && (isPushback[i] == isPushback[j]) && (isLookEnd[i] == isLookEnd[j]); } } } for (i = 1; i < numStates; i++) { Out.debug("Testing state " + i); for (j = 0; j < i; j++) { if (equiv[i][j]) { for (c = (char)0; c < numInput; c++) { if (equiv[i][j]) { int p = table[i][c]; int q = table[j][c]; if (p < q) { int t = p; p = q; q = t; } if (p >= 0 || q >= 0) { // Out.debug("Testing input '"+c+"' for ("+i+","+j+")"); // Out.debug("Target states are ("+p+","+q+")"); if (p != q && (p == -1 || q == -1 || !equiv[p][q])) { equiv[i][j] = false; if (list[i][j] != null) { list[i][j].markAll(list, equiv); } } // printTable(equiv); } // if (p >= 0) .. } // if (equiv[i][j] } // for (char c = 0; c < numInput .. // if i and j are still marked equivalent.. if (equiv[i][j]) { // Out.debug("("+i+","+j+") are still marked equivalent"); for (c = (char)0; c < numInput; c++) { int p = table[i][c]; int q = table[j][c]; if (p < q) { int t = p; p = q; q = t; } if (p != q && p >= 0 && q >= 0) { if (list[p][q] == null) { list[p][q] = new StatePairList(); } list[p][q].addPair(i, j); } } } else { // Out.debug("("+i+","+j+") are not equivalent"); } } // of first if (equiv[i][j]) } // of for j } // of for i // } // printTable(equiv); return(equiv); }
/** * Constructs an NFA accepting the complement of the language * of a given NFA. * * Converts the NFA into a DFA, then negates that DFA. * Exponential state blowup possible and common. * * @param the NFA to construct the complement for. * * @return a pair of integers denoting the index of start * and end state of the complement NFA. */ private IntPair complement(IntPair nfa) { if (Options.DEBUG) { Out.debug("complement for " + nfa); Out.debug("NFA is :" + Out.NL + this); } int dfaStart = nfa.end + 1; // fixme: only need epsilon closure of states reachable from nfa.start epsilonFill(); Hashtable dfaStates = new PrettyHashtable(numStates); ArrayList dfaVector = new PrettyArrayList(numStates); int numDFAStates = 0; int currentDFAState = 0; StateSet currentState, newState; newState = epsilon[nfa.start]; dfaStates[newState] = new Integer(numDFAStates); dfaVector.Add(newState); if (Options.DEBUG) { Out.debug("pos DFA start state is :" + Out.NL + dfaStates + Out.NL + Out.NL + "ordered :" + Out.NL + dfaVector); } currentDFAState = 0; while (currentDFAState <= numDFAStates) { currentState = (StateSet)dfaVector[currentDFAState]; for (char input = (char)0; input < numInput; input++) { newState = DFAEdge(currentState, input); if (newState.containsElements()) { // Out.debug("DFAEdge for input "+(int)input+" and state set "+currentState+" is "+newState); // Out.debug("Looking for state set "+newState); Integer nextDFAState = (Integer)dfaStates[newState]; if (nextDFAState != null) { // Out.debug("FOUND!"); addTransition(dfaStart + currentDFAState, input, dfaStart + nextDFAState.intValue()); } else { if (Options.dump) { Out.print("+"); } // Out.debug("NOT FOUND!"); // Out.debug("Table was "+dfaStates); numDFAStates++; dfaStates[newState] = new Integer(numDFAStates); dfaVector.Add(newState); addTransition(dfaStart + currentDFAState, input, dfaStart + numDFAStates); } } } currentDFAState++; } // We have a dfa accepting the positive regexp. // Now the complement: if (Options.DEBUG) { Out.debug("dfa finished, nfa is now :" + Out.NL + this); } int start = dfaStart + numDFAStates + 1; int error = dfaStart + numDFAStates + 2; int end = dfaStart + numDFAStates + 3; addEpsilonTransition(start, dfaStart); for (int i = 0; i < numInput; i++) { addTransition(error, i, error); } addEpsilonTransition(error, end); for (int s = 0; s <= numDFAStates; s++) { currentState = (StateSet)dfaVector[s]; currentDFAState = dfaStart + s; // if it was not a final state, it is now in the complement if (!currentState.isElement(nfa.end)) { addEpsilonTransition(currentDFAState, end); } // all inputs not present (formerly leading to an implicit error) // now lead to an explicit (final) state accepting everything. for (int i = 0; i < numInput; i++) { if (table[currentDFAState][i] == null) { addTransition(currentDFAState, i, error); } } } // eliminate transitions leading to dead states if (live == null || live.Length < numStates) { live = new bool [2 * numStates]; visited = new bool [2 * numStates]; } _end = end; _dfaStates = dfaVector; _dfaStart = dfaStart; removeDead(dfaStart); if (Options.DEBUG) { Out.debug("complement finished, nfa (" + start + "," + end + ") is now :" + this); } return(new IntPair(start, end)); }
/** * Returns an DFA that accepts the same language as this NFA. * This DFA is usualy not minimal. */ public DFA getDFA() { Hashtable dfaStates = new PrettyHashtable(numStates); ArrayList dfaVector = new PrettyArrayList(numStates); DFA dfa = new DFA(2 * numLexStates, numInput); int numDFAStates = 0; int currentDFAState = 0; Out.println("Converting NFA to DFA : "); epsilonFill(); StateSet currentState, newState; for (int i = 0; i < 2 * numLexStates; i++) { newState = epsilon[i]; dfaStates[newState] = new Integer(numDFAStates); dfaVector.Add(newState); dfa.setLexState(i, numDFAStates); dfa.setFinal(numDFAStates, containsFinal(newState)); dfa.setPushback(numDFAStates, containsPushback(newState)); dfa.setAction(numDFAStates, getAction(newState)); numDFAStates++; } numDFAStates--; if (Options.DEBUG) { Out.debug("DFA start states are :" + Out.NL + dfaStates + Out.NL + Out.NL + "ordered :" + Out.NL + dfaVector); } currentDFAState = 0; StateSet tempStateSet = NFA.tempStateSet; StateSetEnumerator states = NFA.states; // will be reused newState = new StateSet(numStates); while (currentDFAState <= numDFAStates) { currentState = (StateSet)dfaVector[currentDFAState]; for (char input = (char)0; input < numInput; input++) { // newState = DFAEdge(currentState, input); // inlining DFAEdge for performance: // Out.debug("Calculating DFAEdge for state set "+currentState+" and input '"+input+"'"); tempStateSet.clear(); states.reset(currentState); while (states.hasMoreElements()) { tempStateSet.add(table[states.nextElement()][input]); } newState.copy(tempStateSet); states.reset(tempStateSet); while (states.hasMoreElements()) { newState.add(epsilon[states.nextElement()]); } // Out.debug("DFAEdge is : "+newState); if (newState.containsElements()) { // Out.debug("DFAEdge for input "+(int)input+" and state set "+currentState+" is "+newState); // Out.debug("Looking for state set "+newState); Integer nextDFAState = (Integer)dfaStates[newState]; if (nextDFAState != null) { // Out.debug("FOUND!"); dfa.addTransition(currentDFAState, input, nextDFAState.intValue()); } else { if (Options.progress) { Out.print("."); } // Out.debug("NOT FOUND!"); // Out.debug("Table was "+dfaStates); numDFAStates++; // make a new copy of newState to store in dfaStates StateSet storeState = new StateSet(newState); dfaStates[storeState] = new Integer(numDFAStates); dfaVector.Add(storeState); dfa.addTransition(currentDFAState, input, numDFAStates); dfa.setFinal(numDFAStates, containsFinal(storeState)); dfa.setPushback(numDFAStates, containsPushback(storeState)); dfa.setAction(numDFAStates, getAction(storeState)); } } } currentDFAState++; } if (Options.verbose) { Out.println(""); } return(dfa); }
/** * Constructs an NFA for regExp such that the NFA has * * exactly one start state, * exactly one end state, * no transitions leading out of the end state * no transitions leading into the start state * * @param regExp the regular expression to construct the * NFA for * * @return a pair of integers denoting the index of start * and end state of the NFA. */ public IntPair insertNFA(RegExp regExp) { IntPair nfa1, nfa2; int start, end; RegExp2 r; if (Options.DEBUG) { Out.debug("Inserting RegExp : " + regExp); } if (regExp.isCharClass(macros)) { start = numStates; end = numStates + 1; ensureCapacity(end + 1); if (end + 1 > numStates) { numStates = end + 1; } insertNFA(regExp, start, end); return(new IntPair(start, end)); } switch (regExp.type) { case sym.BAR: r = (RegExp2)regExp; nfa1 = insertNFA(r.r1); nfa2 = insertNFA(r.r2); start = nfa2.end + 1; end = nfa2.end + 2; addEpsilonTransition(start, nfa1.start); addEpsilonTransition(start, nfa2.start); addEpsilonTransition(nfa1.end, end); addEpsilonTransition(nfa2.end, end); return(new IntPair(start, end)); case sym.CONCAT: r = (RegExp2)regExp; nfa1 = insertNFA(r.r1); nfa2 = insertNFA(r.r2); addEpsilonTransition(nfa1.end, nfa2.start); return(new IntPair(nfa1.start, nfa2.end)); case sym.STAR: nfa1 = insertNFA((RegExp)((RegExp1)regExp).content); start = nfa1.end + 1; end = nfa1.end + 2; addEpsilonTransition(nfa1.end, end); addEpsilonTransition(start, nfa1.start); addEpsilonTransition(start, end); addEpsilonTransition(nfa1.end, nfa1.start); return(new IntPair(start, end)); case sym.PLUS: nfa1 = insertNFA((RegExp)((RegExp1)regExp).content); start = nfa1.end + 1; end = nfa1.end + 2; addEpsilonTransition(nfa1.end, end); addEpsilonTransition(start, nfa1.start); addEpsilonTransition(nfa1.end, nfa1.start); return(new IntPair(start, end)); case sym.QUESTION: nfa1 = insertNFA((RegExp)((RegExp1)regExp).content); addEpsilonTransition(nfa1.start, nfa1.end); return(new IntPair(nfa1.start, nfa1.end)); case sym.BANG: return(complement(insertNFA((RegExp)((RegExp1)regExp).content))); case sym.TILDE: nfa1 = insertNFA((RegExp)((RegExp1)regExp).content); start = nfa1.end + 1; int s1 = start + 1; int s2 = s1 + 1; end = s2 + 1; for (int i = 0; i < numInput; i++) { addTransition(s1, i, s1); addTransition(s2, i, s2); } addEpsilonTransition(start, s1); addEpsilonTransition(s1, nfa1.start); addEpsilonTransition(nfa1.end, s2); addEpsilonTransition(s2, end); nfa1 = complement(new IntPair(start, end)); nfa2 = insertNFA((RegExp)((RegExp1)regExp).content); addEpsilonTransition(nfa1.end, nfa2.start); return(new IntPair(nfa1.start, nfa2.end)); case sym.STRING: return(insertStringNFA(false, (String)((RegExp1)regExp).content)); case sym.STRING_I: return(insertStringNFA(true, (String)((RegExp1)regExp).content)); case sym.MACROUSE: return(insertNFA(macros.getDefinition((String)((RegExp1)regExp).content))); } throw new Exception("Unknown expression type " + regExp.type + " in NFA construction"); }