📄 semanticize.java
字号:
* This code is not executed if Options.B("USER_TOKEN_MANAGER") is set to * true. Instead the following block of code is executed. */ if (!Options.B("USER_TOKEN_MANAGER")) { FixRJustNames frjn = new FixRJustNames(); for (java.util.Enumeration enum = rexprlist.elements(); enum.hasMoreElements();) { TokenProduction tp = (TokenProduction)(enum.nextElement()); java.util.Vector respecs = tp.respecs; for (java.util.Enumeration enum1 = respecs.elements(); enum1.hasMoreElements();) { RegExprSpec res = (RegExprSpec)(enum1.nextElement()); frjn.root = res.rexp; ExpansionTreeWalker.preOrderWalk(res.rexp, frjn); if (res.rexp instanceof RJustName) { prepareToRemove(respecs, res); } } } } removePreparedItems(); /* * The following code is executed only if Options.B("USER_TOKEN_MANAGER") is * set to true. This code visits all top-level "RJustName"s (ignores * "RJustName"s nested within regular expressions). Since regular expressions * are optional in this case, "RJustName"s without corresponding regular * expressions are given ordinal values here. If "RJustName"s refer to * a named regular expression, their ordinal values are set to reflect this. * All but one "RJustName" node is removed from the lists by the end of * execution of this code. */ if (Options.B("USER_TOKEN_MANAGER")) { for (java.util.Enumeration enum = rexprlist.elements(); enum.hasMoreElements();) { TokenProduction tp = (TokenProduction)(enum.nextElement()); java.util.Vector respecs = tp.respecs; for (java.util.Enumeration enum1 = respecs.elements(); enum1.hasMoreElements();) { RegExprSpec res = (RegExprSpec)(enum1.nextElement()); if (res.rexp instanceof RJustName) { RJustName jn = (RJustName)res.rexp; RegularExpression rexp = (RegularExpression)named_tokens_table.get(jn.label); if (rexp == null) { jn.ordinal = tokenCount++; named_tokens_table.put(jn.label, jn); ordered_named_tokens.addElement(jn); names_of_tokens.put(new Integer(jn.ordinal), jn.label); } else { jn.ordinal = rexp.ordinal; prepareToRemove(respecs, res); } } } } } removePreparedItems(); /* * The following code is executed only if Options.B("USER_TOKEN_MANAGER") is * set to true. This loop labels any unlabeled regular expression and * prints a warning that it is doing so. These labels are added to * "ordered_named_tokens" so that they may be generated into the ...Constants * file. */ if (Options.B("USER_TOKEN_MANAGER")) { for (java.util.Enumeration enum = rexprlist.elements(); enum.hasMoreElements();) { TokenProduction tp = (TokenProduction)(enum.nextElement()); java.util.Vector respecs = tp.respecs; for (java.util.Enumeration enum1 = respecs.elements(); enum1.hasMoreElements();) { RegExprSpec res = (RegExprSpec)(enum1.nextElement()); Integer ii = new Integer(res.rexp.ordinal); if (names_of_tokens.get(ii) == null) { JavaCCErrors.warning(res.rexp, "Unlabeled regular expression cannot be referred to by user generated token manager."); } } } } if (JavaCCErrors.get_error_count() != 0) throw new MetaParseException(); // The following code sets the value of the "emptyPossible" field of NormalProduction // nodes. This field is initialized to false, and then the entire list of // productions is processed. This is repeated as long as at least one item // got updated from false to true in the pass. boolean emptyUpdate = true; while (emptyUpdate) { emptyUpdate = false; for (java.util.Enumeration enum = bnfproductions.elements(); enum.hasMoreElements();) { NormalProduction prod = (NormalProduction)enum.nextElement(); if (emptyExpansionExists(prod.expansion)) { if (!prod.emptyPossible) { emptyUpdate = prod.emptyPossible = true; } } } } if (Options.B("SANITY_CHECK") && JavaCCErrors.get_error_count() == 0) { // The following code checks that all ZeroOrMore, ZeroOrOne, and OneOrMore nodes // do not contain expansions that can expand to the empty token list. for (java.util.Enumeration enum = bnfproductions.elements(); enum.hasMoreElements();) { ExpansionTreeWalker.preOrderWalk(((NormalProduction)enum.nextElement()).expansion, new EmptyChecker()); } // The following code goes through the productions and adds pointers to other // productions that it can expand to without consuming any tokens. Once this is // done, a left-recursion check can be performed. for (java.util.Enumeration enum = bnfproductions.elements(); enum.hasMoreElements();) { NormalProduction prod = (NormalProduction)enum.nextElement(); addLeftMost(prod, prod.expansion); } // Now the following loop calls a recursive walk routine that searches for // actual left recursions. The way the algorithm is coded, once a node has // been determined to participate in a left recursive loop, it is not tried // in any other loop. for (java.util.Enumeration enum = bnfproductions.elements(); enum.hasMoreElements();) { NormalProduction prod = (NormalProduction)enum.nextElement(); if (prod.walkStatus == 0) { prodWalk(prod); } } // Now we do a similar, but much simpler walk for the regular expression part of // the grammar. Here we are looking for any kind of loop, not just left recursions, // so we only need to do the equivalent of the above walk. // This is not done if option USER_TOKEN_MANAGER is set to true. if (!Options.B("USER_TOKEN_MANAGER")) { for (java.util.Enumeration enum = rexprlist.elements(); enum.hasMoreElements();) { TokenProduction tp = (TokenProduction)(enum.nextElement()); java.util.Vector respecs = tp.respecs; for (java.util.Enumeration enum1 = respecs.elements(); enum1.hasMoreElements();) { RegExprSpec res = (RegExprSpec)(enum1.nextElement()); RegularExpression rexp = res.rexp; if (rexp.walkStatus == 0) { rexp.walkStatus = -1; if (rexpWalk(rexp)) { loopString = "..." + rexp.label + "... --> " + loopString; JavaCCErrors.semantic_error(rexp, "Loop in regular expression detected: \"" + loopString + "\""); } rexp.walkStatus = 1; } } } } /* * The following code performs the lookahead ambiguity checking. */ if (JavaCCErrors.get_error_count() == 0) { for (java.util.Enumeration enum = bnfproductions.elements(); enum.hasMoreElements();) { ExpansionTreeWalker.preOrderWalk(((NormalProduction)enum.nextElement()).expansion, new LookaheadChecker()); } } } // matches "if (Options.B("SANITY_CHECK")) {" if (JavaCCErrors.get_error_count() != 0) throw new MetaParseException(); } public static RegularExpression other; // Checks to see if the "str" is superceded by another equal (except case) string // in table. public static boolean hasIgnoreCase(java.util.Hashtable table, String str) { RegularExpression rexp; rexp = (RegularExpression)(table.get(str)); if (rexp != null && !rexp.tpContext.ignoreCase) { return false; } for (java.util.Enumeration enum = table.elements(); enum.hasMoreElements();) { rexp = (RegularExpression)(enum.nextElement()); if (rexp.tpContext.ignoreCase) { other = rexp; return true; } } return false; } // returns true if "exp" can expand to the empty string, returns false otherwise. public static boolean emptyExpansionExists(Expansion exp) { if (exp instanceof NonTerminal) { return ((NonTerminal)exp).prod.emptyPossible; } else if (exp instanceof Action) { return true; } else if (exp instanceof RegularExpression) { return false; } else if (exp instanceof OneOrMore) { return emptyExpansionExists(((OneOrMore)exp).expansion); } else if (exp instanceof ZeroOrMore || exp instanceof ZeroOrOne) { return true; } else if (exp instanceof Lookahead) { return true; } else if (exp instanceof Choice) { for (java.util.Enumeration enum = ((Choice)exp).choices.elements(); enum.hasMoreElements();) { if (emptyExpansionExists((Expansion)enum.nextElement())) { return true; } } return false; } else if (exp instanceof Sequence) { for (java.util.Enumeration enum = ((Sequence)exp).units.elements(); enum.hasMoreElements();) { if (!emptyExpansionExists((Expansion)enum.nextElement())) { return false; } } return true; } else if (exp instanceof TryBlock) { return emptyExpansionExists(((TryBlock)exp).exp); } else { return false; // This should be dead code. } } // Updates prod.leftExpansions based on a walk of exp. static private void addLeftMost(NormalProduction prod, Expansion exp) { if (exp instanceof NonTerminal) { for (int i=0; i<prod.leIndex; i++) { if (prod.leftExpansions[i] == ((NonTerminal)exp).prod) { return; } } if (prod.leIndex == prod.leftExpansions.length) { NormalProduction[] newle = new NormalProduction[prod.leIndex*2]; System.arraycopy(prod.leftExpansions, 0, newle, 0, prod.leIndex); prod.leftExpansions = newle; } prod.leftExpansions[prod.leIndex++] = ((NonTerminal)exp).prod; } else if (exp instanceof OneOrMore) { addLeftMost(prod, ((OneOrMore)exp).expansion); } else if (exp instanceof ZeroOrMore) { addLeftMost(prod, ((ZeroOrMore)exp).expansion); } else if (exp instanceof ZeroOrOne) { addLeftMost(prod, ((ZeroOrOne)exp).expansion); } else if (exp instanceof Choice) { for (java.util.Enumeration enum = ((Choice)exp).choices.elements(); enum.hasMoreElements();) { addLeftMost(prod, (Expansion)enum.nextElement()); } } else if (exp instanceof Sequence) { for (java.util.Enumeration enum = ((Sequence)exp).units.elements(); enum.hasMoreElements();) { Expansion e = (Expansion)enum.nextElement(); addLeftMost(prod, e); if (!emptyExpansionExists(e)) { break; } } } else if (exp instanceof TryBlock) { addLeftMost(prod, ((TryBlock)exp).exp); } } // The string in which the following methods store information. static private String loopString; // Returns true to indicate an unraveling of a detected left recursion loop, // and returns false otherwise. static private boolean prodWalk(NormalProduction prod) { prod.walkStatus = -1; for (int i = 0; i < prod.leIndex; i++) { if (prod.leftExpansions[i].walkStatus == -1) { prod.leftExpansions[i].walkStatus = -2; loopString = prod.lhs + "... --> " + prod.leftExpansions[i].lhs + "..."; if (prod.walkStatus == -2) { prod.walkStatus = 1; JavaCCErrors.semantic_error(prod, "Left recursion detected: \"" + loopString + "\""); return false; } else { prod.walkStatus = 1; return true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -