/* * Copyright © 2002 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * California 95054, U.S.A. All rights reserved. Sun Microsystems, Inc. has * intellectual property rights relating to technology embodied in the product * that is described in this document. In particular, and without limitation, * these intellectual property rights may include one or more of the U.S. * patents listed at http://www.sun.com/patents and one or more additional * patents or pending patent applications in the U.S. and in other countries. * U.S. Government Rights - Commercial software. Government users are subject * to the Sun Microsystems, Inc. standard license agreement and applicable * provisions of the FAR and its supplements. Use is subject to license terms. * Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered * trademarks of Sun Microsystems, Inc. in the U.S. and other countries. This * product is covered and controlled by U.S. Export Control laws and may be * subject to the export or import laws in other countries. Nuclear, missile, * chemical biological weapons or nuclear maritime end uses or end users, * whether direct or indirect, are strictly prohibited. Export or reexport * to countries subject to U.S. embargo or to entities identified on U.S. * export exclusion lists, including, but not limited to, the denied persons * and specially designated nationals lists is strictly prohibited. */ package csjavacc.parser; import java.util.*; import csjavacc.struct.Nfa; import csjavacc.struct.RegularExpression; final class KindInfo { long[] validKinds; long[] finalKinds; int validKindCnt = 0; int finalKindCnt = 0; KindInfo(int maxKind) { validKinds = new long[maxKind / 64 + 1]; finalKinds = new long[maxKind / 64 + 1]; } public void InsertValidKind(int kind) { validKinds[kind / 64] |= (1L << (kind % 64)); validKindCnt++; } public void InsertFinalKind(int kind) { finalKinds[kind / 64] |= (1L << (kind % 64)); finalKindCnt++; } }; /** * Describes string literals. */ public class RStringLiteral extends RegularExpression { /** * The string image of the literal. */ public String image; static int maxStrKind = 0; static int maxLen = 0; static int charCnt = 0; static Vector charPosKind = new Vector(); // Elements are hashtables // with single char keys; static int[] maxLenForActive = new int[100]; // 6400 tokens public static String[] allImages; static int[][] intermediateKinds; static int[][] intermediateMatchedPos; static int startStateCnt = 0; static boolean subString[]; static boolean subStringAtPos[]; static Hashtable[] statesForPos; // Need to call this method after gnerating code for each lexical state. It // initializes all the static variables, so that there is no interference // between the various states of the lexer. public static void ReInit() { maxStrKind = 0; maxLen = 0; charPosKind = new Vector(); maxLenForActive = new int[100]; // 6400 tokens intermediateKinds = null; intermediateMatchedPos = null; startStateCnt = 0; subString = null; subStringAtPos = null; statesForPos = null; } public static void DumpStrLiteralImages(java.io.PrintWriter ostr) { String image; int charCnt = 0, i; ostr.println("public static String[] jjstrLiteralImages = {"); if (allImages == null || allImages.length == 0){ ostr.println("};"); return; } allImages[0] = ""; for (i = 0; i < allImages.length; i++) { if ((image = allImages[i]) == null || ((LexGen.toSkip[i / 64] & (1L << (i % 64))) == 0L && (LexGen.toMore[i / 64] & (1L << (i % 64))) == 0L && (LexGen.toToken[i / 64] & (1L << (i % 64))) == 0L) || (LexGen.toSkip[i / 64] & (1L << (i % 64))) != 0L || (LexGen.toMore[i / 64] & (1L << (i % 64))) != 0L || LexGen.canReachOnMore[LexGen.lexStates[i]] || ((Options.getIgnoreCase() || LexGen.ignoreCase[i]) && (!image.equals(image.toLowerCase()) || !image.equals(image.toUpperCase())))) { allImages[i] = null; if ((charCnt += 6) > 80){ ostr.println(""); charCnt = 0; } ostr.print("null, "); continue; } String toPrint = "\""; for (int j = 0; j < image.length(); j++){ if (image.charAt(j) <= 0xff) // C# (csharp) doesn't allow octal char literals toPrint += ("\\x" + Integer.toHexString((int)image.charAt(j))); else{ String hexVal = Integer.toHexString((int)image.charAt(j)); if (hexVal.length() == 3) hexVal = "0" + hexVal; toPrint += ("\\u" + hexVal); } } toPrint += ( "\", "); if ((charCnt += toPrint.length()) >= 80) { ostr.println(""); charCnt = 0; } ostr.print(toPrint); } while (++i < LexGen.maxOrdinal) { if ((charCnt += 6) > 80) { ostr.println(""); charCnt = 0; } ostr.print("null, "); continue; } ostr.println("};"); } // Used for top level string literals public void GenerateDfa(java.io.PrintWriter ostr, int kind) { String s; Hashtable temp; KindInfo info; int len; if (maxStrKind <= ordinal) maxStrKind = ordinal + 1; if ((len = image.length()) > maxLen) maxLen = len; char c; for (int i = 0; i < len; i++) { if (Options.getIgnoreCase()) s = ("" + (c = image.charAt(i))).toLowerCase(); else s = "" + (c = image.charAt(i)); if (!NfaState.unicodeWarningGiven && c > 0xff && !Options.getCSUnicodeEscape() && !Options.getUserCharStream()) { NfaState.unicodeWarningGiven = true; CSJavaCCErrors.warning(LexGen.curRE, "Non-ASCII characters used in regular expression." + "Please make sure you use the correct Reader when you create the parser that can handle your character set."); } if (i >= charPosKind.size()) // Kludge, but OK charPosKind.addElement(temp = new Hashtable()); else temp = (Hashtable)charPosKind.elementAt(i); if ((info = (KindInfo)temp.get(s)) == null) temp.put(s, info = new KindInfo(LexGen.maxOrdinal)); if (i + 1 == len) info.InsertFinalKind(ordinal); else info.InsertValidKind(ordinal); if (!Options.getIgnoreCase() && LexGen.ignoreCase[ordinal] && c != Character.toLowerCase(c)) { s = ("" + image.charAt(i)).toLowerCase(); if (i >= charPosKind.size()) // Kludge, but OK charPosKind.addElement(temp = new Hashtable()); else temp = (Hashtable)charPosKind.elementAt(i); if ((info = (KindInfo)temp.get(s)) == null) temp.put(s, info = new KindInfo(LexGen.maxOrdinal)); if (i + 1 == len) info.InsertFinalKind(ordinal); else info.InsertValidKind(ordinal); } if (!Options.getIgnoreCase() && LexGen.ignoreCase[ordinal] && c != Character.toUpperCase(c)) { s = ("" + image.charAt(i)).toUpperCase(); if (i >= charPosKind.size()) // Kludge, but OK charPosKind.addElement(temp = new Hashtable()); else temp = (Hashtable)charPosKind.elementAt(i); if ((info = (KindInfo)temp.get(s)) == null) temp.put(s, info = new KindInfo(LexGen.maxOrdinal)); if (i + 1 == len) info.InsertFinalKind(ordinal); else info.InsertValidKind(ordinal); } } maxLenForActive[ordinal / 64] = Math.max(maxLenForActive[ordinal / 64], len -1); allImages[ordinal] = image; } public Nfa GenerateNfa(boolean ignoreCase) { if (image.length() == 1) { RCharacterList temp = new RCharacterList(image.charAt(0)); return temp.GenerateNfa(ignoreCase); } NfaState startState = new NfaState(); NfaState theStartState = startState; NfaState finalState = null; if (image.length() == 0) return new Nfa(theStartState, theStartState); int i; for (i = 0; i < image.length(); i++) { finalState = new NfaState(); startState.charMoves = new char[1]; startState.AddChar(image.charAt(i)); if (Options.getIgnoreCase() || ignoreCase) { startState.AddChar(Character.toLowerCase(image.charAt(i))); startState.AddChar(Character.toUpperCase(image.charAt(i))); } startState.next = finalState; startState = finalState; } return new Nfa(theStartState, finalState); } static void DumpNullStrLiterals(java.io.PrintWriter ostr) { ostr.println("{"); if (NfaState.generatedStates != 0) ostr.println(" return jjMoveNfa" + LexGen.lexStateSuffix + "(" + NfaState.InitStateName() + ", 0);"); else ostr.println(" return 1;"); ostr.println("}"); } private static int GetStateSetForKind(int pos, int kind) { if (LexGen.mixed[LexGen.lexStateIndex] || NfaState.generatedStates == 0) return -1; Hashtable allStateSets = statesForPos[pos]; if (allStateSets == null) return -1; Enumeration e = allStateSets.keys(); while (e.hasMoreElements()) { String s = (String)e.nextElement(); long[] actives = (long[])allStateSets.get(s); s = s.substring(s.indexOf(", ") + 2); s = s.substring(s.indexOf(", ") + 2); if (s.equals("null;")) continue; if (actives != null && (actives[kind / 64] & (1L << (kind % 64))) != 0L) { return NfaState.AddStartStateSet(s); } } return -1; } static String GetLabel(int kind) { RegularExpression re = LexGen.rexprs[kind]; if (re instanceof RStringLiteral) return " \"" + CSJavaCCGlobals.add_escapes(((RStringLiteral)re).image) + "\""; else if (!re.label.equals("")) return " <" + re.label + ">"; else return " "; } static int GetLine(int kind) { return LexGen.rexprs[kind].line; } static int GetColumn(int kind) { return LexGen.rexprs[kind].column; } /** * Returns true if s1 starts with s2 (ignoring case for each character). */ static private boolean StartsWithIgnoreCase(String s1, String s2) { if (s1.length() < s2.length()) return false; for (int i = 0; i < s2.length(); i++) { char c1 = s1.charAt(i), c2 = s2.charAt(i); if (c1 != c2 && Character.toLowerCase(c2) != c1 && Character.toUpperCase(c2) != c1) return false; } return true; } static void FillSubString() { String image; subString = new boolean[maxStrKind + 1]; subStringAtPos = new boolean[maxLen]; for (int i = 0; i < maxStrKind; i++) { subString[i] = false; if ((image = allImages[i]) == null || LexGen.lexStates[i] != LexGen.lexStateIndex) continue; if (LexGen.mixed[LexGen.lexStateIndex]) { // We will not optimize for mixed case subString[i] = true; subStringAtPos[image.length() - 1] = true; continue; } for (int j = 0; j < maxStrKind; j++) { if (j != i && LexGen.lexStates[j] == LexGen.lexStateIndex && ((String)allImages[j]) != null) { if (((String)allImages[j]).indexOf(image) == 0) { subString[i] = true; subStringAtPos[image.length() - 1] = true; break; } else if (Options.getIgnoreCase() && StartsWithIgnoreCase((String)allImages[j], image)) { subString[i] = true; subStringAtPos[image.length() - 1] = true; break; } } } } } static void DumpStartWithStates(java.io.PrintWriter ostr) { ostr.println((Options.getStatic() ? "static " : "") + "private int " + "jjStartNfaWithStates" + LexGen.lexStateSuffix + "(int pos, int kind, int state)"); ostr.println("{"); ostr.println(" jjmatchedKind = kind;"); ostr.println(" jjmatchedPos = pos;"); if (Options.getDebugTokenManager()) { ostr.println(" debugStream.WriteLine(\" No more string literal token matches are possible.\");"); ostr.println(" debugStream.WriteLine(\" Currently matched the first \" + (jjmatchedPos + 1) + \" characters as a \" + tokenImage[jjmatchedKind] + \" token.\");"); } ostr.println(" try { curChar = input_stream.readChar(); }"); ostr.println(" catch(System.IO.IOException e) { return pos + 1; }"); if (Options.getDebugTokenManager()) ostr.println(" debugStream.WriteLine(" + (LexGen.maxLexStates > 1 ? "\"<\" + lexStateNames[curLexState] + \">\" + " : "") + "\"Current character : \" + " + "TokenMgrError.addEscapes(\"\"+(curChar)) + \" (\" + (int)curChar + \") at line \" + input_stream.getLine() + \" column \" + input_stream.getColumn());"); ostr.println(" return jjMoveNfa" + LexGen.lexStateSuffix + "(state, pos + 1);"); ostr.println("}"); } private static boolean boilerPlateDumped = false; static void DumpBoilerPlate(java.io.PrintWriter ostr) { ostr.println((Options.getStatic() ? "static " : "") + "private int " + "jjStopAtPos(int pos, int kind)"); ostr.println("{"); ostr.println(" jjmatchedKind = kind;"); ostr.println(" jjmatchedPos = pos;"); if (Options.getDebugTokenManager()) { ostr.println(" debugStream.WriteLine(\" No more string literal token matches are possible.\");"); ostr.println(" debugStream.WriteLine(\" Currently matched the first \" + (jjmatchedPos + 1) + \" characters as a \" + tokenImage[jjmatchedKind] + \" token.\");"); } ostr.println(" return pos + 1;"); ostr.println("}"); } static String[] ReArrange(Hashtable tab) { String[] ret = new String[tab.size()]; Enumeration e = tab.keys(); int cnt = 0; while (e.hasMoreElements()) { int i = 0, j; String s; char c = (s = (String)e.nextElement()).charAt(0); while (i < cnt && ret[i].charAt(0) < c) i++; if (i < cnt) for (j = cnt - 1; j >= i; j--) ret[j + 1] = ret[j]; ret[i] = s; cnt++; } return ret; } static void DumpDfaCode(java.io.PrintWriter ostr) { Hashtable tab; String key; KindInfo info; int maxLongsReqd = maxStrKind / 64 + 1; int i, j, k; boolean ifGenerated; LexGen.maxLongsReqd[LexGen.lexStateIndex] = maxLongsReqd; if (maxLen == 0) { ostr.println((Options.getStatic() ? "static " : "") + "private int " + "jjMoveStringLiteralDfa0" + LexGen.lexStateSuffix + "()"); DumpNullStrLiterals(ostr); return; } if (!boilerPlateDumped) { DumpBoilerPlate(ostr); boilerPlateDumped = true; } if (!LexGen.mixed[LexGen.lexStateIndex] && NfaState.generatedStates != 0) DumpStartWithStates(ostr); boolean startNfaNeeded; for (i = 0; i < maxLen; i++) { boolean atLeastOne = false; startNfaNeeded = false; tab = (Hashtable)charPosKind.elementAt(i); String[] keys = ReArrange(tab); ostr.print((Options.getStatic() ? "static " : "") + "private int " + "jjMoveStringLiteralDfa" + i + LexGen.lexStateSuffix + "("); if (i != 0) { if (i == 1) { for (j = 0; j < maxLongsReqd - 1; j++) if (i <= maxLenForActive[j]) { if (atLeastOne) ostr.print(", "); else atLeastOne = true; ostr.print("long active" + j); } if (i <= maxLenForActive[j]) { if (atLeastOne) ostr.print(", "); ostr.print("long active" + j); } } else { for (j = 0; j < maxLongsReqd - 1; j++) if (i <= maxLenForActive[j] + 1) { if (atLeastOne) ostr.print(", "); else atLeastOne = true; ostr.print("long old" + j + ", long active" + j); } if (i <= maxLenForActive[j] + 1) { if (atLeastOne) ostr.print(", "); ostr.print("long old" + j + ", long active" + j); } } } ostr.println(")"); ostr.println("{"); if (i != 0) { if (i > 1) { atLeastOne = false; ostr.print(" if (("); for (j = 0; j < maxLongsReqd - 1; j++) if (i <= maxLenForActive[j] + 1) { if (atLeastOne) ostr.print(" | "); else atLeastOne = true; ostr.print("(active" + j + " &= old" + j + ")"); } if (i <= maxLenForActive[j] + 1) { if (atLeastOne) ostr.print(" | "); ostr.print("(active" + j + " &= old" + j + ")"); } ostr.println(") == 0L)"); if (!LexGen.mixed[LexGen.lexStateIndex] && NfaState.generatedStates != 0) { ostr.print(" return jjStartNfa" + LexGen.lexStateSuffix + "(" + (i - 2) + ", "); for (j = 0; j < maxLongsReqd - 1; j++) if (i <= maxLenForActive[j] + 1) ostr.print("old" + j + ", "); else ostr.print("0L, "); if (i <= maxLenForActive[j] + 1) ostr.println("old" + j + "); "); else ostr.println("0L);"); } else if (NfaState.generatedStates != 0) ostr.println(" return jjMoveNfa" + LexGen.lexStateSuffix + "(" + NfaState.InitStateName() + ", " + (i - 1) + ");"); else ostr.println(" return " + i + ";"); } if (i != 0 && Options.getDebugTokenManager()) { ostr.println(" if (jjmatchedKind != 0 && jjmatchedKind != 0x" + Integer.toHexString(Integer.MAX_VALUE) + ")"); ostr.println(" debugStream.WriteLine(\" Currently matched the first \" + (jjmatchedPos + 1) + \" characters as a \" + tokenImage[jjmatchedKind] + \" token.\");"); ostr.println(" debugStream.WriteLine(\" Possible string literal matches : { \""); for (int vecs = 0; vecs < maxStrKind / 64 + 1; vecs++) { if (i <= maxLenForActive[vecs]) { ostr.println(" + "); ostr.print(" jjKindsForBitVector(" + vecs + ", "); ostr.print("active" + vecs + ") "); } } ostr.println(" + \" } \");"); } ostr.println(" try { curChar = input_stream.readChar(); }"); ostr.println(" catch(System.IO.IOException e) {"); if (!LexGen.mixed[LexGen.lexStateIndex] && NfaState.generatedStates != 0) { ostr.print(" jjStopStringLiteralDfa" + LexGen.lexStateSuffix + "(" + (i - 1) + ", "); for (k = 0; k < maxLongsReqd - 1; k++) if (i <= maxLenForActive[k]) ostr.print("active" + k + ", "); else ostr.print("0L, "); if (i <= maxLenForActive[k]) ostr.println("active" + k + ");"); else ostr.println("0L);"); if (i != 0 && Options.getDebugTokenManager()) { ostr.println(" if (jjmatchedKind != 0 && jjmatchedKind != 0x" + Integer.toHexString(Integer.MAX_VALUE) + ")"); ostr.println(" debugStream.WriteLine(\" Currently matched the first \" + (jjmatchedPos + 1) + \" characters as a \" + tokenImage[jjmatchedKind] + \" token.\");"); } ostr.println(" return " + i + ";"); } else if (NfaState.generatedStates != 0) ostr.println(" return jjMoveNfa" + LexGen.lexStateSuffix + "(" + NfaState.InitStateName() + ", " + (i - 1) + ");"); else ostr.println(" return " + i + ";"); ostr.println(" }"); } if (i != 0 && Options.getDebugTokenManager()) ostr.println(" debugStream.WriteLine(" + (LexGen.maxLexStates > 1 ? "\"<\" + lexStateNames[curLexState] + \">\" + " : "") + "\"Current character : \" + " + "TokenMgrError.addEscapes(\"\"+(curChar)) + \" (\" + (int)curChar + \") at line \" + input_stream.getLine() + \" column \" + input_stream.getColumn());"); ostr.println(" switch((int)curChar)"); ostr.println(" {"); CaseLoop: for (int q = 0; q < keys.length; q++) { key = keys[q]; info = (KindInfo)tab.get(key); ifGenerated = false; char c = key.charAt(0); if (i == 0 && c < 128 && info.finalKindCnt != 0 && (NfaState.generatedStates == 0 || !NfaState.CanStartNfaUsingAscii(c))) { int kind; Outer: for (j = 0; j < maxLongsReqd; j++) if (info.finalKinds[j] != 0L) break; for (k = 0; k < 64; k++) if ((info.finalKinds[j] & (1L << k)) != 0L && !subString[kind = (j * 64 + k)]) { if ((intermediateKinds != null && intermediateKinds[(j * 64 + k)] != null && intermediateKinds[(j * 64 + k)][i] < (j * 64 + k) && intermediateMatchedPos != null && intermediateMatchedPos[(j * 64 + k)][i] == i) || (LexGen.canMatchAnyChar[LexGen.lexStateIndex] >= 0 && LexGen.canMatchAnyChar[LexGen.lexStateIndex] < (j * 64 + k))) break; else if ((LexGen.toSkip[kind / 64] & (1L << (kind % 64))) != 0L && (LexGen.toSpecial[kind / 64] & (1L << (kind % 64))) == 0L && LexGen.actions[kind] == null && LexGen.newLexState[kind] == null) { LexGen.AddCharToSkip(c, kind); if (Options.getIgnoreCase()) { if (c != Character.toUpperCase(c)) LexGen.AddCharToSkip(Character.toUpperCase(c), kind); if (c != Character.toLowerCase(c)) LexGen.AddCharToSkip(Character.toLowerCase(c), kind); } continue CaseLoop; } } } // Since we know key is a single character ... if (Options.getIgnoreCase()) { if (c != Character.toUpperCase(c)) ostr.println(" case " + (int)Character.toUpperCase(c) + ":"); if (c != Character.toLowerCase(c)) ostr.println(" case " + (int)Character.toLowerCase(c) + ":"); } ostr.println(" case " + (int)c + ":"); long matchedKind; String prefix = (i == 0) ? " " : " "; if (info.finalKindCnt != 0) { for (j = 0; j < maxLongsReqd; j++) { if ((matchedKind = info.finalKinds[j]) == 0L) continue; for (k = 0; k < 64; k++) { if ((matchedKind & (1L << k)) == 0L) continue; if (ifGenerated) { ostr.print(" else if "); } else if (i != 0) ostr.print(" if "); ifGenerated = true; int kindToPrint; if (i != 0) { ostr.println("((active" + j + " & 0x" + Long.toHexString(1L << k) + "L) != 0L)"); } if (intermediateKinds != null && intermediateKinds[(j * 64 + k)] != null && intermediateKinds[(j * 64 + k)][i] < (j * 64 + k) && intermediateMatchedPos != null && intermediateMatchedPos[(j * 64 + k)][i] == i) { CSJavaCCErrors.warning(" \"" + CSJavaCCGlobals.add_escapes(allImages[j * 64 + k]) + "\" cannot be matched as a string literal token " + "at line " + GetLine(j * 64 + k) + ", column " + GetColumn(j * 64 + k) + ". It will be matched as " + GetLabel(intermediateKinds[(j * 64 + k)][i]) + "."); kindToPrint = intermediateKinds[(j * 64 + k)][i]; } else if (i == 0 && LexGen.canMatchAnyChar[LexGen.lexStateIndex] >= 0 && LexGen.canMatchAnyChar[LexGen.lexStateIndex] < (j * 64 + k)) { CSJavaCCErrors.warning(" \"" + CSJavaCCGlobals.add_escapes(allImages[j * 64 + k]) + "\" cannot be matched as a string literal token " + "at line " + GetLine(j * 64 + k) + ", column " + GetColumn(j * 64 + k) + ". It will be matched as " + GetLabel(LexGen.canMatchAnyChar[LexGen.lexStateIndex]) + "."); kindToPrint = LexGen.canMatchAnyChar[LexGen.lexStateIndex]; } else kindToPrint = j * 64 + k; if (!subString[(j * 64 + k)]) { int stateSetName = GetStateSetForKind(i, j * 64 + k); if (stateSetName != -1) { ostr.println(prefix + "return jjStartNfaWithStates" + LexGen.lexStateSuffix + "(" + i + ", " + kindToPrint + ", " + stateSetName + ");"); } else ostr.println(prefix + "return jjStopAtPos" + "(" + i + ", " + kindToPrint + ");"); } else { if ((LexGen.initMatch[LexGen.lexStateIndex] != 0 && LexGen.initMatch[LexGen.lexStateIndex] != Integer.MAX_VALUE) || i != 0) { ostr.println(" {"); ostr.println(prefix + "jjmatchedKind = " + kindToPrint + ";"); ostr.println(prefix + "jjmatchedPos = " + i + ";"); ostr.println(" }"); } else ostr.println(prefix + "jjmatchedKind = " + kindToPrint + ";"); } } } } if (info.validKindCnt != 0) { atLeastOne = false; if (i == 0) { ostr.print(" return "); ostr.print("jjMoveStringLiteralDfa" + (i + 1) + LexGen.lexStateSuffix + "("); for (j = 0; j < maxLongsReqd - 1; j++) if ((i + 1) <= maxLenForActive[j]) { if (atLeastOne) ostr.print(", "); else atLeastOne = true; ostr.print("0x" + Long.toHexString(info.validKinds[j]) + "L"); } if ((i + 1) <= maxLenForActive[j]) { if (atLeastOne) ostr.print(", "); ostr.print("0x" + Long.toHexString(info.validKinds[j]) + "L"); } ostr.println(");"); } else { ostr.print(" return "); ostr.print("jjMoveStringLiteralDfa" + (i + 1) + LexGen.lexStateSuffix + "("); for (j = 0; j < maxLongsReqd - 1; j++) if ((i + 1) <= maxLenForActive[j] + 1) { if (atLeastOne) ostr.print(", "); else atLeastOne = true; if (info.validKinds[j] != 0L) ostr.print("active" + j + ", 0x" + Long.toHexString(info.validKinds[j]) + "L"); else ostr.print("active" + j + ", 0L"); } if ((i + 1) <= maxLenForActive[j] + 1) { if (atLeastOne) ostr.print(", "); if (info.validKinds[j] != 0L) ostr.print("active" + j + ", 0x" + Long.toHexString(info.validKinds[j]) + "L"); else ostr.print("active" + j + ", 0L"); } ostr.println(");"); } } else { // A very special case. if (i == 0 && LexGen.mixed[LexGen.lexStateIndex]) { if (NfaState.generatedStates != 0) ostr.println(" return jjMoveNfa" + LexGen.lexStateSuffix + "(" + NfaState.InitStateName() + ", 0);"); else ostr.println(" return 1;"); } else if (i != 0) // No more str literals to look for { ostr.println(" break;"); startNfaNeeded = true; } } } /* default means that the current character is not in any of the strings at this position. */ ostr.println(" default :"); if (Options.getDebugTokenManager()) ostr.println(" debugStream.WriteLine(\" No string literal matches possible.\");"); if (NfaState.generatedStates != 0) { if (i == 0) { /* This means no string literal is possible. Just move nfa with this guy and return. */ ostr.println(" return jjMoveNfa" + LexGen.lexStateSuffix + "(" + NfaState.InitStateName() + ", 0);"); } else { ostr.println(" break;"); startNfaNeeded = true; } } else { ostr.println(" return " + (i + 1) + ";"); } ostr.println(" }"); if (i != 0) { if (startNfaNeeded) { if (!LexGen.mixed[LexGen.lexStateIndex] && NfaState.generatedStates != 0) { /* Here, a string literal is successfully matched and no more string literals are possible. So set the kind and state set upto and including this position for the matched string. */ ostr.print(" return jjStartNfa" + LexGen.lexStateSuffix + "(" + (i - 1) + ", "); for (k = 0; k < maxLongsReqd - 1; k++) if (i <= maxLenForActive[k]) ostr.print("active" + k + ", "); else ostr.print("0L, "); if (i <= maxLenForActive[k]) ostr.println("active" + k + ");"); else ostr.println("0L);"); } else if (NfaState.generatedStates != 0) ostr.println(" return jjMoveNfa" + LexGen.lexStateSuffix + "(" + NfaState.InitStateName() + ", " + i + ");"); else ostr.println(" return " + (i + 1) + ";"); } } ostr.println("}"); } } static final int GetStrKind(String str) { for (int i = 0; i < maxStrKind; i++) { if (LexGen.lexStates[i] != LexGen.lexStateIndex) continue; String image = allImages[i]; if (image != null && image.equals(str)) return i; } return Integer.MAX_VALUE; } static void GenerateNfaStartStates(java.io.PrintWriter ostr, NfaState initialState) { boolean[] seen = new boolean[NfaState.generatedStates]; Hashtable stateSets = new Hashtable(); String stateSetString = ""; int i, j, kind, jjmatchedPos = 0; int maxKindsReqd = maxStrKind / 64 + 1; long[] actives; Vector newStates = new Vector(); Vector oldStates = null, jjtmpStates; statesForPos = new Hashtable[maxLen]; intermediateKinds = new int[maxStrKind + 1][]; intermediateMatchedPos = new int[maxStrKind + 1][]; for (i = 0; i < maxStrKind; i++) { if (LexGen.lexStates[i] != LexGen.lexStateIndex) continue; String image = allImages[i]; if (image == null || image.length() < 1) continue; try { if ((oldStates = (Vector)initialState.epsilonMoves.clone()) == null || oldStates.size() == 0) { DumpNfaStartStatesCode(statesForPos, ostr); return; } } catch(Exception e) { CSJavaCCErrors.semantic_error("Error cloning state vector"); } intermediateKinds[i] = new int[image.length()]; intermediateMatchedPos[i] = new int[image.length()]; jjmatchedPos = 0; kind = Integer.MAX_VALUE; for (j = 0; j < image.length(); j++) { if (oldStates == null || oldStates.size() <= 0) { // Here, j > 0 kind = intermediateKinds[i][j] = intermediateKinds[i][j - 1]; jjmatchedPos = intermediateMatchedPos[i][j] = intermediateMatchedPos[i][j - 1]; } else { kind = NfaState.MoveFromSet(image.charAt(j), oldStates, newStates); oldStates.removeAllElements(); if (j == 0 && kind != Integer.MAX_VALUE && LexGen.canMatchAnyChar[LexGen.lexStateIndex] != -1 && kind > LexGen.canMatchAnyChar[LexGen.lexStateIndex]) kind = LexGen.canMatchAnyChar[LexGen.lexStateIndex]; if (GetStrKind(image.substring(0, j + 1)) < kind) { intermediateKinds[i][j] = kind = Integer.MAX_VALUE; jjmatchedPos = 0; } else if (kind != Integer.MAX_VALUE) { intermediateKinds[i][j] = kind; jjmatchedPos = intermediateMatchedPos[i][j] = j; } else if (j == 0) kind = intermediateKinds[i][j] = Integer.MAX_VALUE; else { kind = intermediateKinds[i][j] = intermediateKinds[i][j - 1]; jjmatchedPos = intermediateMatchedPos[i][j] = intermediateMatchedPos[i][j - 1]; } stateSetString = NfaState.GetStateSetString(newStates); } if (kind == Integer.MAX_VALUE && (newStates == null || newStates.size() == 0)) continue; int p; if (stateSets.get(stateSetString) == null) { stateSets.put(stateSetString, stateSetString); for (p = 0; p < newStates.size(); p++) { if (seen[((NfaState)newStates.elementAt(p)).stateName]) ((NfaState)newStates.elementAt(p)).inNextOf++; else seen[((NfaState)newStates.elementAt(p)).stateName] = true; } } else { for (p = 0; p < newStates.size(); p++) seen[((NfaState)newStates.elementAt(p)).stateName] = true; } jjtmpStates = oldStates; oldStates = newStates; (newStates = jjtmpStates).removeAllElements(); if (statesForPos[j] == null) statesForPos[j] = new Hashtable(); if ((actives = ((long[])statesForPos[j].get(kind + ", " + jjmatchedPos + ", " + stateSetString))) == null) { actives = new long[maxKindsReqd]; statesForPos[j].put(kind + ", " + jjmatchedPos + ", " + stateSetString, actives); } actives[i / 64] |= 1L << (i % 64); //String name = NfaState.StoreStateSet(stateSetString); } } DumpNfaStartStatesCode(statesForPos, ostr); } static void DumpNfaStartStatesCode(Hashtable[] statesForPos, java.io.PrintWriter ostr) { if (maxStrKind == 0) { // No need to generate this function return; } int i, maxKindsReqd = maxStrKind / 64 + 1; boolean condGenerated = false; int ind = 0; ostr.print("private" + (Options.getStatic() ? " static" : "") + " int jjStopStringLiteralDfa" + LexGen.lexStateSuffix + "(int pos, "); for (i = 0; i < maxKindsReqd - 1; i++) ostr.print("long active" + i + ", "); ostr.println("long active" + i + ")\n{"); if (Options.getDebugTokenManager()) ostr.println(" debugStream.WriteLine(\" No more string literal token matches are possible.\");"); ostr.println(" switch (pos)\n {"); for (i = 0; i < maxLen - 1; i++) { if (statesForPos[i] == null) continue; ostr.println(" case " + i + ":"); Enumeration e = statesForPos[i].keys(); while (e.hasMoreElements()) { String stateSetString = (String)e.nextElement(); long[] actives = (long[])statesForPos[i].get(stateSetString); for (int j = 0; j < maxKindsReqd; j++) { if (actives[j] == 0L) continue; if (condGenerated) ostr.print(" || "); else ostr.print(" if ("); condGenerated = true; ostr.print("(active" + j + " & unchecked((long)0x" + Long.toHexString(actives[j]) + "L)) != 0L"); } if (condGenerated) { ostr.println(")"); String kindStr = stateSetString.substring(0, ind = stateSetString.indexOf(", ")); String afterKind = stateSetString.substring(ind + 2); int jjmatchedPos = Integer.parseInt( afterKind.substring(0, afterKind.indexOf(", "))); if (!kindStr.equals(String.valueOf(Integer.MAX_VALUE))) ostr.println(" {"); if (!kindStr.equals(String.valueOf(Integer.MAX_VALUE))) { if (i == 0) { ostr.println(" jjmatchedKind = " + kindStr + ";"); if ((LexGen.initMatch[LexGen.lexStateIndex] != 0 && LexGen.initMatch[LexGen.lexStateIndex] != Integer.MAX_VALUE)) ostr.println(" jjmatchedPos = 0;"); } else if (i == jjmatchedPos) { if (subStringAtPos[i]) { ostr.println(" if (jjmatchedPos != " + i + ")"); ostr.println(" {"); ostr.println(" jjmatchedKind = " + kindStr + ";"); ostr.println(" jjmatchedPos = " + i + ";"); ostr.println(" }"); } else { ostr.println(" jjmatchedKind = " + kindStr + ";"); ostr.println(" jjmatchedPos = " + i + ";"); } } else { if (jjmatchedPos > 0) ostr.println(" if (jjmatchedPos < " + jjmatchedPos + ")"); else ostr.println(" if (jjmatchedPos == 0)"); ostr.println(" {"); ostr.println(" jjmatchedKind = " + kindStr + ";"); ostr.println(" jjmatchedPos = " + jjmatchedPos + ";"); ostr.println(" }"); } } kindStr = stateSetString.substring(0, ind = stateSetString.indexOf(", ")); afterKind = stateSetString.substring(ind + 2); stateSetString = afterKind.substring( afterKind.indexOf(", ") + 2); if (stateSetString.equals("null;")) ostr.println(" return -1;"); else ostr.println(" return " + NfaState.AddStartStateSet(stateSetString) + ";"); if (!kindStr.equals(String.valueOf(Integer.MAX_VALUE))) ostr.println(" }"); condGenerated = false; } } ostr.println(" return -1;"); } ostr.println(" default :"); ostr.println(" return -1;"); ostr.println(" }"); ostr.println("}"); ostr.print("private" + (Options.getStatic() ? " static" : "") + " int jjStartNfa" + LexGen.lexStateSuffix + "(int pos, "); for (i = 0; i < maxKindsReqd - 1; i++) ostr.print("long active" + i + ", "); ostr.println("long active" + i + ")\n{"); if (LexGen.mixed[LexGen.lexStateIndex]) { if (NfaState.generatedStates != 0) ostr.println(" return jjMoveNfa" + LexGen.lexStateSuffix + "(" + NfaState.InitStateName() + ", pos + 1);"); else ostr.println(" return pos + 1;"); ostr.println("}"); return; } ostr.print(" return jjMoveNfa" + LexGen.lexStateSuffix + "(" + "jjStopStringLiteralDfa" + LexGen.lexStateSuffix + "(pos, "); for (i = 0; i < maxKindsReqd - 1; i++) ostr.print("active" + i + ", "); ostr.print("active" + i + ")"); ostr.println(", pos + 1);"); ostr.println("}"); } public static void reInit() { maxStrKind = 0; maxLen = 0; charCnt = 0; charPosKind = new Vector(); maxLenForActive = new int[100]; allImages = null; intermediateKinds = null; intermediateMatchedPos = null; startStateCnt = 0; subString = null; subStringAtPos = null; statesForPos = null; boilerPlateDumped = false; } }