diff options
4 files changed, 0 insertions, 4884 deletions
diff --git a/infrastructure/yuicompressor/src/yuicompressor/org/mozilla/javascript/Decompiler.java.orig b/infrastructure/yuicompressor/src/yuicompressor/org/mozilla/javascript/Decompiler.java.orig deleted file mode 100644 index cdb00b7..0000000 --- a/infrastructure/yuicompressor/src/yuicompressor/org/mozilla/javascript/Decompiler.java.orig +++ /dev/null @@ -1,910 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Mike Ang - * Igor Bukanov - * Bob Jervis - * Mike McCabe - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * The following class save decompilation information about the source. - * Source information is returned from the parser as a String - * associated with function nodes and with the toplevel script. When - * saved in the constant pool of a class, this string will be UTF-8 - * encoded, and token values will occupy a single byte. - - * Source is saved (mostly) as token numbers. The tokens saved pretty - * much correspond to the token stream of a 'canonical' representation - * of the input program, as directed by the parser. (There were a few - * cases where tokens could have been left out where decompiler could - * easily reconstruct them, but I left them in for clarity). (I also - * looked adding source collection to TokenStream instead, where I - * could have limited the changes to a few lines in getToken... but - * this wouldn't have saved any space in the resulting source - * representation, and would have meant that I'd have to duplicate - * parser logic in the decompiler to disambiguate situations where - * newlines are important.) The function decompile expands the - * tokens back into their string representations, using simple - * lookahead to correct spacing and indentation. - * - * Assignments are saved as two-token pairs (Token.ASSIGN, op). Number tokens - * are stored inline, as a NUMBER token, a character representing the type, and - * either 1 or 4 characters representing the bit-encoding of the number. String - * types NAME, STRING and OBJECT are currently stored as a token type, - * followed by a character giving the length of the string (assumed to - * be less than 2^16), followed by the characters of the string - * inlined into the source string. Changing this to some reference to - * to the string in the compiled class' constant pool would probably - * save a lot of space... but would require some method of deriving - * the final constant pool entry from information available at parse - * time. - */ -public class Decompiler -{ - /** - * Flag to indicate that the decompilation should omit the - * function header and trailing brace. - */ - public static final int ONLY_BODY_FLAG = 1 << 0; - - /** - * Flag to indicate that the decompilation generates toSource result. - */ - public static final int TO_SOURCE_FLAG = 1 << 1; - - /** - * Decompilation property to specify initial ident value. - */ - public static final int INITIAL_INDENT_PROP = 1; - - /** - * Decompilation property to specify default identation offset. - */ - public static final int INDENT_GAP_PROP = 2; - - /** - * Decompilation property to specify identation offset for case labels. - */ - public static final int CASE_GAP_PROP = 3; - - // Marker to denote the last RC of function so it can be distinguished from - // the last RC of object literals in case of function expressions - private static final int FUNCTION_END = Token.LAST_TOKEN + 1; - - String getEncodedSource() - { - return sourceToString(0); - } - - int getCurrentOffset() - { - return sourceTop; - } - - int markFunctionStart(int functionType) - { - int savedOffset = getCurrentOffset(); - addToken(Token.FUNCTION); - append((char)functionType); - return savedOffset; - } - - int markFunctionEnd(int functionStart) - { - int offset = getCurrentOffset(); - append((char)FUNCTION_END); - return offset; - } - - void addToken(int token) - { - if (!(0 <= token && token <= Token.LAST_TOKEN)) - throw new IllegalArgumentException(); - - append((char)token); - } - - void addEOL(int token) - { - if (!(0 <= token && token <= Token.LAST_TOKEN)) - throw new IllegalArgumentException(); - - append((char)token); - append((char)Token.EOL); - } - - void addName(String str) - { - addToken(Token.NAME); - appendString(str); - } - - void addString(String str) - { - addToken(Token.STRING); - appendString(str); - } - - void addRegexp(String regexp, String flags) - { - addToken(Token.REGEXP); - appendString('/' + regexp + '/' + flags); - } - - void addNumber(double n) - { - addToken(Token.NUMBER); - - /* encode the number in the source stream. - * Save as NUMBER type (char | char char char char) - * where type is - * 'D' - double, 'S' - short, 'J' - long. - - * We need to retain float vs. integer type info to keep the - * behavior of liveconnect type-guessing the same after - * decompilation. (Liveconnect tries to present 1.0 to Java - * as a float/double) - * OPT: This is no longer true. We could compress the format. - - * This may not be the most space-efficient encoding; - * the chars created below may take up to 3 bytes in - * constant pool UTF-8 encoding, so a Double could take - * up to 12 bytes. - */ - - long lbits = (long)n; - if (lbits != n) { - // if it's floating point, save as a Double bit pattern. - // (12/15/97 our scanner only returns Double for f.p.) - lbits = Double.doubleToLongBits(n); - append('D'); - append((char)(lbits >> 48)); - append((char)(lbits >> 32)); - append((char)(lbits >> 16)); - append((char)lbits); - } - else { - // we can ignore negative values, bc they're already prefixed - // by NEG - if (lbits < 0) Kit.codeBug(); - - // will it fit in a char? - // this gives a short encoding for integer values up to 2^16. - if (lbits <= Character.MAX_VALUE) { - append('S'); - append((char)lbits); - } - else { // Integral, but won't fit in a char. Store as a long. - append('J'); - append((char)(lbits >> 48)); - append((char)(lbits >> 32)); - append((char)(lbits >> 16)); - append((char)lbits); - } - } - } - - private void appendString(String str) - { - int L = str.length(); - int lengthEncodingSize = 1; - if (L >= 0x8000) { - lengthEncodingSize = 2; - } - int nextTop = sourceTop + lengthEncodingSize + L; - if (nextTop > sourceBuffer.length) { - increaseSourceCapacity(nextTop); - } - if (L >= 0x8000) { - // Use 2 chars to encode strings exceeding 32K, were the highest - // bit in the first char indicates presence of the next byte - sourceBuffer[sourceTop] = (char)(0x8000 | (L >>> 16)); - ++sourceTop; - } - sourceBuffer[sourceTop] = (char)L; - ++sourceTop; - str.getChars(0, L, sourceBuffer, sourceTop); - sourceTop = nextTop; - } - - private void append(char c) - { - if (sourceTop == sourceBuffer.length) { - increaseSourceCapacity(sourceTop + 1); - } - sourceBuffer[sourceTop] = c; - ++sourceTop; - } - - private void increaseSourceCapacity(int minimalCapacity) - { - // Call this only when capacity increase is must - if (minimalCapacity <= sourceBuffer.length) Kit.codeBug(); - int newCapacity = sourceBuffer.length * 2; - if (newCapacity < minimalCapacity) { - newCapacity = minimalCapacity; - } - char[] tmp = new char[newCapacity]; - System.arraycopy(sourceBuffer, 0, tmp, 0, sourceTop); - sourceBuffer = tmp; - } - - private String sourceToString(int offset) - { - if (offset < 0 || sourceTop < offset) Kit.codeBug(); - return new String(sourceBuffer, offset, sourceTop - offset); - } - - /** - * Decompile the source information associated with this js - * function/script back into a string. For the most part, this - * just means translating tokens back to their string - * representations; there's a little bit of lookahead logic to - * decide the proper spacing/indentation. Most of the work in - * mapping the original source to the prettyprinted decompiled - * version is done by the parser. - * - * @param source encoded source tree presentation - * - * @param flags flags to select output format - * - * @param properties indentation properties - * - */ - public static String decompile(String source, int flags, - UintMap properties) - { - int length = source.length(); - if (length == 0) { return ""; } - - int indent = properties.getInt(INITIAL_INDENT_PROP, 0); - if (indent < 0) throw new IllegalArgumentException(); - int indentGap = properties.getInt(INDENT_GAP_PROP, 4); - if (indentGap < 0) throw new IllegalArgumentException(); - int caseGap = properties.getInt(CASE_GAP_PROP, 2); - if (caseGap < 0) throw new IllegalArgumentException(); - - StringBuffer result = new StringBuffer(); - boolean justFunctionBody = (0 != (flags & Decompiler.ONLY_BODY_FLAG)); - boolean toSource = (0 != (flags & Decompiler.TO_SOURCE_FLAG)); - - // Spew tokens in source, for debugging. - // as TYPE number char - if (printSource) { - System.err.println("length:" + length); - for (int i = 0; i < length; ++i) { - // Note that tokenToName will fail unless Context.printTrees - // is true. - String tokenname = null; - if (Token.printNames) { - tokenname = Token.name(source.charAt(i)); - } - if (tokenname == null) { - tokenname = "---"; - } - String pad = tokenname.length() > 7 - ? "\t" - : "\t\t"; - System.err.println - (tokenname - + pad + (int)source.charAt(i) - + "\t'" + ScriptRuntime.escapeString - (source.substring(i, i+1)) - + "'"); - } - System.err.println(); - } - - int braceNesting = 0; - boolean afterFirstEOL = false; - int i = 0; - int topFunctionType; - if (source.charAt(i) == Token.SCRIPT) { - ++i; - topFunctionType = -1; - } else { - topFunctionType = source.charAt(i + 1); - } - - if (!toSource) { - // add an initial newline to exactly match js. - result.append('\n'); - for (int j = 0; j < indent; j++) - result.append(' '); - } else { - if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) { - result.append('('); - } - } - - while (i < length) { - switch(source.charAt(i)) { - case Token.GET: - case Token.SET: - result.append(source.charAt(i) == Token.GET ? "get " : "set "); - ++i; - i = printSourceString(source, i + 1, false, result); - // Now increment one more to get past the FUNCTION token - ++i; - break; - - case Token.NAME: - case Token.REGEXP: // re-wrapped in '/'s in parser... - i = printSourceString(source, i + 1, false, result); - continue; - - case Token.STRING: - i = printSourceString(source, i + 1, true, result); - continue; - - case Token.NUMBER: - i = printSourceNumber(source, i + 1, result); - continue; - - case Token.TRUE: - result.append("true"); - break; - - case Token.FALSE: - result.append("false"); - break; - - case Token.NULL: - result.append("null"); - break; - - case Token.THIS: - result.append("this"); - break; - - case Token.FUNCTION: - ++i; // skip function type - result.append("function "); - break; - - case FUNCTION_END: - // Do nothing - break; - - case Token.COMMA: - result.append(", "); - break; - - case Token.LC: - ++braceNesting; - if (Token.EOL == getNext(source, length, i)) - indent += indentGap; - result.append('{'); - break; - - case Token.RC: { - --braceNesting; - /* don't print the closing RC if it closes the - * toplevel function and we're called from - * decompileFunctionBody. - */ - if (justFunctionBody && braceNesting == 0) - break; - - result.append('}'); - switch (getNext(source, length, i)) { - case Token.EOL: - case FUNCTION_END: - indent -= indentGap; - break; - case Token.WHILE: - case Token.ELSE: - indent -= indentGap; - result.append(' '); - break; - } - break; - } - case Token.LP: - result.append('('); - break; - - case Token.RP: - result.append(')'); - if (Token.LC == getNext(source, length, i)) - result.append(' '); - break; - - case Token.LB: - result.append('['); - break; - - case Token.RB: - result.append(']'); - break; - - case Token.EOL: { - if (toSource) break; - boolean newLine = true; - if (!afterFirstEOL) { - afterFirstEOL = true; - if (justFunctionBody) { - /* throw away just added 'function name(...) {' - * and restore the original indent - */ - result.setLength(0); - indent -= indentGap; - newLine = false; - } - } - if (newLine) { - result.append('\n'); - } - - /* add indent if any tokens remain, - * less setback if next token is - * a label, case or default. - */ - if (i + 1 < length) { - int less = 0; - int nextToken = source.charAt(i + 1); - if (nextToken == Token.CASE - || nextToken == Token.DEFAULT) - { - less = indentGap - caseGap; - } else if (nextToken == Token.RC) { - less = indentGap; - } - - /* elaborate check against label... skip past a - * following inlined NAME and look for a COLON. - */ - else if (nextToken == Token.NAME) { - int afterName = getSourceStringEnd(source, i + 2); - if (source.charAt(afterName) == Token.COLON) - less = indentGap; - } - - for (; less < indent; less++) - result.append(' '); - } - break; - } - case Token.DOT: - result.append('.'); - break; - - case Token.NEW: - result.append("new "); - break; - - case Token.DELPROP: - result.append("delete "); - break; - - case Token.IF: - result.append("if "); - break; - - case Token.ELSE: - result.append("else "); - break; - - case Token.FOR: - result.append("for "); - break; - - case Token.IN: - result.append(" in "); - break; - - case Token.WITH: - result.append("with "); - break; - - case Token.WHILE: - result.append("while "); - break; - - case Token.DO: - result.append("do "); - break; - - case Token.TRY: - result.append("try "); - break; - - case Token.CATCH: - result.append("catch "); - break; - - case Token.FINALLY: - result.append("finally "); - break; - - case Token.THROW: - result.append("throw "); - break; - - case Token.SWITCH: - result.append("switch "); - break; - - case Token.BREAK: - result.append("break"); - if (Token.NAME == getNext(source, length, i)) - result.append(' '); - break; - - case Token.CONTINUE: - result.append("continue"); - if (Token.NAME == getNext(source, length, i)) - result.append(' '); - break; - - case Token.CASE: - result.append("case "); - break; - - case Token.DEFAULT: - result.append("default"); - break; - - case Token.RETURN: - result.append("return"); - if (Token.SEMI != getNext(source, length, i)) - result.append(' '); - break; - - case Token.VAR: - result.append("var "); - break; - - case Token.SEMI: - result.append(';'); - if (Token.EOL != getNext(source, length, i)) { - // separators in FOR - result.append(' '); - } - break; - - case Token.ASSIGN: - result.append(" = "); - break; - - case Token.ASSIGN_ADD: - result.append(" += "); - break; - - case Token.ASSIGN_SUB: - result.append(" -= "); - break; - - case Token.ASSIGN_MUL: - result.append(" *= "); - break; - - case Token.ASSIGN_DIV: - result.append(" /= "); - break; - - case Token.ASSIGN_MOD: - result.append(" %= "); - break; - - case Token.ASSIGN_BITOR: - result.append(" |= "); - break; - - case Token.ASSIGN_BITXOR: - result.append(" ^= "); - break; - - case Token.ASSIGN_BITAND: - result.append(" &= "); - break; - - case Token.ASSIGN_LSH: - result.append(" <<= "); - break; - - case Token.ASSIGN_RSH: - result.append(" >>= "); - break; - - case Token.ASSIGN_URSH: - result.append(" >>>= "); - break; - - case Token.HOOK: - result.append(" ? "); - break; - - case Token.OBJECTLIT: - // pun OBJECTLIT to mean colon in objlit property - // initialization. - // This needs to be distinct from COLON in the general case - // to distinguish from the colon in a ternary... which needs - // different spacing. - result.append(':'); - break; - - case Token.COLON: - if (Token.EOL == getNext(source, length, i)) - // it's the end of a label - result.append(':'); - else - // it's the middle part of a ternary - result.append(" : "); - break; - - case Token.OR: - result.append(" || "); - break; - - case Token.AND: - result.append(" && "); - break; - - case Token.BITOR: - result.append(" | "); - break; - - case Token.BITXOR: - result.append(" ^ "); - break; - - case Token.BITAND: - result.append(" & "); - break; - - case Token.SHEQ: - result.append(" === "); - break; - - case Token.SHNE: - result.append(" !== "); - break; - - case Token.EQ: - result.append(" == "); - break; - - case Token.NE: - result.append(" != "); - break; - - case Token.LE: - result.append(" <= "); - break; - - case Token.LT: - result.append(" < "); - break; - - case Token.GE: - result.append(" >= "); - break; - - case Token.GT: - result.append(" > "); - break; - - case Token.INSTANCEOF: - result.append(" instanceof "); - break; - - case Token.LSH: - result.append(" << "); - break; - - case Token.RSH: - result.append(" >> "); - break; - - case Token.URSH: - result.append(" >>> "); - break; - - case Token.TYPEOF: - result.append("typeof "); - break; - - case Token.VOID: - result.append("void "); - break; - - case Token.CONST: - result.append("const "); - break; - - case Token.NOT: - result.append('!'); - break; - - case Token.BITNOT: - result.append('~'); - break; - - case Token.POS: - result.append('+'); - break; - - case Token.NEG: - result.append('-'); - break; - - case Token.INC: - result.append("++"); - break; - - case Token.DEC: - result.append("--"); - break; - - case Token.ADD: - result.append(" + "); - break; - - case Token.SUB: - result.append(" - "); - break; - - case Token.MUL: - result.append(" * "); - break; - - case Token.DIV: - result.append(" / "); - break; - - case Token.MOD: - result.append(" % "); - break; - - case Token.COLONCOLON: - result.append("::"); - break; - - case Token.DOTDOT: - result.append(".."); - break; - - case Token.DOTQUERY: - result.append(".("); - break; - - case Token.XMLATTR: - result.append('@'); - break; - - default: - // If we don't know how to decompile it, raise an exception. - throw new RuntimeException("Token: " + - Token.name(source.charAt(i))); - } - ++i; - } - - if (!toSource) { - // add that trailing newline if it's an outermost function. - if (!justFunctionBody) - result.append('\n'); - } else { - if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) { - result.append(')'); - } - } - - return result.toString(); - } - - private static int getNext(String source, int length, int i) - { - return (i + 1 < length) ? source.charAt(i + 1) : Token.EOF; - } - - private static int getSourceStringEnd(String source, int offset) - { - return printSourceString(source, offset, false, null); - } - - private static int printSourceString(String source, int offset, - boolean asQuotedString, - StringBuffer sb) - { - int length = source.charAt(offset); - ++offset; - if ((0x8000 & length) != 0) { - length = ((0x7FFF & length) << 16) | source.charAt(offset); - ++offset; - } - if (sb != null) { - String str = source.substring(offset, offset + length); - if (!asQuotedString) { - sb.append(str); - } else { - sb.append('"'); - sb.append(ScriptRuntime.escapeString(str)); - sb.append('"'); - } - } - return offset + length; - } - - private static int printSourceNumber(String source, int offset, - StringBuffer sb) - { - double number = 0.0; - char type = source.charAt(offset); - ++offset; - if (type == 'S') { - if (sb != null) { - int ival = source.charAt(offset); - number = ival; - } - ++offset; - } else if (type == 'J' || type == 'D') { - if (sb != null) { - long lbits; - lbits = (long)source.charAt(offset) << 48; - lbits |= (long)source.charAt(offset + 1) << 32; - lbits |= (long)source.charAt(offset + 2) << 16; - lbits |= source.charAt(offset + 3); - if (type == 'J') { - number = lbits; - } else { - number = Double.longBitsToDouble(lbits); - } - } - offset += 4; - } else { - // Bad source - throw new RuntimeException(); - } - if (sb != null) { - sb.append(ScriptRuntime.numberToString(number, 10)); - } - return offset; - } - - private char[] sourceBuffer = new char[128]; - -// Per script/function source buffer top: parent source does not include a -// nested functions source and uses function index as a reference instead. - private int sourceTop; - -// whether to do a debug print of the source information, when decompiling. - private static final boolean printSource = false; - -} diff --git a/infrastructure/yuicompressor/src/yuicompressor/org/mozilla/javascript/Parser.java.orig b/infrastructure/yuicompressor/src/yuicompressor/org/mozilla/javascript/Parser.java.orig deleted file mode 100644 index 628bb42..0000000 --- a/infrastructure/yuicompressor/src/yuicompressor/org/mozilla/javascript/Parser.java.orig +++ /dev/null @@ -1,2159 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Mike Ang - * Igor Bukanov - * Yuh-Ruey Chen - * Ethan Hugg - * Bob Jervis - * Terry Lucas - * Mike McCabe - * Milen Nankov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.Reader; -import java.io.IOException; -import java.util.Hashtable; - -/** - * This class implements the JavaScript parser. - * - * It is based on the C source files jsparse.c and jsparse.h - * in the jsref package. - * - * @see TokenStream - * - * @author Mike McCabe - * @author Brendan Eich - */ - -public class Parser -{ - // TokenInformation flags : currentFlaggedToken stores them together - // with token type - final static int - CLEAR_TI_MASK = 0xFFFF, // mask to clear token information bits - TI_AFTER_EOL = 1 << 16, // first token of the source line - TI_CHECK_LABEL = 1 << 17; // indicates to check for label - - CompilerEnvirons compilerEnv; - private ErrorReporter errorReporter; - private String sourceURI; - boolean calledByCompileFunction; - - private TokenStream ts; - private int currentFlaggedToken; - private int syntaxErrorCount; - - private IRFactory nf; - - private int nestingOfFunction; - - private Decompiler decompiler; - private String encodedSource; - -// The following are per function variables and should be saved/restored -// during function parsing. -// XXX Move to separated class? - ScriptOrFnNode currentScriptOrFn; - private int nestingOfWith; - private Hashtable labelSet; // map of label names into nodes - private ObjArray loopSet; - private ObjArray loopAndSwitchSet; - private boolean hasReturnValue; - private int functionEndFlags; -// end of per function variables - - // Exception to unwind - private static class ParserException extends RuntimeException - { - static final long serialVersionUID = 5882582646773765630L; - } - - public Parser(CompilerEnvirons compilerEnv, ErrorReporter errorReporter) - { - this.compilerEnv = compilerEnv; - this.errorReporter = errorReporter; - } - - protected Decompiler createDecompiler(CompilerEnvirons compilerEnv) - { - return new Decompiler(); - } - - void addStrictWarning(String messageId, String messageArg) - { - if (compilerEnv.isStrictMode()) - addWarning(messageId, messageArg); - } - - void addWarning(String messageId, String messageArg) - { - String message = ScriptRuntime.getMessage1(messageId, messageArg); - if (compilerEnv.reportWarningAsError()) { - ++syntaxErrorCount; - errorReporter.error(message, sourceURI, ts.getLineno(), - ts.getLine(), ts.getOffset()); - } else - errorReporter.warning(message, sourceURI, ts.getLineno(), - ts.getLine(), ts.getOffset()); - } - - void addError(String messageId) - { - ++syntaxErrorCount; - String message = ScriptRuntime.getMessage0(messageId); - errorReporter.error(message, sourceURI, ts.getLineno(), - ts.getLine(), ts.getOffset()); - } - - void addError(String messageId, String messageArg) - { - ++syntaxErrorCount; - String message = ScriptRuntime.getMessage1(messageId, messageArg); - errorReporter.error(message, sourceURI, ts.getLineno(), - ts.getLine(), ts.getOffset()); - } - - RuntimeException reportError(String messageId) - { - addError(messageId); - - // Throw a ParserException exception to unwind the recursive descent - // parse. - throw new ParserException(); - } - - private int peekToken() - throws IOException - { - int tt = currentFlaggedToken; - if (tt == Token.EOF) { - tt = ts.getToken(); - if (tt == Token.EOL) { - do { - tt = ts.getToken(); - } while (tt == Token.EOL); - tt |= TI_AFTER_EOL; - } - currentFlaggedToken = tt; - } - return tt & CLEAR_TI_MASK; - } - - private int peekFlaggedToken() - throws IOException - { - peekToken(); - return currentFlaggedToken; - } - - private void consumeToken() - { - currentFlaggedToken = Token.EOF; - } - - private int nextToken() - throws IOException - { - int tt = peekToken(); - consumeToken(); - return tt; - } - - private int nextFlaggedToken() - throws IOException - { - peekToken(); - int ttFlagged = currentFlaggedToken; - consumeToken(); - return ttFlagged; - } - - private boolean matchToken(int toMatch) - throws IOException - { - int tt = peekToken(); - if (tt != toMatch) { - return false; - } - consumeToken(); - return true; - } - - private int peekTokenOrEOL() - throws IOException - { - int tt = peekToken(); - // Check for last peeked token flags - if ((currentFlaggedToken & TI_AFTER_EOL) != 0) { - tt = Token.EOL; - } - return tt; - } - - private void setCheckForLabel() - { - if ((currentFlaggedToken & CLEAR_TI_MASK) != Token.NAME) - throw Kit.codeBug(); - currentFlaggedToken |= TI_CHECK_LABEL; - } - - private void mustMatchToken(int toMatch, String messageId) - throws IOException, ParserException - { - if (!matchToken(toMatch)) { - reportError(messageId); - } - } - - private void mustHaveXML() - { - if (!compilerEnv.isXmlAvailable()) { - reportError("msg.XML.not.available"); - } - } - - public String getEncodedSource() - { - return encodedSource; - } - - public boolean eof() - { - return ts.eof(); - } - - boolean insideFunction() - { - return nestingOfFunction != 0; - } - - private Node enterLoop(Node loopLabel) - { - Node loop = nf.createLoopNode(loopLabel, ts.getLineno()); - if (loopSet == null) { - loopSet = new ObjArray(); - if (loopAndSwitchSet == null) { - loopAndSwitchSet = new ObjArray(); - } - } - loopSet.push(loop); - loopAndSwitchSet.push(loop); - return loop; - } - - private void exitLoop() - { - loopSet.pop(); - loopAndSwitchSet.pop(); - } - - private Node enterSwitch(Node switchSelector, int lineno) - { - Node switchNode = nf.createSwitch(switchSelector, lineno); - if (loopAndSwitchSet == null) { - loopAndSwitchSet = new ObjArray(); - } - loopAndSwitchSet.push(switchNode); - return switchNode; - } - - private void exitSwitch() - { - loopAndSwitchSet.pop(); - } - - /* - * Build a parse tree from the given sourceString. - * - * @return an Object representing the parsed - * program. If the parse fails, null will be returned. (The - * parse failure will result in a call to the ErrorReporter from - * CompilerEnvirons.) - */ - public ScriptOrFnNode parse(String sourceString, - String sourceURI, int lineno) - { - this.sourceURI = sourceURI; - this.ts = new TokenStream(this, null, sourceString, lineno); - try { - return parse(); - } catch (IOException ex) { - // Should never happen - throw new IllegalStateException(); - } - } - - /* - * Build a parse tree from the given sourceString. - * - * @return an Object representing the parsed - * program. If the parse fails, null will be returned. (The - * parse failure will result in a call to the ErrorReporter from - * CompilerEnvirons.) - */ - public ScriptOrFnNode parse(Reader sourceReader, - String sourceURI, int lineno) - throws IOException - { - this.sourceURI = sourceURI; - this.ts = new TokenStream(this, sourceReader, null, lineno); - return parse(); - } - - private ScriptOrFnNode parse() - throws IOException - { - this.decompiler = createDecompiler(compilerEnv); - this.nf = new IRFactory(this); - currentScriptOrFn = nf.createScript(); - int sourceStartOffset = decompiler.getCurrentOffset(); - this.encodedSource = null; - decompiler.addToken(Token.SCRIPT); - - this.currentFlaggedToken = Token.EOF; - this.syntaxErrorCount = 0; - - int baseLineno = ts.getLineno(); // line number where source starts - - /* so we have something to add nodes to until - * we've collected all the source */ - Node pn = nf.createLeaf(Token.BLOCK); - - try { - for (;;) { - int tt = peekToken(); - - if (tt <= Token.EOF) { - break; - } - - Node n; - if (tt == Token.FUNCTION) { - consumeToken(); - try { - n = function(calledByCompileFunction - ? FunctionNode.FUNCTION_EXPRESSION - : FunctionNode.FUNCTION_STATEMENT); - } catch (ParserException e) { - break; - } - } else { - n = statement(); - } - nf.addChildToBack(pn, n); - } - } catch (StackOverflowError ex) { - String msg = ScriptRuntime.getMessage0( - "msg.too.deep.parser.recursion"); - throw Context.reportRuntimeError(msg, sourceURI, - ts.getLineno(), null, 0); - } - - if (this.syntaxErrorCount != 0) { - String msg = String.valueOf(this.syntaxErrorCount); - msg = ScriptRuntime.getMessage1("msg.got.syntax.errors", msg); - throw errorReporter.runtimeError(msg, sourceURI, baseLineno, - null, 0); - } - - currentScriptOrFn.setSourceName(sourceURI); - currentScriptOrFn.setBaseLineno(baseLineno); - currentScriptOrFn.setEndLineno(ts.getLineno()); - - int sourceEndOffset = decompiler.getCurrentOffset(); - currentScriptOrFn.setEncodedSourceBounds(sourceStartOffset, - sourceEndOffset); - - nf.initScript(currentScriptOrFn, pn); - - if (compilerEnv.isGeneratingSource()) { - encodedSource = decompiler.getEncodedSource(); - } - this.decompiler = null; // It helps GC - - return currentScriptOrFn; - } - - /* - * The C version of this function takes an argument list, - * which doesn't seem to be needed for tree generation... - * it'd only be useful for checking argument hiding, which - * I'm not doing anyway... - */ - private Node parseFunctionBody() - throws IOException - { - ++nestingOfFunction; - Node pn = nf.createBlock(ts.getLineno()); - try { - bodyLoop: for (;;) { - Node n; - int tt = peekToken(); - switch (tt) { - case Token.ERROR: - case Token.EOF: - case Token.RC: - break bodyLoop; - - case Token.FUNCTION: - consumeToken(); - n = function(FunctionNode.FUNCTION_STATEMENT); - break; - default: - n = statement(); - break; - } - nf.addChildToBack(pn, n); - } - } catch (ParserException e) { - // Ignore it - } finally { - --nestingOfFunction; - } - - return pn; - } - - private Node function(int functionType) - throws IOException, ParserException - { - int syntheticType = functionType; - int baseLineno = ts.getLineno(); // line number where source starts - - int functionSourceStart = decompiler.markFunctionStart(functionType); - String name; - Node memberExprNode = null; - if (matchToken(Token.NAME)) { - name = ts.getString(); - decompiler.addName(name); - if (!matchToken(Token.LP)) { - if (compilerEnv.isAllowMemberExprAsFunctionName()) { - // Extension to ECMA: if 'function <name>' does not follow - // by '(', assume <name> starts memberExpr - Node memberExprHead = nf.createName(name); - name = ""; - memberExprNode = memberExprTail(false, memberExprHead); - } - mustMatchToken(Token.LP, "msg.no.paren.parms"); - } - } else if (matchToken(Token.LP)) { - // Anonymous function - name = ""; - } else { - name = ""; - if (compilerEnv.isAllowMemberExprAsFunctionName()) { - // Note that memberExpr can not start with '(' like - // in function (1+2).toString(), because 'function (' already - // processed as anonymous function - memberExprNode = memberExpr(false); - } - mustMatchToken(Token.LP, "msg.no.paren.parms"); - } - - if (memberExprNode != null) { - syntheticType = FunctionNode.FUNCTION_EXPRESSION; - } - - boolean nested = insideFunction(); - - FunctionNode fnNode = nf.createFunction(name); - if (nested || nestingOfWith > 0) { - // 1. Nested functions are not affected by the dynamic scope flag - // as dynamic scope is already a parent of their scope. - // 2. Functions defined under the with statement also immune to - // this setup, in which case dynamic scope is ignored in favor - // of with object. - fnNode.itsIgnoreDynamicScope = true; - } - - int functionIndex = currentScriptOrFn.addFunction(fnNode); - - int functionSourceEnd; - - ScriptOrFnNode savedScriptOrFn = currentScriptOrFn; - currentScriptOrFn = fnNode; - int savedNestingOfWith = nestingOfWith; - nestingOfWith = 0; - Hashtable savedLabelSet = labelSet; - labelSet = null; - ObjArray savedLoopSet = loopSet; - loopSet = null; - ObjArray savedLoopAndSwitchSet = loopAndSwitchSet; - loopAndSwitchSet = null; - boolean savedHasReturnValue = hasReturnValue; - int savedFunctionEndFlags = functionEndFlags; - - Node body; - try { - decompiler.addToken(Token.LP); - if (!matchToken(Token.RP)) { - boolean first = true; - do { - if (!first) - decompiler.addToken(Token.COMMA); - first = false; - mustMatchToken(Token.NAME, "msg.no.parm"); - String s = ts.getString(); - if (fnNode.hasParamOrVar(s)) { - addWarning("msg.dup.parms", s); - } - fnNode.addParam(s); - decompiler.addName(s); - } while (matchToken(Token.COMMA)); - - mustMatchToken(Token.RP, "msg.no.paren.after.parms"); - } - decompiler.addToken(Token.RP); - - mustMatchToken(Token.LC, "msg.no.brace.body"); - decompiler.addEOL(Token.LC); - body = parseFunctionBody(); - mustMatchToken(Token.RC, "msg.no.brace.after.body"); - - if (compilerEnv.isStrictMode() && !body.hasConsistentReturnUsage()) - { - String msg = name.length() > 0 ? "msg.no.return.value" - : "msg.anon.no.return.value"; - addStrictWarning(msg, name); - } - - decompiler.addToken(Token.RC); - functionSourceEnd = decompiler.markFunctionEnd(functionSourceStart); - if (functionType != FunctionNode.FUNCTION_EXPRESSION) { - // Add EOL only if function is not part of expression - // since it gets SEMI + EOL from Statement in that case - decompiler.addToken(Token.EOL); - } - } - finally { - hasReturnValue = savedHasReturnValue; - functionEndFlags = savedFunctionEndFlags; - loopAndSwitchSet = savedLoopAndSwitchSet; - loopSet = savedLoopSet; - labelSet = savedLabelSet; - nestingOfWith = savedNestingOfWith; - currentScriptOrFn = savedScriptOrFn; - } - - fnNode.setEncodedSourceBounds(functionSourceStart, functionSourceEnd); - fnNode.setSourceName(sourceURI); - fnNode.setBaseLineno(baseLineno); - fnNode.setEndLineno(ts.getLineno()); - - if (name != null) { - int index = currentScriptOrFn.getParamOrVarIndex(name); - if (index >= 0 && index < currentScriptOrFn.getParamCount()) - addStrictWarning("msg.var.hides.arg", name); - } - - Node pn = nf.initFunction(fnNode, functionIndex, body, syntheticType); - if (memberExprNode != null) { - pn = nf.createAssignment(Token.ASSIGN, memberExprNode, pn); - if (functionType != FunctionNode.FUNCTION_EXPRESSION) { - // XXX check JScript behavior: should it be createExprStatement? - pn = nf.createExprStatementNoReturn(pn, baseLineno); - } - } - return pn; - } - - private Node statements() - throws IOException - { - Node pn = nf.createBlock(ts.getLineno()); - - int tt; - while((tt = peekToken()) > Token.EOF && tt != Token.RC) { - nf.addChildToBack(pn, statement()); - } - - return pn; - } - - private Node condition() - throws IOException, ParserException - { - mustMatchToken(Token.LP, "msg.no.paren.cond"); - decompiler.addToken(Token.LP); - Node pn = expr(false); - mustMatchToken(Token.RP, "msg.no.paren.after.cond"); - decompiler.addToken(Token.RP); - - // Report strict warning on code like "if (a = 7) ...". Suppress the - // warning if the condition is parenthesized, like "if ((a = 7)) ...". - if (pn.getProp(Node.PARENTHESIZED_PROP) == null && - (pn.getType() == Token.SETNAME || pn.getType() == Token.SETPROP || - pn.getType() == Token.SETELEM)) - { - addStrictWarning("msg.equal.as.assign", ""); - } - return pn; - } - - // match a NAME; return null if no match. - private Node matchJumpLabelName() - throws IOException, ParserException - { - Node label = null; - - int tt = peekTokenOrEOL(); - if (tt == Token.NAME) { - consumeToken(); - String name = ts.getString(); - decompiler.addName(name); - if (labelSet != null) { - label = (Node)labelSet.get(name); - } - if (label == null) { - reportError("msg.undef.label"); - } - } - - return label; - } - - private Node statement() - throws IOException - { - try { - Node pn = statementHelper(null); - if (pn != null) { - if (compilerEnv.isStrictMode() && !pn.hasSideEffects()) - addStrictWarning("msg.no.side.effects", ""); - return pn; - } - } catch (ParserException e) { } - - // skip to end of statement - int lineno = ts.getLineno(); - guessingStatementEnd: for (;;) { - int tt = peekTokenOrEOL(); - consumeToken(); - switch (tt) { - case Token.ERROR: - case Token.EOF: - case Token.EOL: - case Token.SEMI: - break guessingStatementEnd; - } - } - return nf.createExprStatement(nf.createName("error"), lineno); - } - - /** - * Whether the "catch (e: e instanceof Exception) { ... }" syntax - * is implemented. - */ - - private Node statementHelper(Node statementLabel) - throws IOException, ParserException - { - Node pn = null; - - int tt; - - tt = peekToken(); - - switch(tt) { - case Token.IF: { - consumeToken(); - - decompiler.addToken(Token.IF); - int lineno = ts.getLineno(); - Node cond = condition(); - decompiler.addEOL(Token.LC); - Node ifTrue = statement(); - Node ifFalse = null; - if (matchToken(Token.ELSE)) { - decompiler.addToken(Token.RC); - decompiler.addToken(Token.ELSE); - decompiler.addEOL(Token.LC); - ifFalse = statement(); - } - decompiler.addEOL(Token.RC); - pn = nf.createIf(cond, ifTrue, ifFalse, lineno); - return pn; - } - - case Token.SWITCH: { - consumeToken(); - - decompiler.addToken(Token.SWITCH); - int lineno = ts.getLineno(); - mustMatchToken(Token.LP, "msg.no.paren.switch"); - decompiler.addToken(Token.LP); - pn = enterSwitch(expr(false), lineno); - try { - mustMatchToken(Token.RP, "msg.no.paren.after.switch"); - decompiler.addToken(Token.RP); - mustMatchToken(Token.LC, "msg.no.brace.switch"); - decompiler.addEOL(Token.LC); - - boolean hasDefault = false; - switchLoop: for (;;) { - tt = nextToken(); - Node caseExpression; - switch (tt) { - case Token.RC: - break switchLoop; - - case Token.CASE: - decompiler.addToken(Token.CASE); - caseExpression = expr(false); - mustMatchToken(Token.COLON, "msg.no.colon.case"); - decompiler.addEOL(Token.COLON); - break; - - case Token.DEFAULT: - if (hasDefault) { - reportError("msg.double.switch.default"); - } - decompiler.addToken(Token.DEFAULT); - hasDefault = true; - caseExpression = null; - mustMatchToken(Token.COLON, "msg.no.colon.case"); - decompiler.addEOL(Token.COLON); - break; - - default: - reportError("msg.bad.switch"); - break switchLoop; - } - - Node block = nf.createLeaf(Token.BLOCK); - while ((tt = peekToken()) != Token.RC - && tt != Token.CASE - && tt != Token.DEFAULT - && tt != Token.EOF) - { - nf.addChildToBack(block, statement()); - } - - // caseExpression == null => add default lable - nf.addSwitchCase(pn, caseExpression, block); - } - decompiler.addEOL(Token.RC); - nf.closeSwitch(pn); - } finally { - exitSwitch(); - } - return pn; - } - - case Token.WHILE: { - consumeToken(); - decompiler.addToken(Token.WHILE); - - Node loop = enterLoop(statementLabel); - try { - Node cond = condition(); - decompiler.addEOL(Token.LC); - Node body = statement(); - decompiler.addEOL(Token.RC); - pn = nf.createWhile(loop, cond, body); - } finally { - exitLoop(); - } - return pn; - } - - case Token.DO: { - consumeToken(); - decompiler.addToken(Token.DO); - decompiler.addEOL(Token.LC); - - Node loop = enterLoop(statementLabel); - try { - Node body = statement(); - decompiler.addToken(Token.RC); - mustMatchToken(Token.WHILE, "msg.no.while.do"); - decompiler.addToken(Token.WHILE); - Node cond = condition(); - pn = nf.createDoWhile(loop, body, cond); - } finally { - exitLoop(); - } - // Always auto-insert semicon to follow SpiderMonkey: - // It is required by EMAScript but is ignored by the rest of - // world, see bug 238945 - matchToken(Token.SEMI); - decompiler.addEOL(Token.SEMI); - return pn; - } - - case Token.FOR: { - consumeToken(); - boolean isForEach = false; - decompiler.addToken(Token.FOR); - - Node loop = enterLoop(statementLabel); - try { - - Node init; // Node init is also foo in 'foo in Object' - Node cond; // Node cond is also object in 'foo in Object' - Node incr = null; // to kill warning - Node body; - - // See if this is a for each () instead of just a for () - if (matchToken(Token.NAME)) { - decompiler.addName(ts.getString()); - if (ts.getString().equals("each")) { - isForEach = true; - } else { - reportError("msg.no.paren.for"); - } - } - - mustMatchToken(Token.LP, "msg.no.paren.for"); - decompiler.addToken(Token.LP); - tt = peekToken(); - if (tt == Token.SEMI) { - init = nf.createLeaf(Token.EMPTY); - } else { - if (tt == Token.VAR) { - // set init to a var list or initial - consumeToken(); // consume the 'var' token - init = variables(Token.FOR); - } - else { - init = expr(true); - } - } - - if (matchToken(Token.IN)) { - decompiler.addToken(Token.IN); - // 'cond' is the object over which we're iterating - cond = expr(false); - } else { // ordinary for loop - mustMatchToken(Token.SEMI, "msg.no.semi.for"); - decompiler.addToken(Token.SEMI); - if (peekToken() == Token.SEMI) { - // no loop condition - cond = nf.createLeaf(Token.EMPTY); - } else { - cond = expr(false); - } - - mustMatchToken(Token.SEMI, "msg.no.semi.for.cond"); - decompiler.addToken(Token.SEMI); - if (peekToken() == Token.RP) { - incr = nf.createLeaf(Token.EMPTY); - } else { - incr = expr(false); - } - } - - mustMatchToken(Token.RP, "msg.no.paren.for.ctrl"); - decompiler.addToken(Token.RP); - decompiler.addEOL(Token.LC); - body = statement(); - decompiler.addEOL(Token.RC); - - if (incr == null) { - // cond could be null if 'in obj' got eaten - // by the init node. - pn = nf.createForIn(loop, init, cond, body, isForEach); - } else { - pn = nf.createFor(loop, init, cond, incr, body); - } - } finally { - exitLoop(); - } - return pn; - } - - case Token.TRY: { - consumeToken(); - int lineno = ts.getLineno(); - - Node tryblock; - Node catchblocks = null; - Node finallyblock = null; - - decompiler.addToken(Token.TRY); - decompiler.addEOL(Token.LC); - tryblock = statement(); - decompiler.addEOL(Token.RC); - - catchblocks = nf.createLeaf(Token.BLOCK); - - boolean sawDefaultCatch = false; - int peek = peekToken(); - if (peek == Token.CATCH) { - while (matchToken(Token.CATCH)) { - if (sawDefaultCatch) { - reportError("msg.catch.unreachable"); - } - decompiler.addToken(Token.CATCH); - mustMatchToken(Token.LP, "msg.no.paren.catch"); - decompiler.addToken(Token.LP); - - mustMatchToken(Token.NAME, "msg.bad.catchcond"); - String varName = ts.getString(); - decompiler.addName(varName); - - Node catchCond = null; - if (matchToken(Token.IF)) { - decompiler.addToken(Token.IF); - catchCond = expr(false); - } else { - sawDefaultCatch = true; - } - - mustMatchToken(Token.RP, "msg.bad.catchcond"); - decompiler.addToken(Token.RP); - mustMatchToken(Token.LC, "msg.no.brace.catchblock"); - decompiler.addEOL(Token.LC); - - nf.addChildToBack(catchblocks, - nf.createCatch(varName, catchCond, - statements(), - ts.getLineno())); - - mustMatchToken(Token.RC, "msg.no.brace.after.body"); - decompiler.addEOL(Token.RC); - } - } else if (peek != Token.FINALLY) { - mustMatchToken(Token.FINALLY, "msg.try.no.catchfinally"); - } - - if (matchToken(Token.FINALLY)) { - decompiler.addToken(Token.FINALLY); - decompiler.addEOL(Token.LC); - finallyblock = statement(); - decompiler.addEOL(Token.RC); - } - - pn = nf.createTryCatchFinally(tryblock, catchblocks, - finallyblock, lineno); - - return pn; - } - - case Token.THROW: { - consumeToken(); - if (peekTokenOrEOL() == Token.EOL) { - // ECMAScript does not allow new lines before throw expression, - // see bug 256617 - reportError("msg.bad.throw.eol"); - } - - int lineno = ts.getLineno(); - decompiler.addToken(Token.THROW); - pn = nf.createThrow(expr(false), lineno); - break; - } - - case Token.BREAK: { - consumeToken(); - int lineno = ts.getLineno(); - - decompiler.addToken(Token.BREAK); - - // matchJumpLabelName only matches if there is one - Node breakStatement = matchJumpLabelName(); - if (breakStatement == null) { - if (loopAndSwitchSet == null || loopAndSwitchSet.size() == 0) { - reportError("msg.bad.break"); - return null; - } - breakStatement = (Node)loopAndSwitchSet.peek(); - } - pn = nf.createBreak(breakStatement, lineno); - break; - } - - case Token.CONTINUE: { - consumeToken(); - int lineno = ts.getLineno(); - - decompiler.addToken(Token.CONTINUE); - - Node loop; - // matchJumpLabelName only matches if there is one - Node label = matchJumpLabelName(); - if (label == null) { - if (loopSet == null || loopSet.size() == 0) { - reportError("msg.continue.outside"); - return null; - } - loop = (Node)loopSet.peek(); - } else { - loop = nf.getLabelLoop(label); - if (loop == null) { - reportError("msg.continue.nonloop"); - return null; - } - } - pn = nf.createContinue(loop, lineno); - break; - } - - case Token.WITH: { - consumeToken(); - - decompiler.addToken(Token.WITH); - int lineno = ts.getLineno(); - mustMatchToken(Token.LP, "msg.no.paren.with"); - decompiler.addToken(Token.LP); - Node obj = expr(false); - mustMatchToken(Token.RP, "msg.no.paren.after.with"); - decompiler.addToken(Token.RP); - decompiler.addEOL(Token.LC); - - ++nestingOfWith; - Node body; - try { - body = statement(); - } finally { - --nestingOfWith; - } - - decompiler.addEOL(Token.RC); - - pn = nf.createWith(obj, body, lineno); - return pn; - } - - case Token.CONST: - case Token.VAR: { - consumeToken(); - pn = variables(tt); - break; - } - - case Token.RETURN: { - if (!insideFunction()) { - reportError("msg.bad.return"); - } - consumeToken(); - decompiler.addToken(Token.RETURN); - int lineno = ts.getLineno(); - - Node retExpr; - /* This is ugly, but we don't want to require a semicolon. */ - tt = peekTokenOrEOL(); - switch (tt) { - case Token.SEMI: - case Token.RC: - case Token.EOF: - case Token.EOL: - case Token.ERROR: - retExpr = null; - break; - default: - retExpr = expr(false); - hasReturnValue = true; - } - pn = nf.createReturn(retExpr, lineno); - - // see if we need a strict mode warning - if (retExpr == null) { - if (functionEndFlags == Node.END_RETURNS_VALUE) - addStrictWarning("msg.return.inconsistent", ""); - - functionEndFlags |= Node.END_RETURNS; - } else { - if (functionEndFlags == Node.END_RETURNS) - addStrictWarning("msg.return.inconsistent", ""); - - functionEndFlags |= Node.END_RETURNS_VALUE; - } - - break; - } - - case Token.LC: - consumeToken(); - if (statementLabel != null) { - decompiler.addToken(Token.LC); - } - pn = statements(); - mustMatchToken(Token.RC, "msg.no.brace.block"); - if (statementLabel != null) { - decompiler.addEOL(Token.RC); - } - return pn; - - case Token.ERROR: - // Fall thru, to have a node for error recovery to work on - case Token.SEMI: - consumeToken(); - pn = nf.createLeaf(Token.EMPTY); - return pn; - - case Token.FUNCTION: { - consumeToken(); - pn = function(FunctionNode.FUNCTION_EXPRESSION_STATEMENT); - return pn; - } - - case Token.DEFAULT : - consumeToken(); - mustHaveXML(); - - decompiler.addToken(Token.DEFAULT); - int nsLine = ts.getLineno(); - - if (!(matchToken(Token.NAME) - && ts.getString().equals("xml"))) - { - reportError("msg.bad.namespace"); - } - decompiler.addName(" xml"); - - if (!(matchToken(Token.NAME) - && ts.getString().equals("namespace"))) - { - reportError("msg.bad.namespace"); - } - decompiler.addName(" namespace"); - - if (!matchToken(Token.ASSIGN)) { - reportError("msg.bad.namespace"); - } - decompiler.addToken(Token.ASSIGN); - - Node expr = expr(false); - pn = nf.createDefaultNamespace(expr, nsLine); - break; - - case Token.NAME: { - int lineno = ts.getLineno(); - String name = ts.getString(); - setCheckForLabel(); - pn = expr(false); - if (pn.getType() != Token.LABEL) { - pn = nf.createExprStatement(pn, lineno); - } else { - // Parsed the label: push back token should be - // colon that primaryExpr left untouched. - if (peekToken() != Token.COLON) Kit.codeBug(); - consumeToken(); - // depend on decompiling lookahead to guess that that - // last name was a label. - decompiler.addName(name); - decompiler.addEOL(Token.COLON); - - if (labelSet == null) { - labelSet = new Hashtable(); - } else if (labelSet.containsKey(name)) { - reportError("msg.dup.label"); - } - - boolean firstLabel; - if (statementLabel == null) { - firstLabel = true; - statementLabel = pn; - } else { - // Discard multiple label nodes and use only - // the first: it allows to simplify IRFactory - firstLabel = false; - } - labelSet.put(name, statementLabel); - try { - pn = statementHelper(statementLabel); - } finally { - labelSet.remove(name); - } - if (firstLabel) { - pn = nf.createLabeledStatement(statementLabel, pn); - } - return pn; - } - break; - } - - default: { - int lineno = ts.getLineno(); - pn = expr(false); - pn = nf.createExprStatement(pn, lineno); - break; - } - } - - int ttFlagged = peekFlaggedToken(); - switch (ttFlagged & CLEAR_TI_MASK) { - case Token.SEMI: - // Consume ';' as a part of expression - consumeToken(); - break; - case Token.ERROR: - case Token.EOF: - case Token.RC: - // Autoinsert ; - break; - default: - if ((ttFlagged & TI_AFTER_EOL) == 0) { - // Report error if no EOL or autoinsert ; otherwise - reportError("msg.no.semi.stmt"); - } - break; - } - decompiler.addEOL(Token.SEMI); - - return pn; - } - - /** - * Parse a 'var' or 'const' statement, or a 'var' init list in a for - * statement. - * @param context A token value: either VAR, CONST or FOR depending on - * context. - * @return The parsed statement - * @throws IOException - * @throws ParserException - */ - private Node variables(int context) - throws IOException, ParserException - { - Node pn; - boolean first = true; - - if (context == Token.CONST){ - pn = nf.createVariables(Token.CONST, ts.getLineno()); - decompiler.addToken(Token.CONST); - } else { - pn = nf.createVariables(Token.VAR, ts.getLineno()); - decompiler.addToken(Token.VAR); - } - - for (;;) { - Node name; - Node init; - mustMatchToken(Token.NAME, "msg.bad.var"); - String s = ts.getString(); - - if (!first) - decompiler.addToken(Token.COMMA); - first = false; - - decompiler.addName(s); - - if (context == Token.CONST) { - if (!currentScriptOrFn.addConst(s)) { - // We know it's already defined, since addConst passes if - // it's not defined at all. The addVar call just confirms - // what it is. - if (currentScriptOrFn.addVar(s) != ScriptOrFnNode.DUPLICATE_CONST) - addError("msg.var.redecl", s); - else - addError("msg.const.redecl", s); - } - } else { - int dupState = currentScriptOrFn.addVar(s); - if (dupState == ScriptOrFnNode.DUPLICATE_CONST) - addError("msg.const.redecl", s); - else if (dupState == ScriptOrFnNode.DUPLICATE_PARAMETER) - addStrictWarning("msg.var.hides.arg", s); - else if (dupState == ScriptOrFnNode.DUPLICATE_VAR) - addStrictWarning("msg.var.redecl", s); - } - name = nf.createName(s); - - // omitted check for argument hiding - - if (matchToken(Token.ASSIGN)) { - decompiler.addToken(Token.ASSIGN); - - init = assignExpr(context == Token.FOR); - nf.addChildToBack(name, init); - } - nf.addChildToBack(pn, name); - if (!matchToken(Token.COMMA)) - break; - } - return pn; - } - - private Node expr(boolean inForInit) - throws IOException, ParserException - { - Node pn = assignExpr(inForInit); - while (matchToken(Token.COMMA)) { - decompiler.addToken(Token.COMMA); - if (compilerEnv.isStrictMode() && !pn.hasSideEffects()) - addStrictWarning("msg.no.side.effects", ""); - pn = nf.createBinary(Token.COMMA, pn, assignExpr(inForInit)); - } - return pn; - } - - private Node assignExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = condExpr(inForInit); - - int tt = peekToken(); - if (Token.FIRST_ASSIGN <= tt && tt <= Token.LAST_ASSIGN) { - consumeToken(); - decompiler.addToken(tt); - pn = nf.createAssignment(tt, pn, assignExpr(inForInit)); - } - - return pn; - } - - private Node condExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = orExpr(inForInit); - - if (matchToken(Token.HOOK)) { - decompiler.addToken(Token.HOOK); - Node ifTrue = assignExpr(false); - mustMatchToken(Token.COLON, "msg.no.colon.cond"); - decompiler.addToken(Token.COLON); - Node ifFalse = assignExpr(inForInit); - return nf.createCondExpr(pn, ifTrue, ifFalse); - } - - return pn; - } - - private Node orExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = andExpr(inForInit); - if (matchToken(Token.OR)) { - decompiler.addToken(Token.OR); - pn = nf.createBinary(Token.OR, pn, orExpr(inForInit)); - } - - return pn; - } - - private Node andExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = bitOrExpr(inForInit); - if (matchToken(Token.AND)) { - decompiler.addToken(Token.AND); - pn = nf.createBinary(Token.AND, pn, andExpr(inForInit)); - } - - return pn; - } - - private Node bitOrExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = bitXorExpr(inForInit); - while (matchToken(Token.BITOR)) { - decompiler.addToken(Token.BITOR); - pn = nf.createBinary(Token.BITOR, pn, bitXorExpr(inForInit)); - } - return pn; - } - - private Node bitXorExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = bitAndExpr(inForInit); - while (matchToken(Token.BITXOR)) { - decompiler.addToken(Token.BITXOR); - pn = nf.createBinary(Token.BITXOR, pn, bitAndExpr(inForInit)); - } - return pn; - } - - private Node bitAndExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = eqExpr(inForInit); - while (matchToken(Token.BITAND)) { - decompiler.addToken(Token.BITAND); - pn = nf.createBinary(Token.BITAND, pn, eqExpr(inForInit)); - } - return pn; - } - - private Node eqExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = relExpr(inForInit); - for (;;) { - int tt = peekToken(); - switch (tt) { - case Token.EQ: - case Token.NE: - case Token.SHEQ: - case Token.SHNE: - consumeToken(); - int decompilerToken = tt; - int parseToken = tt; - if (compilerEnv.getLanguageVersion() == Context.VERSION_1_2) { - // JavaScript 1.2 uses shallow equality for == and != . - // In addition, convert === and !== for decompiler into - // == and != since the decompiler is supposed to show - // canonical source and in 1.2 ===, !== are allowed - // only as an alias to ==, !=. - switch (tt) { - case Token.EQ: - parseToken = Token.SHEQ; - break; - case Token.NE: - parseToken = Token.SHNE; - break; - case Token.SHEQ: - decompilerToken = Token.EQ; - break; - case Token.SHNE: - decompilerToken = Token.NE; - break; - } - } - decompiler.addToken(decompilerToken); - pn = nf.createBinary(parseToken, pn, relExpr(inForInit)); - continue; - } - break; - } - return pn; - } - - private Node relExpr(boolean inForInit) - throws IOException, ParserException - { - Node pn = shiftExpr(); - for (;;) { - int tt = peekToken(); - switch (tt) { - case Token.IN: - if (inForInit) - break; - // fall through - case Token.INSTANCEOF: - case Token.LE: - case Token.LT: - case Token.GE: - case Token.GT: - consumeToken(); - decompiler.addToken(tt); - pn = nf.createBinary(tt, pn, shiftExpr()); - continue; - } - break; - } - return pn; - } - - private Node shiftExpr() - throws IOException, ParserException - { - Node pn = addExpr(); - for (;;) { - int tt = peekToken(); - switch (tt) { - case Token.LSH: - case Token.URSH: - case Token.RSH: - consumeToken(); - decompiler.addToken(tt); - pn = nf.createBinary(tt, pn, addExpr()); - continue; - } - break; - } - return pn; - } - - private Node addExpr() - throws IOException, ParserException - { - Node pn = mulExpr(); - for (;;) { - int tt = peekToken(); - if (tt == Token.ADD || tt == Token.SUB) { - consumeToken(); - decompiler.addToken(tt); - // flushNewLines - pn = nf.createBinary(tt, pn, mulExpr()); - continue; - } - break; - } - - return pn; - } - - private Node mulExpr() - throws IOException, ParserException - { - Node pn = unaryExpr(); - for (;;) { - int tt = peekToken(); - switch (tt) { - case Token.MUL: - case Token.DIV: - case Token.MOD: - consumeToken(); - decompiler.addToken(tt); - pn = nf.createBinary(tt, pn, unaryExpr()); - continue; - } - break; - } - - return pn; - } - - private Node unaryExpr() - throws IOException, ParserException - { - int tt; - - tt = peekToken(); - - switch(tt) { - case Token.VOID: - case Token.NOT: - case Token.BITNOT: - case Token.TYPEOF: - consumeToken(); - decompiler.addToken(tt); - return nf.createUnary(tt, unaryExpr()); - - case Token.ADD: - consumeToken(); - // Convert to special POS token in decompiler and parse tree - decompiler.addToken(Token.POS); - return nf.createUnary(Token.POS, unaryExpr()); - - case Token.SUB: - consumeToken(); - // Convert to special NEG token in decompiler and parse tree - decompiler.addToken(Token.NEG); - return nf.createUnary(Token.NEG, unaryExpr()); - - case Token.INC: - case Token.DEC: - consumeToken(); - decompiler.addToken(tt); - return nf.createIncDec(tt, false, memberExpr(true)); - - case Token.DELPROP: - consumeToken(); - decompiler.addToken(Token.DELPROP); - return nf.createUnary(Token.DELPROP, unaryExpr()); - - case Token.ERROR: - consumeToken(); - break; - - // XML stream encountered in expression. - case Token.LT: - if (compilerEnv.isXmlAvailable()) { - consumeToken(); - Node pn = xmlInitializer(); - return memberExprTail(true, pn); - } - // Fall thru to the default handling of RELOP - - default: - Node pn = memberExpr(true); - - // Don't look across a newline boundary for a postfix incop. - tt = peekTokenOrEOL(); - if (tt == Token.INC || tt == Token.DEC) { - consumeToken(); - decompiler.addToken(tt); - return nf.createIncDec(tt, true, pn); - } - return pn; - } - return nf.createName("err"); // Only reached on error. Try to continue. - - } - - private Node xmlInitializer() throws IOException - { - int tt = ts.getFirstXMLToken(); - if (tt != Token.XML && tt != Token.XMLEND) { - reportError("msg.syntax"); - return null; - } - - /* Make a NEW node to append to. */ - Node pnXML = nf.createLeaf(Token.NEW); - - String xml = ts.getString(); - boolean fAnonymous = xml.trim().startsWith("<>"); - - Node pn = nf.createName(fAnonymous ? "XMLList" : "XML"); - nf.addChildToBack(pnXML, pn); - - pn = null; - Node expr; - for (;;tt = ts.getNextXMLToken()) { - switch (tt) { - case Token.XML: - xml = ts.getString(); - decompiler.addName(xml); - mustMatchToken(Token.LC, "msg.syntax"); - decompiler.addToken(Token.LC); - expr = (peekToken() == Token.RC) - ? nf.createString("") - : expr(false); - mustMatchToken(Token.RC, "msg.syntax"); - decompiler.addToken(Token.RC); - if (pn == null) { - pn = nf.createString(xml); - } else { - pn = nf.createBinary(Token.ADD, pn, nf.createString(xml)); - } - if (ts.isXMLAttribute()) { - /* Need to put the result in double quotes */ - expr = nf.createUnary(Token.ESCXMLATTR, expr); - Node prepend = nf.createBinary(Token.ADD, - nf.createString("\""), - expr); - expr = nf.createBinary(Token.ADD, - prepend, - nf.createString("\"")); - } else { - expr = nf.createUnary(Token.ESCXMLTEXT, expr); - } - pn = nf.createBinary(Token.ADD, pn, expr); - break; - case Token.XMLEND: - xml = ts.getString(); - decompiler.addName(xml); - if (pn == null) { - pn = nf.createString(xml); - } else { - pn = nf.createBinary(Token.ADD, pn, nf.createString(xml)); - } - - nf.addChildToBack(pnXML, pn); - return pnXML; - default: - reportError("msg.syntax"); - return null; - } - } - } - - private void argumentList(Node listNode) - throws IOException, ParserException - { - boolean matched; - matched = matchToken(Token.RP); - if (!matched) { - boolean first = true; - do { - if (!first) - decompiler.addToken(Token.COMMA); - first = false; - nf.addChildToBack(listNode, assignExpr(false)); - } while (matchToken(Token.COMMA)); - - mustMatchToken(Token.RP, "msg.no.paren.arg"); - } - decompiler.addToken(Token.RP); - } - - private Node memberExpr(boolean allowCallSyntax) - throws IOException, ParserException - { - int tt; - - Node pn; - - /* Check for new expressions. */ - tt = peekToken(); - if (tt == Token.NEW) { - /* Eat the NEW token. */ - consumeToken(); - decompiler.addToken(Token.NEW); - - /* Make a NEW node to append to. */ - pn = nf.createCallOrNew(Token.NEW, memberExpr(false)); - - if (matchToken(Token.LP)) { - decompiler.addToken(Token.LP); - /* Add the arguments to pn, if any are supplied. */ - argumentList(pn); - } - - /* XXX there's a check in the C source against - * "too many constructor arguments" - how many - * do we claim to support? - */ - - /* Experimental syntax: allow an object literal to follow a new expression, - * which will mean a kind of anonymous class built with the JavaAdapter. - * the object literal will be passed as an additional argument to the constructor. - */ - tt = peekToken(); - if (tt == Token.LC) { - nf.addChildToBack(pn, primaryExpr()); - } - } else { - pn = primaryExpr(); - } - - return memberExprTail(allowCallSyntax, pn); - } - - private Node memberExprTail(boolean allowCallSyntax, Node pn) - throws IOException, ParserException - { - tailLoop: - for (;;) { - int tt = peekToken(); - switch (tt) { - - case Token.DOT: - case Token.DOTDOT: - { - int memberTypeFlags; - String s; - - consumeToken(); - decompiler.addToken(tt); - memberTypeFlags = 0; - if (tt == Token.DOTDOT) { - mustHaveXML(); - memberTypeFlags = Node.DESCENDANTS_FLAG; - } - if (!compilerEnv.isXmlAvailable()) { - mustMatchToken(Token.NAME, "msg.no.name.after.dot"); - s = ts.getString(); - decompiler.addName(s); - pn = nf.createPropertyGet(pn, null, s, memberTypeFlags); - break; - } - - tt = nextToken(); - switch (tt) { - // handles: name, ns::name, ns::*, ns::[expr] - case Token.NAME: - s = ts.getString(); - decompiler.addName(s); - pn = propertyName(pn, s, memberTypeFlags); - break; - - // handles: *, *::name, *::*, *::[expr] - case Token.MUL: - decompiler.addName("*"); - pn = propertyName(pn, "*", memberTypeFlags); - break; - - // handles: '@attr', '@ns::attr', '@ns::*', '@ns::*', - // '@::attr', '@::*', '@*', '@*::attr', '@*::*' - case Token.XMLATTR: - decompiler.addToken(Token.XMLATTR); - pn = attributeAccess(pn, memberTypeFlags); - break; - - default: - reportError("msg.no.name.after.dot"); - } - } - break; - - case Token.DOTQUERY: - consumeToken(); - mustHaveXML(); - decompiler.addToken(Token.DOTQUERY); - pn = nf.createDotQuery(pn, expr(false), ts.getLineno()); - mustMatchToken(Token.RP, "msg.no.paren"); - decompiler.addToken(Token.RP); - break; - - case Token.LB: - consumeToken(); - decompiler.addToken(Token.LB); - pn = nf.createElementGet(pn, null, expr(false), 0); - mustMatchToken(Token.RB, "msg.no.bracket.index"); - decompiler.addToken(Token.RB); - break; - - case Token.LP: - if (!allowCallSyntax) { - break tailLoop; - } - consumeToken(); - decompiler.addToken(Token.LP); - pn = nf.createCallOrNew(Token.CALL, pn); - /* Add the arguments to pn, if any are supplied. */ - argumentList(pn); - break; - - default: - break tailLoop; - } - } - return pn; - } - - /* - * Xml attribute expression: - * '@attr', '@ns::attr', '@ns::*', '@ns::*', '@*', '@*::attr', '@*::*' - */ - private Node attributeAccess(Node pn, int memberTypeFlags) - throws IOException - { - memberTypeFlags |= Node.ATTRIBUTE_FLAG; - int tt = nextToken(); - - switch (tt) { - // handles: @name, @ns::name, @ns::*, @ns::[expr] - case Token.NAME: - { - String s = ts.getString(); - decompiler.addName(s); - pn = propertyName(pn, s, memberTypeFlags); - } - break; - - // handles: @*, @*::name, @*::*, @*::[expr] - case Token.MUL: - decompiler.addName("*"); - pn = propertyName(pn, "*", memberTypeFlags); - break; - - // handles @[expr] - case Token.LB: - decompiler.addToken(Token.LB); - pn = nf.createElementGet(pn, null, expr(false), memberTypeFlags); - mustMatchToken(Token.RB, "msg.no.bracket.index"); - decompiler.addToken(Token.RB); - break; - - default: - reportError("msg.no.name.after.xmlAttr"); - pn = nf.createPropertyGet(pn, null, "?", memberTypeFlags); - break; - } - - return pn; - } - - /** - * Check if :: follows name in which case it becomes qualified name - */ - private Node propertyName(Node pn, String name, int memberTypeFlags) - throws IOException, ParserException - { - String namespace = null; - if (matchToken(Token.COLONCOLON)) { - decompiler.addToken(Token.COLONCOLON); - namespace = name; - - int tt = nextToken(); - switch (tt) { - // handles name::name - case Token.NAME: - name = ts.getString(); - decompiler.addName(name); - break; - - // handles name::* - case Token.MUL: - decompiler.addName("*"); - name = "*"; - break; - - // handles name::[expr] - case Token.LB: - decompiler.addToken(Token.LB); - pn = nf.createElementGet(pn, namespace, expr(false), - memberTypeFlags); - mustMatchToken(Token.RB, "msg.no.bracket.index"); - decompiler.addToken(Token.RB); - return pn; - - default: - reportError("msg.no.name.after.coloncolon"); - name = "?"; - } - } - - pn = nf.createPropertyGet(pn, namespace, name, memberTypeFlags); - return pn; - } - - private Node primaryExpr() - throws IOException, ParserException - { - Node pn; - - int ttFlagged = nextFlaggedToken(); - int tt = ttFlagged & CLEAR_TI_MASK; - - switch(tt) { - - case Token.FUNCTION: - return function(FunctionNode.FUNCTION_EXPRESSION); - - case Token.LB: { - ObjArray elems = new ObjArray(); - int skipCount = 0; - decompiler.addToken(Token.LB); - boolean after_lb_or_comma = true; - for (;;) { - tt = peekToken(); - - if (tt == Token.COMMA) { - consumeToken(); - decompiler.addToken(Token.COMMA); - if (!after_lb_or_comma) { - after_lb_or_comma = true; - } else { - elems.add(null); - ++skipCount; - } - } else if (tt == Token.RB) { - consumeToken(); - decompiler.addToken(Token.RB); - break; - } else { - if (!after_lb_or_comma) { - reportError("msg.no.bracket.arg"); - } - elems.add(assignExpr(false)); - after_lb_or_comma = false; - } - } - return nf.createArrayLiteral(elems, skipCount); - } - - case Token.LC: { - ObjArray elems = new ObjArray(); - decompiler.addToken(Token.LC); - if (!matchToken(Token.RC)) { - - boolean first = true; - commaloop: - do { - Object property; - - if (!first) - decompiler.addToken(Token.COMMA); - else - first = false; - - tt = peekToken(); - switch(tt) { - case Token.NAME: - case Token.STRING: - consumeToken(); - // map NAMEs to STRINGs in object literal context - // but tell the decompiler the proper type - String s = ts.getString(); - if (tt == Token.NAME) { - if (s.equals("get") && - peekToken() == Token.NAME) { - decompiler.addToken(Token.GET); - consumeToken(); - s = ts.getString(); - decompiler.addName(s); - property = ScriptRuntime.getIndexObject(s); - if (!getterSetterProperty(elems, property, - true)) - break commaloop; - break; - } else if (s.equals("set") && - peekToken() == Token.NAME) { - decompiler.addToken(Token.SET); - consumeToken(); - s = ts.getString(); - decompiler.addName(s); - property = ScriptRuntime.getIndexObject(s); - if (!getterSetterProperty(elems, property, - false)) - break commaloop; - break; - } - decompiler.addName(s); - } else { - decompiler.addString(s); - } - property = ScriptRuntime.getIndexObject(s); - plainProperty(elems, property); - break; - - case Token.NUMBER: - consumeToken(); - double n = ts.getNumber(); - decompiler.addNumber(n); - property = ScriptRuntime.getIndexObject(n); - plainProperty(elems, property); - break; - - case Token.RC: - // trailing comma is OK. - break commaloop; - default: - reportError("msg.bad.prop"); - break commaloop; - } - } while (matchToken(Token.COMMA)); - - mustMatchToken(Token.RC, "msg.no.brace.prop"); - } - decompiler.addToken(Token.RC); - return nf.createObjectLiteral(elems); - } - - case Token.LP: - - /* Brendan's IR-jsparse.c makes a new node tagged with - * TOK_LP here... I'm not sure I understand why. Isn't - * the grouping already implicit in the structure of the - * parse tree? also TOK_LP is already overloaded (I - * think) in the C IR as 'function call.' */ - decompiler.addToken(Token.LP); - pn = expr(false); - pn.putProp(Node.PARENTHESIZED_PROP, Boolean.TRUE); - decompiler.addToken(Token.RP); - mustMatchToken(Token.RP, "msg.no.paren"); - return pn; - - case Token.XMLATTR: - mustHaveXML(); - decompiler.addToken(Token.XMLATTR); - pn = attributeAccess(null, 0); - return pn; - - case Token.NAME: { - String name = ts.getString(); - if ((ttFlagged & TI_CHECK_LABEL) != 0) { - if (peekToken() == Token.COLON) { - // Do not consume colon, it is used as unwind indicator - // to return to statementHelper. - // XXX Better way? - return nf.createLabel(ts.getLineno()); - } - } - - decompiler.addName(name); - if (compilerEnv.isXmlAvailable()) { - pn = propertyName(null, name, 0); - } else { - pn = nf.createName(name); - } - return pn; - } - - case Token.NUMBER: { - double n = ts.getNumber(); - decompiler.addNumber(n); - return nf.createNumber(n); - } - - case Token.STRING: { - String s = ts.getString(); - decompiler.addString(s); - return nf.createString(s); - } - - case Token.DIV: - case Token.ASSIGN_DIV: { - // Got / or /= which should be treated as regexp in fact - ts.readRegExp(tt); - String flags = ts.regExpFlags; - ts.regExpFlags = null; - String re = ts.getString(); - decompiler.addRegexp(re, flags); - int index = currentScriptOrFn.addRegexp(re, flags); - return nf.createRegExp(index); - } - - case Token.NULL: - case Token.THIS: - case Token.FALSE: - case Token.TRUE: - decompiler.addToken(tt); - return nf.createLeaf(tt); - - case Token.RESERVED: - reportError("msg.reserved.id"); - break; - - case Token.ERROR: - /* the scanner or one of its subroutines reported the error. */ - break; - - case Token.EOF: - reportError("msg.unexpected.eof"); - break; - - default: - reportError("msg.syntax"); - break; - } - return null; // should never reach here - } - - private void plainProperty(ObjArray elems, Object property) - throws IOException { - mustMatchToken(Token.COLON, "msg.no.colon.prop"); - - // OBJLIT is used as ':' in object literal for - // decompilation to solve spacing ambiguity. - decompiler.addToken(Token.OBJECTLIT); - elems.add(property); - elems.add(assignExpr(false)); - } - - private boolean getterSetterProperty(ObjArray elems, Object property, - boolean isGetter) throws IOException { - Node f = function(FunctionNode.FUNCTION_EXPRESSION); - if (f.getType() != Token.FUNCTION) { - reportError("msg.bad.prop"); - return false; - } - int fnIndex = f.getExistingIntProp(Node.FUNCTION_PROP); - FunctionNode fn = currentScriptOrFn.getFunctionNode(fnIndex); - if (fn.getFunctionName().length() != 0) { - reportError("msg.bad.prop"); - return false; - } - elems.add(property); - if (isGetter) { - elems.add(nf.createUnary(Token.GET, f)); - } else { - elems.add(nf.createUnary(Token.SET, f)); - } - return true; - } -} diff --git a/infrastructure/yuicompressor/src/yuicompressor/org/mozilla/javascript/Token.java.orig b/infrastructure/yuicompressor/src/yuicompressor/org/mozilla/javascript/Token.java.orig deleted file mode 100644 index 7f7cdc2..0000000 --- a/infrastructure/yuicompressor/src/yuicompressor/org/mozilla/javascript/Token.java.orig +++ /dev/null @@ -1,417 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Roger Lawrence - * Mike McCabe - * Igor Bukanov - * Bob Jervis - * Milen Nankov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -/** - * This class implements the JavaScript scanner. - * - * It is based on the C source files jsscan.c and jsscan.h - * in the jsref package. - * - * @see org.mozilla.javascript.Parser - * - * @author Mike McCabe - * @author Brendan Eich - */ - -public class Token -{ - - // debug flags - public static final boolean printTrees = false; - static final boolean printICode = false; - static final boolean printNames = printTrees || printICode; - - /** - * Token types. These values correspond to JSTokenType values in - * jsscan.c. - */ - - public final static int - // start enum - ERROR = -1, // well-known as the only code < EOF - EOF = 0, // end of file token - (not EOF_CHAR) - EOL = 1, // end of line - - // Interpreter reuses the following as bytecodes - FIRST_BYTECODE_TOKEN = 2, - - ENTERWITH = 2, - LEAVEWITH = 3, - RETURN = 4, - GOTO = 5, - IFEQ = 6, - IFNE = 7, - SETNAME = 8, - BITOR = 9, - BITXOR = 10, - BITAND = 11, - EQ = 12, - NE = 13, - LT = 14, - LE = 15, - GT = 16, - GE = 17, - LSH = 18, - RSH = 19, - URSH = 20, - ADD = 21, - SUB = 22, - MUL = 23, - DIV = 24, - MOD = 25, - NOT = 26, - BITNOT = 27, - POS = 28, - NEG = 29, - NEW = 30, - DELPROP = 31, - TYPEOF = 32, - GETPROP = 33, - SETPROP = 34, - GETELEM = 35, - SETELEM = 36, - CALL = 37, - NAME = 38, - NUMBER = 39, - STRING = 40, - NULL = 41, - THIS = 42, - FALSE = 43, - TRUE = 44, - SHEQ = 45, // shallow equality (===) - SHNE = 46, // shallow inequality (!==) - REGEXP = 47, - BINDNAME = 48, - THROW = 49, - RETHROW = 50, // rethrow caught execetion: catch (e if ) use it - IN = 51, - INSTANCEOF = 52, - LOCAL_LOAD = 53, - GETVAR = 54, - SETVAR = 55, - CATCH_SCOPE = 56, - ENUM_INIT_KEYS = 57, - ENUM_INIT_VALUES = 58, - ENUM_NEXT = 59, - ENUM_ID = 60, - THISFN = 61, - RETURN_RESULT = 62, // to return prevoisly stored return result - ARRAYLIT = 63, // array literal - OBJECTLIT = 64, // object literal - GET_REF = 65, // *reference - SET_REF = 66, // *reference = something - DEL_REF = 67, // delete reference - REF_CALL = 68, // f(args) = something or f(args)++ - REF_SPECIAL = 69, // reference for special properties like __proto - - // For XML support: - DEFAULTNAMESPACE = 70, // default xml namespace = - ESCXMLATTR = 71, - ESCXMLTEXT = 72, - REF_MEMBER = 73, // Reference for x.@y, x..y etc. - REF_NS_MEMBER = 74, // Reference for x.ns::y, x..ns::y etc. - REF_NAME = 75, // Reference for @y, @[y] etc. - REF_NS_NAME = 76; // Reference for ns::y, @ns::y@[y] etc. - - // End of interpreter bytecodes - public final static int - LAST_BYTECODE_TOKEN = REF_NS_NAME, - - TRY = 77, - SEMI = 78, // semicolon - LB = 79, // left and right brackets - RB = 80, - LC = 81, // left and right curlies (braces) - RC = 82, - LP = 83, // left and right parentheses - RP = 84, - COMMA = 85, // comma operator - - ASSIGN = 86, // simple assignment (=) - ASSIGN_BITOR = 87, // |= - ASSIGN_BITXOR = 88, // ^= - ASSIGN_BITAND = 89, // |= - ASSIGN_LSH = 90, // <<= - ASSIGN_RSH = 91, // >>= - ASSIGN_URSH = 92, // >>>= - ASSIGN_ADD = 93, // += - ASSIGN_SUB = 94, // -= - ASSIGN_MUL = 95, // *= - ASSIGN_DIV = 96, // /= - ASSIGN_MOD = 97; // %= - - public final static int - FIRST_ASSIGN = ASSIGN, - LAST_ASSIGN = ASSIGN_MOD, - - HOOK = 98, // conditional (?:) - COLON = 99, - OR = 100, // logical or (||) - AND = 101, // logical and (&&) - INC = 102, // increment/decrement (++ --) - DEC = 103, - DOT = 104, // member operator (.) - FUNCTION = 105, // function keyword - EXPORT = 106, // export keyword - IMPORT = 107, // import keyword - IF = 108, // if keyword - ELSE = 109, // else keyword - SWITCH = 110, // switch keyword - CASE = 111, // case keyword - DEFAULT = 112, // default keyword - WHILE = 113, // while keyword - DO = 114, // do keyword - FOR = 115, // for keyword - BREAK = 116, // break keyword - CONTINUE = 117, // continue keyword - VAR = 118, // var keyword - WITH = 119, // with keyword - CATCH = 120, // catch keyword - FINALLY = 121, // finally keyword - VOID = 122, // void keyword - RESERVED = 123, // reserved keywords - - EMPTY = 124, - - /* types used for the parse tree - these never get returned - * by the scanner. - */ - - BLOCK = 125, // statement block - LABEL = 126, // label - TARGET = 127, - LOOP = 128, - EXPR_VOID = 129, // expression statement in functions - EXPR_RESULT = 130, // expression statement in scripts - JSR = 131, - SCRIPT = 132, // top-level node for entire script - TYPEOFNAME = 133, // for typeof(simple-name) - USE_STACK = 134, - SETPROP_OP = 135, // x.y op= something - SETELEM_OP = 136, // x[y] op= something - LOCAL_BLOCK = 137, - SET_REF_OP = 138, // *reference op= something - - // For XML support: - DOTDOT = 139, // member operator (..) - COLONCOLON = 140, // namespace::name - XML = 141, // XML type - DOTQUERY = 142, // .() -- e.g., x.emps.emp.(name == "terry") - XMLATTR = 143, // @ - XMLEND = 144, - - // Optimizer-only-tokens - TO_OBJECT = 145, - TO_DOUBLE = 146, - - GET = 147, // JS 1.5 get pseudo keyword - SET = 148, // JS 1.5 set pseudo keyword - CONST = 149, - SETCONST = 150, - SETCONSTVAR = 151, - LAST_TOKEN = 152; - - public static String name(int token) - { - if (!printNames) { - return String.valueOf(token); - } - switch (token) { - case ERROR: return "ERROR"; - case EOF: return "EOF"; - case EOL: return "EOL"; - case ENTERWITH: return "ENTERWITH"; - case LEAVEWITH: return "LEAVEWITH"; - case RETURN: return "RETURN"; - case GOTO: return "GOTO"; - case IFEQ: return "IFEQ"; - case IFNE: return "IFNE"; - case SETNAME: return "SETNAME"; - case BITOR: return "BITOR"; - case BITXOR: return "BITXOR"; - case BITAND: return "BITAND"; - case EQ: return "EQ"; - case NE: return "NE"; - case LT: return "LT"; - case LE: return "LE"; - case GT: return "GT"; - case GE: return "GE"; - case LSH: return "LSH"; - case RSH: return "RSH"; - case URSH: return "URSH"; - case ADD: return "ADD"; - case SUB: return "SUB"; - case MUL: return "MUL"; - case DIV: return "DIV"; - case MOD: return "MOD"; - case NOT: return "NOT"; - case BITNOT: return "BITNOT"; - case POS: return "POS"; - case NEG: return "NEG"; - case NEW: return "NEW"; - case DELPROP: return "DELPROP"; - case TYPEOF: return "TYPEOF"; - case GETPROP: return "GETPROP"; - case SETPROP: return "SETPROP"; - case GETELEM: return "GETELEM"; - case SETELEM: return "SETELEM"; - case CALL: return "CALL"; - case NAME: return "NAME"; - case NUMBER: return "NUMBER"; - case STRING: return "STRING"; - case NULL: return "NULL"; - case THIS: return "THIS"; - case FALSE: return "FALSE"; - case TRUE: return "TRUE"; - case SHEQ: return "SHEQ"; - case SHNE: return "SHNE"; - case REGEXP: return "OBJECT"; - case BINDNAME: return "BINDNAME"; - case THROW: return "THROW"; - case RETHROW: return "RETHROW"; - case IN: return "IN"; - case INSTANCEOF: return "INSTANCEOF"; - case LOCAL_LOAD: return "LOCAL_LOAD"; - case GETVAR: return "GETVAR"; - case SETVAR: return "SETVAR"; - case CATCH_SCOPE: return "CATCH_SCOPE"; - case ENUM_INIT_KEYS: return "ENUM_INIT_KEYS"; - case ENUM_INIT_VALUES: return "ENUM_INIT_VALUES"; - case ENUM_NEXT: return "ENUM_NEXT"; - case ENUM_ID: return "ENUM_ID"; - case THISFN: return "THISFN"; - case RETURN_RESULT: return "RETURN_RESULT"; - case ARRAYLIT: return "ARRAYLIT"; - case OBJECTLIT: return "OBJECTLIT"; - case GET_REF: return "GET_REF"; - case SET_REF: return "SET_REF"; - case DEL_REF: return "DEL_REF"; - case REF_CALL: return "REF_CALL"; - case REF_SPECIAL: return "REF_SPECIAL"; - case DEFAULTNAMESPACE:return "DEFAULTNAMESPACE"; - case ESCXMLTEXT: return "ESCXMLTEXT"; - case ESCXMLATTR: return "ESCXMLATTR"; - case REF_MEMBER: return "REF_MEMBER"; - case REF_NS_MEMBER: return "REF_NS_MEMBER"; - case REF_NAME: return "REF_NAME"; - case REF_NS_NAME: return "REF_NS_NAME"; - case TRY: return "TRY"; - case SEMI: return "SEMI"; - case LB: return "LB"; - case RB: return "RB"; - case LC: return "LC"; - case RC: return "RC"; - case LP: return "LP"; - case RP: return "RP"; - case COMMA: return "COMMA"; - case ASSIGN: return "ASSIGN"; - case ASSIGN_BITOR: return "ASSIGN_BITOR"; - case ASSIGN_BITXOR: return "ASSIGN_BITXOR"; - case ASSIGN_BITAND: return "ASSIGN_BITAND"; - case ASSIGN_LSH: return "ASSIGN_LSH"; - case ASSIGN_RSH: return "ASSIGN_RSH"; - case ASSIGN_URSH: return "ASSIGN_URSH"; - case ASSIGN_ADD: return "ASSIGN_ADD"; - case ASSIGN_SUB: return "ASSIGN_SUB"; - case ASSIGN_MUL: return "ASSIGN_MUL"; - case ASSIGN_DIV: return "ASSIGN_DIV"; - case ASSIGN_MOD: return "ASSIGN_MOD"; - case HOOK: return "HOOK"; - case COLON: return "COLON"; - case OR: return "OR"; - case AND: return "AND"; - case INC: return "INC"; - case DEC: return "DEC"; - case DOT: return "DOT"; - case FUNCTION: return "FUNCTION"; - case EXPORT: return "EXPORT"; - case IMPORT: return "IMPORT"; - case IF: return "IF"; - case ELSE: return "ELSE"; - case SWITCH: return "SWITCH"; - case CASE: return "CASE"; - case DEFAULT: return "DEFAULT"; - case WHILE: return "WHILE"; - case DO: return "DO"; - case FOR: return "FOR"; - case BREAK: return "BREAK"; - case CONTINUE: return "CONTINUE"; - case VAR: return "VAR"; - case WITH: return "WITH"; - case CATCH: return "CATCH"; - case FINALLY: return "FINALLY"; - case RESERVED: return "RESERVED"; - case EMPTY: return "EMPTY"; - case BLOCK: return "BLOCK"; - case LABEL: return "LABEL"; - case TARGET: return "TARGET"; - case LOOP: return "LOOP"; - case EXPR_VOID: return "EXPR_VOID"; - case EXPR_RESULT: return "EXPR_RESULT"; - case JSR: return "JSR"; - case SCRIPT: return "SCRIPT"; - case TYPEOFNAME: return "TYPEOFNAME"; - case USE_STACK: return "USE_STACK"; - case SETPROP_OP: return "SETPROP_OP"; - case SETELEM_OP: return "SETELEM_OP"; - case LOCAL_BLOCK: return "LOCAL_BLOCK"; - case SET_REF_OP: return "SET_REF_OP"; - case DOTDOT: return "DOTDOT"; - case COLONCOLON: return "COLONCOLON"; - case XML: return "XML"; - case DOTQUERY: return "DOTQUERY"; - case XMLATTR: return "XMLATTR"; - case XMLEND: return "XMLEND"; - case TO_OBJECT: return "TO_OBJECT"; - case TO_DOUBLE: return "TO_DOUBLE"; - case GET: return "GET"; - case SET: return "SET"; - case CONST: return "CONST"; - case SETCONST: return "SETCONST"; - } - - // Token without name - throw new IllegalStateException(String.valueOf(token)); - } -} diff --git a/infrastructure/yuicompressor/src/yuicompressor/org/mozilla/javascript/TokenStream.java.orig b/infrastructure/yuicompressor/src/yuicompressor/org/mozilla/javascript/TokenStream.java.orig deleted file mode 100644 index c276894..0000000 --- a/infrastructure/yuicompressor/src/yuicompressor/org/mozilla/javascript/TokenStream.java.orig +++ /dev/null @@ -1,1398 +0,0 @@ -/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Rhino code, released - * May 6, 1999. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1997-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Roger Lawrence - * Mike McCabe - * Igor Bukanov - * Ethan Hugg - * Bob Jervis - * Terry Lucas - * Milen Nankov - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License Version 2 or later (the "GPL"), in which - * case the provisions of the GPL are applicable instead of those above. If - * you wish to allow use of your version of this file only under the terms of - * the GPL and not to allow others to use your version of this file under the - * MPL, indicate your decision by deleting the provisions above and replacing - * them with the notice and other provisions required by the GPL. If you do - * not delete the provisions above, a recipient may use your version of this - * file under either the MPL or the GPL. - * - * ***** END LICENSE BLOCK ***** */ - -package org.mozilla.javascript; - -import java.io.*; - -/** - * This class implements the JavaScript scanner. - * - * It is based on the C source files jsscan.c and jsscan.h - * in the jsref package. - * - * @see org.mozilla.javascript.Parser - * - * @author Mike McCabe - * @author Brendan Eich - */ - -class TokenStream -{ - /* - * For chars - because we need something out-of-range - * to check. (And checking EOF by exception is annoying.) - * Note distinction from EOF token type! - */ - private final static int - EOF_CHAR = -1; - - TokenStream(Parser parser, Reader sourceReader, String sourceString, - int lineno) - { - this.parser = parser; - this.lineno = lineno; - if (sourceReader != null) { - if (sourceString != null) Kit.codeBug(); - this.sourceReader = sourceReader; - this.sourceBuffer = new char[512]; - this.sourceEnd = 0; - } else { - if (sourceString == null) Kit.codeBug(); - this.sourceString = sourceString; - this.sourceEnd = sourceString.length(); - } - this.sourceCursor = 0; - } - - /* This function uses the cached op, string and number fields in - * TokenStream; if getToken has been called since the passed token - * was scanned, the op or string printed may be incorrect. - */ - String tokenToString(int token) - { - if (Token.printTrees) { - String name = Token.name(token); - - switch (token) { - case Token.STRING: - case Token.REGEXP: - case Token.NAME: - return name + " `" + this.string + "'"; - - case Token.NUMBER: - return "NUMBER " + this.number; - } - - return name; - } - return ""; - } - - static boolean isKeyword(String s) - { - return Token.EOF != stringToKeyword(s); - } - - private static int stringToKeyword(String name) - { -// #string_id_map# -// The following assumes that Token.EOF == 0 - final int - Id_break = Token.BREAK, - Id_case = Token.CASE, - Id_continue = Token.CONTINUE, - Id_default = Token.DEFAULT, - Id_delete = Token.DELPROP, - Id_do = Token.DO, - Id_else = Token.ELSE, - Id_export = Token.EXPORT, - Id_false = Token.FALSE, - Id_for = Token.FOR, - Id_function = Token.FUNCTION, - Id_if = Token.IF, - Id_in = Token.IN, - Id_new = Token.NEW, - Id_null = Token.NULL, - Id_return = Token.RETURN, - Id_switch = Token.SWITCH, - Id_this = Token.THIS, - Id_true = Token.TRUE, - Id_typeof = Token.TYPEOF, - Id_var = Token.VAR, - Id_void = Token.VOID, - Id_while = Token.WHILE, - Id_with = Token.WITH, - - // the following are #ifdef RESERVE_JAVA_KEYWORDS in jsscan.c - Id_abstract = Token.RESERVED, - Id_boolean = Token.RESERVED, - Id_byte = Token.RESERVED, - Id_catch = Token.CATCH, - Id_char = Token.RESERVED, - Id_class = Token.RESERVED, - Id_const = Token.CONST, - Id_debugger = Token.RESERVED, - Id_double = Token.RESERVED, - Id_enum = Token.RESERVED, - Id_extends = Token.RESERVED, - Id_final = Token.RESERVED, - Id_finally = Token.FINALLY, - Id_float = Token.RESERVED, - Id_goto = Token.RESERVED, - Id_implements = Token.RESERVED, - Id_import = Token.IMPORT, - Id_instanceof = Token.INSTANCEOF, - Id_int = Token.RESERVED, - Id_interface = Token.RESERVED, - Id_long = Token.RESERVED, - Id_native = Token.RESERVED, - Id_package = Token.RESERVED, - Id_private = Token.RESERVED, - Id_protected = Token.RESERVED, - Id_public = Token.RESERVED, - Id_short = Token.RESERVED, - Id_static = Token.RESERVED, - Id_super = Token.RESERVED, - Id_synchronized = Token.RESERVED, - Id_throw = Token.THROW, - Id_throws = Token.RESERVED, - Id_transient = Token.RESERVED, - Id_try = Token.TRY, - Id_volatile = Token.RESERVED; - - int id; - String s = name; -// #generated# Last update: 2001-06-01 17:45:01 CEST - L0: { id = 0; String X = null; int c; - L: switch (s.length()) { - case 2: c=s.charAt(1); - if (c=='f') { if (s.charAt(0)=='i') {id=Id_if; break L0;} } - else if (c=='n') { if (s.charAt(0)=='i') {id=Id_in; break L0;} } - else if (c=='o') { if (s.charAt(0)=='d') {id=Id_do; break L0;} } - break L; - case 3: switch (s.charAt(0)) { - case 'f': if (s.charAt(2)=='r' && s.charAt(1)=='o') {id=Id_for; break L0;} break L; - case 'i': if (s.charAt(2)=='t' && s.charAt(1)=='n') {id=Id_int; break L0;} break L; - case 'n': if (s.charAt(2)=='w' && s.charAt(1)=='e') {id=Id_new; break L0;} break L; - case 't': if (s.charAt(2)=='y' && s.charAt(1)=='r') {id=Id_try; break L0;} break L; - case 'v': if (s.charAt(2)=='r' && s.charAt(1)=='a') {id=Id_var; break L0;} break L; - } break L; - case 4: switch (s.charAt(0)) { - case 'b': X="byte";id=Id_byte; break L; - case 'c': c=s.charAt(3); - if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='a') {id=Id_case; break L0;} } - else if (c=='r') { if (s.charAt(2)=='a' && s.charAt(1)=='h') {id=Id_char; break L0;} } - break L; - case 'e': c=s.charAt(3); - if (c=='e') { if (s.charAt(2)=='s' && s.charAt(1)=='l') {id=Id_else; break L0;} } - else if (c=='m') { if (s.charAt(2)=='u' && s.charAt(1)=='n') {id=Id_enum; break L0;} } - break L; - case 'g': X="goto";id=Id_goto; break L; - case 'l': X="long";id=Id_long; break L; - case 'n': X="null";id=Id_null; break L; - case 't': c=s.charAt(3); - if (c=='e') { if (s.charAt(2)=='u' && s.charAt(1)=='r') {id=Id_true; break L0;} } - else if (c=='s') { if (s.charAt(2)=='i' && s.charAt(1)=='h') {id=Id_this; break L0;} } - break L; - case 'v': X="void";id=Id_void; break L; - case 'w': X="with";id=Id_with; break L; - } break L; - case 5: switch (s.charAt(2)) { - case 'a': X="class";id=Id_class; break L; - case 'e': X="break";id=Id_break; break L; - case 'i': X="while";id=Id_while; break L; - case 'l': X="false";id=Id_false; break L; - case 'n': c=s.charAt(0); - if (c=='c') { X="const";id=Id_const; } - else if (c=='f') { X="final";id=Id_final; } - break L; - case 'o': c=s.charAt(0); - if (c=='f') { X="float";id=Id_float; } - else if (c=='s') { X="short";id=Id_short; } - break L; - case 'p': X="super";id=Id_super; break L; - case 'r': X="throw";id=Id_throw; break L; - case 't': X="catch";id=Id_catch; break L; - } break L; - case 6: switch (s.charAt(1)) { - case 'a': X="native";id=Id_native; break L; - case 'e': c=s.charAt(0); - if (c=='d') { X="delete";id=Id_delete; } - else if (c=='r') { X="return";id=Id_return; } - break L; - case 'h': X="throws";id=Id_throws; break L; - case 'm': X="import";id=Id_import; break L; - case 'o': X="double";id=Id_double; break L; - case 't': X="static";id=Id_static; break L; - case 'u': X="public";id=Id_public; break L; - case 'w': X="switch";id=Id_switch; break L; - case 'x': X="export";id=Id_export; break L; - case 'y': X="typeof";id=Id_typeof; break L; - } break L; - case 7: switch (s.charAt(1)) { - case 'a': X="package";id=Id_package; break L; - case 'e': X="default";id=Id_default; break L; - case 'i': X="finally";id=Id_finally; break L; - case 'o': X="boolean";id=Id_boolean; break L; - case 'r': X="private";id=Id_private; break L; - case 'x': X="extends";id=Id_extends; break L; - } break L; - case 8: switch (s.charAt(0)) { - case 'a': X="abstract";id=Id_abstract; break L; - case 'c': X="continue";id=Id_continue; break L; - case 'd': X="debugger";id=Id_debugger; break L; - case 'f': X="function";id=Id_function; break L; - case 'v': X="volatile";id=Id_volatile; break L; - } break L; - case 9: c=s.charAt(0); - if (c=='i') { X="interface";id=Id_interface; } - else if (c=='p') { X="protected";id=Id_protected; } - else if (c=='t') { X="transient";id=Id_transient; } - break L; - case 10: c=s.charAt(1); - if (c=='m') { X="implements";id=Id_implements; } - else if (c=='n') { X="instanceof";id=Id_instanceof; } - break L; - case 12: X="synchronized";id=Id_synchronized; break L; - } - if (X!=null && X!=s && !X.equals(s)) id = 0; - } -// #/generated# -// #/string_id_map# - if (id == 0) { return Token.EOF; } - return id & 0xff; - } - - final int getLineno() { return lineno; } - - final String getString() { return string; } - - final double getNumber() { return number; } - - final boolean eof() { return hitEOF; } - - final int getToken() throws IOException - { - int c; - - retry: - for (;;) { - // Eat whitespace, possibly sensitive to newlines. - for (;;) { - c = getChar(); - if (c == EOF_CHAR) { - return Token.EOF; - } else if (c == '\n') { - dirtyLine = false; - return Token.EOL; - } else if (!isJSSpace(c)) { - if (c != '-') { - dirtyLine = true; - } - break; - } - } - - if (c == '@') return Token.XMLATTR; - - // identifier/keyword/instanceof? - // watch out for starting with a <backslash> - boolean identifierStart; - boolean isUnicodeEscapeStart = false; - if (c == '\\') { - c = getChar(); - if (c == 'u') { - identifierStart = true; - isUnicodeEscapeStart = true; - stringBufferTop = 0; - } else { - identifierStart = false; - ungetChar(c); - c = '\\'; - } - } else { - identifierStart = Character.isJavaIdentifierStart((char)c); - if (identifierStart) { - stringBufferTop = 0; - addToString(c); - } - } - - if (identifierStart) { - boolean containsEscape = isUnicodeEscapeStart; - for (;;) { - if (isUnicodeEscapeStart) { - // strictly speaking we should probably push-back - // all the bad characters if the <backslash>uXXXX - // sequence is malformed. But since there isn't a - // correct context(is there?) for a bad Unicode - // escape sequence in an identifier, we can report - // an error here. - int escapeVal = 0; - for (int i = 0; i != 4; ++i) { - c = getChar(); - escapeVal = Kit.xDigitToInt(c, escapeVal); - // Next check takes care about c < 0 and bad escape - if (escapeVal < 0) { break; } - } - if (escapeVal < 0) { - parser.addError("msg.invalid.escape"); - return Token.ERROR; - } - addToString(escapeVal); - isUnicodeEscapeStart = false; - } else { - c = getChar(); - if (c == '\\') { - c = getChar(); - if (c == 'u') { - isUnicodeEscapeStart = true; - containsEscape = true; - } else { - parser.addError("msg.illegal.character"); - return Token.ERROR; - } - } else { - if (c == EOF_CHAR - || !Character.isJavaIdentifierPart((char)c)) - { - break; - } - addToString(c); - } - } - } - ungetChar(c); - - String str = getStringFromBuffer(); - if (!containsEscape) { - // OPT we shouldn't have to make a string (object!) to - // check if it's a keyword. - - // Return the corresponding token if it's a keyword - int result = stringToKeyword(str); - if (result != Token.EOF) { - if (result != Token.RESERVED) { - return result; - } else if (!parser.compilerEnv. - isReservedKeywordAsIdentifier()) - { - return result; - } else { - // If implementation permits to use future reserved - // keywords in violation with the EcmaScript, - // treat it as name but issue warning - parser.addWarning("msg.reserved.keyword", str); - } - } - } - this.string = (String)allStrings.intern(str); - return Token.NAME; - } - - // is it a number? - if (isDigit(c) || (c == '.' && isDigit(peekChar()))) { - - stringBufferTop = 0; - int base = 10; - - if (c == '0') { - c = getChar(); - if (c == 'x' || c == 'X') { - base = 16; - c = getChar(); - } else if (isDigit(c)) { - base = 8; - } else { - addToString('0'); - } - } - - if (base == 16) { - while (0 <= Kit.xDigitToInt(c, 0)) { - addToString(c); - c = getChar(); - } - } else { - while ('0' <= c && c <= '9') { - /* - * We permit 08 and 09 as decimal numbers, which - * makes our behavior a superset of the ECMA - * numeric grammar. We might not always be so - * permissive, so we warn about it. - */ - if (base == 8 && c >= '8') { - parser.addWarning("msg.bad.octal.literal", - c == '8' ? "8" : "9"); - base = 10; - } - addToString(c); - c = getChar(); - } - } - - boolean isInteger = true; - - if (base == 10 && (c == '.' || c == 'e' || c == 'E')) { - isInteger = false; - if (c == '.') { - do { - addToString(c); - c = getChar(); - } while (isDigit(c)); - } - if (c == 'e' || c == 'E') { - addToString(c); - c = getChar(); - if (c == '+' || c == '-') { - addToString(c); - c = getChar(); - } - if (!isDigit(c)) { - parser.addError("msg.missing.exponent"); - return Token.ERROR; - } - do { - addToString(c); - c = getChar(); - } while (isDigit(c)); - } - } - ungetChar(c); - String numString = getStringFromBuffer(); - - double dval; - if (base == 10 && !isInteger) { - try { - // Use Java conversion to number from string... - dval = Double.valueOf(numString).doubleValue(); - } - catch (NumberFormatException ex) { - parser.addError("msg.caught.nfe"); - return Token.ERROR; - } - } else { - dval = ScriptRuntime.stringToNumber(numString, 0, base); - } - - this.number = dval; - return Token.NUMBER; - } - - // is it a string? - if (c == '"' || c == '\'') { - // We attempt to accumulate a string the fast way, by - // building it directly out of the reader. But if there - // are any escaped characters in the string, we revert to - // building it out of a StringBuffer. - - int quoteChar = c; - stringBufferTop = 0; - - c = getChar(); - strLoop: while (c != quoteChar) { - if (c == '\n' || c == EOF_CHAR) { - ungetChar(c); - parser.addError("msg.unterminated.string.lit"); - return Token.ERROR; - } - - if (c == '\\') { - // We've hit an escaped character - int escapeVal; - - c = getChar(); - switch (c) { - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - - // \v a late addition to the ECMA spec, - // it is not in Java, so use 0xb - case 'v': c = 0xb; break; - - case 'u': - // Get 4 hex digits; if the u escape is not - // followed by 4 hex digits, use 'u' + the - // literal character sequence that follows. - int escapeStart = stringBufferTop; - addToString('u'); - escapeVal = 0; - for (int i = 0; i != 4; ++i) { - c = getChar(); - escapeVal = Kit.xDigitToInt(c, escapeVal); - if (escapeVal < 0) { - continue strLoop; - } - addToString(c); - } - // prepare for replace of stored 'u' sequence - // by escape value - stringBufferTop = escapeStart; - c = escapeVal; - break; - case 'x': - // Get 2 hex digits, defaulting to 'x'+literal - // sequence, as above. - c = getChar(); - escapeVal = Kit.xDigitToInt(c, 0); - if (escapeVal < 0) { - addToString('x'); - continue strLoop; - } else { - int c1 = c; - c = getChar(); - escapeVal = Kit.xDigitToInt(c, escapeVal); - if (escapeVal < 0) { - addToString('x'); - addToString(c1); - continue strLoop; - } else { - // got 2 hex digits - c = escapeVal; - } - } - break; - - case '\n': - // Remove line terminator after escape to follow - // SpiderMonkey and C/C++ - c = getChar(); - continue strLoop; - - default: - if ('0' <= c && c < '8') { - int val = c - '0'; - c = getChar(); - if ('0' <= c && c < '8') { - val = 8 * val + c - '0'; - c = getChar(); - if ('0' <= c && c < '8' && val <= 037) { - // c is 3rd char of octal sequence only - // if the resulting val <= 0377 - val = 8 * val + c - '0'; - c = getChar(); - } - } - ungetChar(c); - c = val; - } - } - } - addToString(c); - c = getChar(); - } - - String str = getStringFromBuffer(); - this.string = (String)allStrings.intern(str); - return Token.STRING; - } - - switch (c) { - case ';': return Token.SEMI; - case '[': return Token.LB; - case ']': return Token.RB; - case '{': return Token.LC; - case '}': return Token.RC; - case '(': return Token.LP; - case ')': return Token.RP; - case ',': return Token.COMMA; - case '?': return Token.HOOK; - case ':': - if (matchChar(':')) { - return Token.COLONCOLON; - } else { - return Token.COLON; - } - case '.': - if (matchChar('.')) { - return Token.DOTDOT; - } else if (matchChar('(')) { - return Token.DOTQUERY; - } else { - return Token.DOT; - } - - case '|': - if (matchChar('|')) { - return Token.OR; - } else if (matchChar('=')) { - return Token.ASSIGN_BITOR; - } else { - return Token.BITOR; - } - - case '^': - if (matchChar('=')) { - return Token.ASSIGN_BITXOR; - } else { - return Token.BITXOR; - } - - case '&': - if (matchChar('&')) { - return Token.AND; - } else if (matchChar('=')) { - return Token.ASSIGN_BITAND; - } else { - return Token.BITAND; - } - - case '=': - if (matchChar('=')) { - if (matchChar('=')) - return Token.SHEQ; - else - return Token.EQ; - } else { - return Token.ASSIGN; - } - - case '!': - if (matchChar('=')) { - if (matchChar('=')) - return Token.SHNE; - else - return Token.NE; - } else { - return Token.NOT; - } - - case '<': - /* NB:treat HTML begin-comment as comment-till-eol */ - if (matchChar('!')) { - if (matchChar('-')) { - if (matchChar('-')) { - skipLine(); - continue retry; - } - ungetChar('-'); - } - ungetChar('!'); - } - if (matchChar('<')) { - if (matchChar('=')) { - return Token.ASSIGN_LSH; - } else { - return Token.LSH; - } - } else { - if (matchChar('=')) { - return Token.LE; - } else { - return Token.LT; - } - } - - case '>': - if (matchChar('>')) { - if (matchChar('>')) { - if (matchChar('=')) { - return Token.ASSIGN_URSH; - } else { - return Token.URSH; - } - } else { - if (matchChar('=')) { - return Token.ASSIGN_RSH; - } else { - return Token.RSH; - } - } - } else { - if (matchChar('=')) { - return Token.GE; - } else { - return Token.GT; - } - } - - case '*': - if (matchChar('=')) { - return Token.ASSIGN_MUL; - } else { - return Token.MUL; - } - - case '/': - // is it a // comment? - if (matchChar('/')) { - skipLine(); - continue retry; - } - if (matchChar('*')) { - boolean lookForSlash = false; - for (;;) { - c = getChar(); - if (c == EOF_CHAR) { - parser.addError("msg.unterminated.comment"); - return Token.ERROR; - } else if (c == '*') { - lookForSlash = true; - } else if (c == '/') { - if (lookForSlash) { - continue retry; - } - } else { - lookForSlash = false; - } - } - } - - if (matchChar('=')) { - return Token.ASSIGN_DIV; - } else { - return Token.DIV; - } - - case '%': - if (matchChar('=')) { - return Token.ASSIGN_MOD; - } else { - return Token.MOD; - } - - case '~': - return Token.BITNOT; - - case '+': - if (matchChar('=')) { - return Token.ASSIGN_ADD; - } else if (matchChar('+')) { - return Token.INC; - } else { - return Token.ADD; - } - - case '-': - if (matchChar('=')) { - c = Token.ASSIGN_SUB; - } else if (matchChar('-')) { - if (!dirtyLine) { - // treat HTML end-comment after possible whitespace - // after line start as comment-utill-eol - if (matchChar('>')) { - skipLine(); - continue retry; - } - } - c = Token.DEC; - } else { - c = Token.SUB; - } - dirtyLine = true; - return c; - - default: - parser.addError("msg.illegal.character"); - return Token.ERROR; - } - } - } - - private static boolean isAlpha(int c) - { - // Use 'Z' < 'a' - if (c <= 'Z') { - return 'A' <= c; - } else { - return 'a' <= c && c <= 'z'; - } - } - - static boolean isDigit(int c) - { - return '0' <= c && c <= '9'; - } - - /* As defined in ECMA. jsscan.c uses C isspace() (which allows - * \v, I think.) note that code in getChar() implicitly accepts - * '\r' == \u000D as well. - */ - static boolean isJSSpace(int c) - { - if (c <= 127) { - return c == 0x20 || c == 0x9 || c == 0xC || c == 0xB; - } else { - return c == 0xA0 - || Character.getType((char)c) == Character.SPACE_SEPARATOR; - } - } - - private static boolean isJSFormatChar(int c) - { - return c > 127 && Character.getType((char)c) == Character.FORMAT; - } - - /** - * Parser calls the method when it gets / or /= in literal context. - */ - void readRegExp(int startToken) - throws IOException - { - stringBufferTop = 0; - if (startToken == Token.ASSIGN_DIV) { - // Miss-scanned /= - addToString('='); - } else { - if (startToken != Token.DIV) Kit.codeBug(); - } - - int c; - while ((c = getChar()) != '/') { - if (c == '\n' || c == EOF_CHAR) { - ungetChar(c); - throw parser.reportError("msg.unterminated.re.lit"); - } - if (c == '\\') { - addToString(c); - c = getChar(); - } - - addToString(c); - } - int reEnd = stringBufferTop; - - while (true) { - if (matchChar('g')) - addToString('g'); - else if (matchChar('i')) - addToString('i'); - else if (matchChar('m')) - addToString('m'); - else - break; - } - - if (isAlpha(peekChar())) { - throw parser.reportError("msg.invalid.re.flag"); - } - - this.string = new String(stringBuffer, 0, reEnd); - this.regExpFlags = new String(stringBuffer, reEnd, - stringBufferTop - reEnd); - } - - boolean isXMLAttribute() - { - return xmlIsAttribute; - } - - int getFirstXMLToken() throws IOException - { - xmlOpenTagsCount = 0; - xmlIsAttribute = false; - xmlIsTagContent = false; - ungetChar('<'); - return getNextXMLToken(); - } - - int getNextXMLToken() throws IOException - { - stringBufferTop = 0; // remember the XML - - for (int c = getChar(); c != EOF_CHAR; c = getChar()) { - if (xmlIsTagContent) { - switch (c) { - case '>': - addToString(c); - xmlIsTagContent = false; - xmlIsAttribute = false; - break; - case '/': - addToString(c); - if (peekChar() == '>') { - c = getChar(); - addToString(c); - xmlIsTagContent = false; - xmlOpenTagsCount--; - } - break; - case '{': - ungetChar(c); - this.string = getStringFromBuffer(); - return Token.XML; - case '\'': - case '"': - addToString(c); - if (!readQuotedString(c)) return Token.ERROR; - break; - case '=': - addToString(c); - xmlIsAttribute = true; - break; - case ' ': - case '\t': - case '\r': - case '\n': - addToString(c); - break; - default: - addToString(c); - xmlIsAttribute = false; - break; - } - - if (!xmlIsTagContent && xmlOpenTagsCount == 0) { - this.string = getStringFromBuffer(); - return Token.XMLEND; - } - } else { - switch (c) { - case '<': - addToString(c); - c = peekChar(); - switch (c) { - case '!': - c = getChar(); // Skip ! - addToString(c); - c = peekChar(); - switch (c) { - case '-': - c = getChar(); // Skip - - addToString(c); - c = getChar(); - if (c == '-') { - addToString(c); - if(!readXmlComment()) return Token.ERROR; - } else { - // throw away the string in progress - stringBufferTop = 0; - this.string = null; - parser.addError("msg.XML.bad.form"); - return Token.ERROR; - } - break; - case '[': - c = getChar(); // Skip [ - addToString(c); - if (getChar() == 'C' && - getChar() == 'D' && - getChar() == 'A' && - getChar() == 'T' && - getChar() == 'A' && - getChar() == '[') - { - addToString('C'); - addToString('D'); - addToString('A'); - addToString('T'); - addToString('A'); - addToString('['); - if (!readCDATA()) return Token.ERROR; - - } else { - // throw away the string in progress - stringBufferTop = 0; - this.string = null; - parser.addError("msg.XML.bad.form"); - return Token.ERROR; - } - break; - default: - if(!readEntity()) return Token.ERROR; - break; - } - break; - case '?': - c = getChar(); // Skip ? - addToString(c); - if (!readPI()) return Token.ERROR; - break; - case '/': - // End tag - c = getChar(); // Skip / - addToString(c); - if (xmlOpenTagsCount == 0) { - // throw away the string in progress - stringBufferTop = 0; - this.string = null; - parser.addError("msg.XML.bad.form"); - return Token.ERROR; - } - xmlIsTagContent = true; - xmlOpenTagsCount--; - break; - default: - // Start tag - xmlIsTagContent = true; - xmlOpenTagsCount++; - break; - } - break; - case '{': - ungetChar(c); - this.string = getStringFromBuffer(); - return Token.XML; - default: - addToString(c); - break; - } - } - } - - stringBufferTop = 0; // throw away the string in progress - this.string = null; - parser.addError("msg.XML.bad.form"); - return Token.ERROR; - } - - /** - * - */ - private boolean readQuotedString(int quote) throws IOException - { - for (int c = getChar(); c != EOF_CHAR; c = getChar()) { - addToString(c); - if (c == quote) return true; - } - - stringBufferTop = 0; // throw away the string in progress - this.string = null; - parser.addError("msg.XML.bad.form"); - return false; - } - - /** - * - */ - private boolean readXmlComment() throws IOException - { - for (int c = getChar(); c != EOF_CHAR;) { - addToString(c); - if (c == '-' && peekChar() == '-') { - c = getChar(); - addToString(c); - if (peekChar() == '>') { - c = getChar(); // Skip > - addToString(c); - return true; - } else { - continue; - } - } - c = getChar(); - } - - stringBufferTop = 0; // throw away the string in progress - this.string = null; - parser.addError("msg.XML.bad.form"); - return false; - } - - /** - * - */ - private boolean readCDATA() throws IOException - { - for (int c = getChar(); c != EOF_CHAR;) { - addToString(c); - if (c == ']' && peekChar() == ']') { - c = getChar(); - addToString(c); - if (peekChar() == '>') { - c = getChar(); // Skip > - addToString(c); - return true; - } else { - continue; - } - } - c = getChar(); - } - - stringBufferTop = 0; // throw away the string in progress - this.string = null; - parser.addError("msg.XML.bad.form"); - return false; - } - - /** - * - */ - private boolean readEntity() throws IOException - { - int declTags = 1; - for (int c = getChar(); c != EOF_CHAR; c = getChar()) { - addToString(c); - switch (c) { - case '<': - declTags++; - break; - case '>': - declTags--; - if (declTags == 0) return true; - break; - } - } - - stringBufferTop = 0; // throw away the string in progress - this.string = null; - parser.addError("msg.XML.bad.form"); - return false; - } - - /** - * - */ - private boolean readPI() throws IOException - { - for (int c = getChar(); c != EOF_CHAR; c = getChar()) { - addToString(c); - if (c == '?' && peekChar() == '>') { - c = getChar(); // Skip > - addToString(c); - return true; - } - } - - stringBufferTop = 0; // throw away the string in progress - this.string = null; - parser.addError("msg.XML.bad.form"); - return false; - } - - private String getStringFromBuffer() - { - return new String(stringBuffer, 0, stringBufferTop); - } - - private void addToString(int c) - { - int N = stringBufferTop; - if (N == stringBuffer.length) { - char[] tmp = new char[stringBuffer.length * 2]; - System.arraycopy(stringBuffer, 0, tmp, 0, N); - stringBuffer = tmp; - } - stringBuffer[N] = (char)c; - stringBufferTop = N + 1; - } - - private void ungetChar(int c) - { - // can not unread past across line boundary - if (ungetCursor != 0 && ungetBuffer[ungetCursor - 1] == '\n') - Kit.codeBug(); - ungetBuffer[ungetCursor++] = c; - } - - private boolean matchChar(int test) throws IOException - { - int c = getChar(); - if (c == test) { - return true; - } else { - ungetChar(c); - return false; - } - } - - private int peekChar() throws IOException - { - int c = getChar(); - ungetChar(c); - return c; - } - - private int getChar() throws IOException - { - if (ungetCursor != 0) { - return ungetBuffer[--ungetCursor]; - } - - for(;;) { - int c; - if (sourceString != null) { - if (sourceCursor == sourceEnd) { - hitEOF = true; - return EOF_CHAR; - } - c = sourceString.charAt(sourceCursor++); - } else { - if (sourceCursor == sourceEnd) { - if (!fillSourceBuffer()) { - hitEOF = true; - return EOF_CHAR; - } - } - c = sourceBuffer[sourceCursor++]; - } - - if (lineEndChar >= 0) { - if (lineEndChar == '\r' && c == '\n') { - lineEndChar = '\n'; - continue; - } - lineEndChar = -1; - lineStart = sourceCursor - 1; - lineno++; - } - - if (c <= 127) { - if (c == '\n' || c == '\r') { - lineEndChar = c; - c = '\n'; - } - } else { - if (isJSFormatChar(c)) { - continue; - } - if (ScriptRuntime.isJSLineTerminator(c)) { - lineEndChar = c; - c = '\n'; - } - } - return c; - } - } - - private void skipLine() throws IOException - { - // skip to end of line - int c; - while ((c = getChar()) != EOF_CHAR && c != '\n') { } - ungetChar(c); - } - - final int getOffset() - { - int n = sourceCursor - lineStart; - if (lineEndChar >= 0) { --n; } - return n; - } - - final String getLine() - { - if (sourceString != null) { - // String case - int lineEnd = sourceCursor; - if (lineEndChar >= 0) { - --lineEnd; - } else { - for (; lineEnd != sourceEnd; ++lineEnd) { - int c = sourceString.charAt(lineEnd); - if (ScriptRuntime.isJSLineTerminator(c)) { - break; - } - } - } - return sourceString.substring(lineStart, lineEnd); - } else { - // Reader case - int lineLength = sourceCursor - lineStart; - if (lineEndChar >= 0) { - --lineLength; - } else { - // Read until the end of line - for (;; ++lineLength) { - int i = lineStart + lineLength; - if (i == sourceEnd) { - try { - if (!fillSourceBuffer()) { break; } - } catch (IOException ioe) { - // ignore it, we're already displaying an error... - break; - } - // i recalculuation as fillSourceBuffer can move saved - // line buffer and change lineStart - i = lineStart + lineLength; - } - int c = sourceBuffer[i]; - if (ScriptRuntime.isJSLineTerminator(c)) { - break; - } - } - } - return new String(sourceBuffer, lineStart, lineLength); - } - } - - private boolean fillSourceBuffer() throws IOException - { - if (sourceString != null) Kit.codeBug(); - if (sourceEnd == sourceBuffer.length) { - if (lineStart != 0) { - System.arraycopy(sourceBuffer, lineStart, sourceBuffer, 0, - sourceEnd - lineStart); - sourceEnd -= lineStart; - sourceCursor -= lineStart; - lineStart = 0; - } else { - char[] tmp = new char[sourceBuffer.length * 2]; - System.arraycopy(sourceBuffer, 0, tmp, 0, sourceEnd); - sourceBuffer = tmp; - } - } - int n = sourceReader.read(sourceBuffer, sourceEnd, - sourceBuffer.length - sourceEnd); - if (n < 0) { - return false; - } - sourceEnd += n; - return true; - } - - // stuff other than whitespace since start of line - private boolean dirtyLine; - - String regExpFlags; - - // Set this to an inital non-null value so that the Parser has - // something to retrieve even if an error has occured and no - // string is found. Fosters one class of error, but saves lots of - // code. - private String string = ""; - private double number; - - private char[] stringBuffer = new char[128]; - private int stringBufferTop; - private ObjToIntMap allStrings = new ObjToIntMap(50); - - // Room to backtrace from to < on failed match of the last - in <!-- - private final int[] ungetBuffer = new int[3]; - private int ungetCursor; - - private boolean hitEOF = false; - - private int lineStart = 0; - private int lineno; - private int lineEndChar = -1; - - private String sourceString; - private Reader sourceReader; - private char[] sourceBuffer; - private int sourceEnd; - private int sourceCursor; - - // for xml tokenizer - private boolean xmlIsAttribute; - private boolean xmlIsTagContent; - private int xmlOpenTagsCount; - - private Parser parser; -} |