Author: Alex.Kolonitsky
Date: 2009-11-01 11:30:05 -0500 (Sun, 01 Nov 2009)
New Revision: 15793
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java
root/cdk/trunk/plugins/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java
Log:
Code style policy
https://jira.jboss.org/jira/browse/RFPL-195
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/CssCompressor.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -8,29 +8,31 @@
* This code is a port of Isaac Schlueter's cssmin utility.
*/
+
+
package com.yahoo.platform.yui.compressor;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
+
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class CssCompressor {
-
private StringBuffer srcsb = new StringBuffer();
public CssCompressor(Reader in) throws IOException {
+
// Read the stream...
int c;
+
while ((c = in.read()) != -1) {
srcsb.append((char) c);
}
}
- public void compress(Writer out, int linebreakpos)
- throws IOException {
-
+ public void compress(Writer out, int linebreakpos) throws IOException {
Pattern p;
Matcher m;
String css;
@@ -39,10 +41,13 @@
// Remove all comment blocks...
sb = new StringBuffer(srcsb.toString());
+
while ((startIndex = sb.indexOf("/*")) >= 0) {
endIndex = sb.indexOf("*/", startIndex + 2);
- if (endIndex >= startIndex + 2)
+
+ if (endIndex >= startIndex + 2) {
sb.delete(startIndex, endIndex + 2);
+ }
}
css = sb.toString();
@@ -56,11 +61,14 @@
sb = new StringBuffer();
p = Pattern.compile("(^|\\})(([^\\{:])+:)+([^\\{]*\\{)");
m = p.matcher(css);
+
while (m.find()) {
String s = m.group();
+
s = s.replaceAll(":", "___PSEUDOCLASSCOLON___");
m.appendReplacement(sb, s);
}
+
m.appendTail(sb);
css = sb.toString();
css = css.replaceAll("\\s+([!{};:>+\\(\\)\\],])", "$1");
@@ -79,6 +87,7 @@
css = css.replaceAll(":0 0 0 0;", ":0;");
css = css.replaceAll(":0 0 0;", ":0;");
css = css.replaceAll(":0 0;", ":0;");
+
// Replace background-position:0; with background-position:0 0;
css = css.replaceAll("background-position:0;",
"background-position:0 0;");
@@ -90,40 +99,49 @@
p = Pattern.compile("rgb\\s*\\(\\s*([0-9,\\s]+)\\s*\\)");
m = p.matcher(css);
sb = new StringBuffer();
+
while (m.find()) {
String[] rgbcolors = m.group(1).split(",");
StringBuffer hexcolor = new StringBuffer("#");
+
for (int i = 0; i < rgbcolors.length; i++) {
int val = Integer.parseInt(rgbcolors[i]);
+
if (val < 16) {
hexcolor.append("0");
}
+
hexcolor.append(Integer.toHexString(val));
}
+
m.appendReplacement(sb, hexcolor.toString());
}
+
m.appendTail(sb);
css = sb.toString();
// Shorten colors from #AABBCC to #ABC. Note that we want to make sure
// the color is not preceded by either ", " or =. Indeed, the property
- // filter: chroma(color="#FFFFFF");
+ // filter: chroma(color="#FFFFFF");
// would become
- // filter: chroma(color="#FFF");
+ // filter: chroma(color="#FFF");
// which makes the filter break in IE.
- p =
Pattern.compile("([^\"'=\\s])(\\s*)#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])");
+ p = Pattern.compile(
+
"([^\"'=\\s])(\\s*)#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])");
m = p.matcher(css);
sb = new StringBuffer();
+
while (m.find()) {
+
// Test for AABBCC pattern
- if (m.group(3).equalsIgnoreCase(m.group(4)) &&
- m.group(5).equalsIgnoreCase(m.group(6)) &&
- m.group(7).equalsIgnoreCase(m.group(8))) {
+ if (m.group(3).equalsIgnoreCase(m.group(4)) &&
m.group(5).equalsIgnoreCase(m.group(6))
+ && m.group(7).equalsIgnoreCase(m.group(8))) {
m.appendReplacement(sb, m.group(1) + m.group(2) + "#" +
m.group(3) + m.group(5) + m.group(7));
} else {
m.appendReplacement(sb, m.group());
}
}
+
m.appendTail(sb);
css = sb.toString();
@@ -131,14 +149,18 @@
css = css.replaceAll("[^\\}]+\\{;\\}", "");
if (linebreakpos >= 0) {
+
// Some source control tools don't like it when files containing lines
longer
// than, say 8000 characters, are checked in. The linebreak option is used
in
// that case to split long lines after a specific column.
int i = 0;
int linestartpos = 0;
+
sb = new StringBuffer(css);
+
while (i < sb.length()) {
char c = sb.charAt(i++);
+
if (c == '}' && i - linestartpos > linebreakpos) {
sb.insert(i, '\n');
linestartpos = i;
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptCompressor.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -6,6 +6,8 @@
*
http://developer.yahoo.net/yui/license.txt
*/
+
+
package com.yahoo.platform.yui.compressor;
import org.mozilla.javascript.*;
@@ -13,17 +15,18 @@
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
+
import java.util.*;
public class JavaScriptCompressor {
-
+ private static final int BUILDING_SYMBOL_TREE = 1;
+ private static final int CHECKING_SYMBOL_TREE = 2;
+ static final Set builtin = new HashSet();
+ static final Map literals = new Hashtable();
static final ArrayList ones;
+ static final ArrayList threes;
static final ArrayList twos;
- static final ArrayList threes;
- static final Set builtin = new HashSet();
- static final Map literals = new Hashtable();
-
static {
// This list contains all the 3 characters or less built-in global
@@ -31,22 +34,32 @@
// see anything missing.
builtin.add("NaN");
builtin.add("top");
+ ones = new ArrayList();
- ones = new ArrayList();
- for (char c = 'A'; c <= 'Z'; c++)
+ for (char c = 'A'; c <= 'Z'; c++) {
ones.add(Character.toString(c));
- for (char c = 'a'; c <= 'z'; c++)
+ }
+
+ for (char c = 'a'; c <= 'z'; c++) {
ones.add(Character.toString(c));
+ }
twos = new ArrayList();
+
for (int i = 0; i < ones.size(); i++) {
String one = (String) ones.get(i);
- for (char c = 'A'; c <= 'Z'; c++)
+
+ for (char c = 'A'; c <= 'Z'; c++) {
twos.add(one + Character.toString(c));
- for (char c = 'a'; c <= 'z'; c++)
+ }
+
+ for (char c = 'a'; c <= 'z'; c++) {
twos.add(one + Character.toString(c));
- for (char c = '0'; c <= '9'; c++)
+ }
+
+ for (char c = '0'; c <= '9'; c++) {
twos.add(one + Character.toString(c));
+ }
}
// Remove two-letter JavaScript reserved words and built-in globals...
@@ -56,16 +69,22 @@
twos.remove("if");
twos.remove("in");
twos.removeAll(builtin);
+ threes = new ArrayList();
- threes = new ArrayList();
for (int i = 0; i < twos.size(); i++) {
String two = (String) twos.get(i);
- for (char c = 'A'; c <= 'Z'; c++)
+
+ for (char c = 'A'; c <= 'Z'; c++) {
threes.add(two + Character.toString(c));
- for (char c = 'a'; c <= 'z'; c++)
+ }
+
+ for (char c = 'a'; c <= 'z'; c++) {
threes.add(two + Character.toString(c));
- for (char c = '0'; c <= '9'; c++)
+ }
+
+ for (char c = '0'; c <= '9'; c++) {
threes.add(two + Character.toString(c));
+ }
}
// Remove three-letter JavaScript reserved words and built-in globals...
@@ -79,7 +98,6 @@
// That's up to ((26+26)*(1+(26+26+10)))*(1+(26+26+10))-8
// (206,380 symbols per scope)
-
// The following list comes from org/mozilla/javascript/Decompiler.java...
literals.put(new Integer(Token.GET), "get ");
literals.put(new Integer(Token.SET), "set ");
@@ -169,75 +187,106 @@
literals.put(new Integer(Token.XMLATTR), "@");
}
+ private Stack scopes = new Stack();
+ private Hashtable indexedScopes = new Hashtable();
+ private ScriptOrFnScope globalScope = new ScriptOrFnScope(-1, null);
+ private int braceNesting;
+ private ErrorReporter logger;
+ private int mode;
+ private boolean munge;
+ private int offset;
+ private ArrayList srctokens, tokens;
+ private boolean warn;
+
+ public JavaScriptCompressor(Reader in, ErrorReporter reporter) throws IOException,
EvaluatorException {
+ this.logger = reporter;
+ this.srctokens = parse(in, reporter);
+ }
+
private static int countChar(String haystack, char needle) {
int idx = 0;
int count = 0;
int length = haystack.length();
+
while (idx < length) {
char c = haystack.charAt(idx++);
+
if (c == needle) {
count++;
}
}
+
return count;
}
private static int printSourceString(String source, int offset, 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);
+
sb.append(str);
}
+
return offset + length;
}
- private static int printSourceNumber(String source,
- int offset, StringBuffer sb) {
+ 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) {
number = source.charAt(offset);
}
+
++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 |= (long) 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 static ArrayList parse(Reader in, ErrorReporter reporter)
- throws IOException, EvaluatorException {
-
+ private static ArrayList parse(Reader in, ErrorReporter reporter) throws IOException,
EvaluatorException {
CompilerEnvirons env = new CompilerEnvirons();
Parser parser = new Parser(env, reporter);
+
parser.parse(in, null, 1);
+
String source = parser.getEncodedSource();
-
int offset = 0;
int length = source.length();
ArrayList tokens = new ArrayList();
@@ -245,28 +294,32 @@
while (offset < length) {
int tt = source.charAt(offset++);
+
switch (tt) {
-
- case Token.IECC:
- case Token.NAME:
- case Token.REGEXP:
- case Token.STRING:
+ case Token.IECC :
+ case Token.NAME :
+ case Token.REGEXP :
+ case Token.STRING :
sb.setLength(0);
offset = printSourceString(source, offset, sb);
tokens.add(new JavaScriptToken(tt, sb.toString()));
+
break;
- case Token.NUMBER:
+ case Token.NUMBER :
sb.setLength(0);
offset = printSourceNumber(source, offset, sb);
tokens.add(new JavaScriptToken(tt, sb.toString()));
+
break;
- default:
+ default :
String literal = (String) literals.get(new Integer(tt));
+
if (literal != null) {
tokens.add(new JavaScriptToken(tt, literal));
}
+
break;
}
}
@@ -275,7 +328,6 @@
}
private static ArrayList processStringLiterals(ArrayList tokens, boolean merge) {
-
String tv;
int i, length;
ArrayList result = new ArrayList();
@@ -283,49 +335,52 @@
// Concatenate string literals that are being appended wherever
// it is safe to do so. Note that we take care of the case:
- // "a" + "b".toUpperCase()
-
+ // "a" + "b".toUpperCase()
for (i = 0, length = tokens.size(); i < length; i++) {
token = (JavaScriptToken) tokens.get(i);
+
switch (token.getType()) {
-
- case Token.ADD:
+ case Token.ADD :
if (merge) {
if (i > 0 && i < length) {
prevToken = (JavaScriptToken) result.get(result.size() - 1);
nextToken = (JavaScriptToken) tokens.get(i + 1);
- if (prevToken.getType() == Token.STRING &&
nextToken.getType() == Token.STRING &&
- (i == length - 1 || ((JavaScriptToken) tokens.get(i +
2)).getType() != Token.DOT)) {
- result.set(result.size() - 1, new
JavaScriptToken(Token.STRING,
- prevToken.getValue() + nextToken.getValue()));
+
+ if (prevToken.getType() == Token.STRING &&
nextToken.getType() == Token.STRING
+ && (i == length - 1
+ || ((JavaScriptToken) tokens.get(i +
2)).getType() != Token.DOT)) {
+ result.set(result.size() - 1,
+ new JavaScriptToken(Token.STRING,
+ prevToken.getValue() +
nextToken.getValue()));
i++; // not a good practice, but oh well...
+
break;
}
}
}
- /* FALLSTHROUGH */
+ /* FALLSTHROUGH */
+ default :
+ result.add(token);
- default:
- result.add(token);
break;
}
}
// Second pass...
-
for (i = 0, length = result.size(); i < length; i++) {
token = (JavaScriptToken) result.get(i);
+
if (token.getType() == Token.STRING) {
tv = token.getValue();
// Finally, add the quoting characters and escape the string. We use
// the quoting character that minimizes the amount of escaping to save
// a few additional bytes.
-
char quotechar;
int singleQuoteCount = countChar(tv, '\'');
int doubleQuoteCount = countChar(tv, '"');
+
if (doubleQuoteCount <= singleQuoteCount) {
quotechar = '"';
} else {
@@ -335,13 +390,12 @@
tv = quotechar + escapeString(tv, quotechar) + quotechar;
// String concatenation transforms the old script scheme:
- // '<scr'+'ipt ...><'+'/script>'
+ // '<scr'+'ipt ...><'+'/script>'
// into the following:
- // '<script ...></script>'
+ // '<script ...></script>'
// which breaks if this code is embedded inside an HTML document.
// Since this is not the right way to do this, let's fix the code by
// transforming all "</script" into
"<\/script"
-
if (tv.indexOf("</script") >= 0) {
tv = tv.replaceAll("<\\/script",
"<\\\\/script");
}
@@ -355,7 +409,6 @@
// Add necessary escaping that was removed in Rhino's tokenizer.
private static String escapeString(String s, char quotechar) {
-
assert quotechar == '"' || quotechar == '\'';
if (s == null) {
@@ -363,51 +416,29 @@
}
StringBuffer sb = new StringBuffer();
+
for (int i = 0, L = s.length(); i < L; i++) {
int c = s.charAt(i);
+
if (c == quotechar) {
sb.append("\\");
}
+
sb.append((char) c);
}
return sb.toString();
}
- private ErrorReporter logger;
-
- private boolean munge;
- private boolean warn;
-
- private static final int BUILDING_SYMBOL_TREE = 1;
- private static final int CHECKING_SYMBOL_TREE = 2;
-
- private int mode;
- private int offset;
- private int braceNesting;
- private ArrayList srctokens, tokens;
- private Stack scopes = new Stack();
- private ScriptOrFnScope globalScope = new ScriptOrFnScope(-1, null);
- private Hashtable indexedScopes = new Hashtable();
-
- public JavaScriptCompressor(Reader in, ErrorReporter reporter)
- throws IOException, EvaluatorException {
-
- this.logger = reporter;
- this.srctokens = parse(in, reporter);
- }
-
- public void compress(Writer out, int linebreak, boolean munge, boolean warn,
- boolean preserveAllSemiColons, boolean preserveStringLiterals)
+ public void compress(Writer out, int linebreak, boolean munge, boolean warn, boolean
preserveAllSemiColons,
+ boolean preserveStringLiterals)
throws IOException {
-
this.munge = munge;
this.warn = warn;
-
this.tokens = processStringLiterals(this.srctokens, !preserveStringLiterals);
-
buildSymbolTree();
mungeSymboltree();
+
StringBuffer sb = printSymbolTree(linebreak, preserveAllSemiColons);
out.write(sb.toString());
@@ -440,13 +471,17 @@
*/
private JavaScriptIdentifier getIdentifier(String symbol, ScriptOrFnScope scope) {
JavaScriptIdentifier identifier;
+
while (scope != null) {
identifier = scope.getIdentifier(symbol);
+
if (identifier != null) {
return identifier;
}
+
scope = scope.getParentScope();
}
+
return null;
}
@@ -459,6 +494,7 @@
assert scope != null;
if (scope == globalScope) {
+
// The global scope does not get obfuscated,
// so we don't need to worry about it...
return;
@@ -475,17 +511,25 @@
private String getDebugString(int max) {
assert max > 0;
+
StringBuffer result = new StringBuffer();
int start = Math.max(offset - max, 0);
int end = Math.min(offset + max, tokens.size());
+
for (int i = start; i < end; i++) {
JavaScriptToken token = (JavaScriptToken) tokens.get(i);
- if (i == offset)
+
+ if (i == offset) {
result.append(" ---> ");
+ }
+
result.append(token.getValue());
- if (i == offset)
+
+ if (i == offset) {
result.append(" <--- ");
+ }
}
+
return result.toString();
}
@@ -494,33 +538,38 @@
if (showDebugString) {
message = message + "\n" + getDebugString(10);
}
+
logger.warning(message, null, -1, null, -1);
}
}
private void parseFunctionDeclaration() {
-
String symbol;
JavaScriptToken token;
ScriptOrFnScope currentScope, fnScope;
JavaScriptIdentifier identifier;
currentScope = getCurrentScope();
+ token = consumeToken();
- token = consumeToken();
if (token.getType() == Token.NAME) {
if (mode == BUILDING_SYMBOL_TREE) {
+
// Get the name of the function and declare it in the current scope.
symbol = token.getValue();
+
if (currentScope.getIdentifier(symbol) != null) {
warn("[WARNING] The function " + symbol + " has
already been declared in the same scope...", true);
}
+
currentScope.declareIdentifier(symbol);
}
+
token = consumeToken();
}
assert token.getType() == Token.LP;
+
if (mode == BUILDING_SYMBOL_TREE) {
fnScope = new ScriptOrFnScope(braceNesting, currentScope);
indexedScopes.put(new Integer(offset), fnScope);
@@ -530,16 +579,20 @@
// Parse function arguments.
int argpos = 0;
+
while ((token = consumeToken()).getType() != Token.RP) {
- assert token.getType() == Token.NAME ||
- token.getType() == Token.COMMA;
+ assert token.getType() == Token.NAME || token.getType() == Token.COMMA;
+
if (token.getType() == Token.NAME && mode == BUILDING_SYMBOL_TREE) {
symbol = token.getValue();
identifier = fnScope.declareIdentifier(symbol);
+
if (symbol.equals("$super") && argpos == 0) {
+
// Exception for Prototype 1.6...
identifier.preventMunging();
}
+
argpos++;
}
}
@@ -547,10 +600,10 @@
token = consumeToken();
assert token.getType() == Token.LC;
braceNesting++;
+ token = getToken(0);
- token = getToken(0);
- if (token.getType() == Token.STRING &&
- getToken(1).getType() == Token.SEMI) {
+ if (token.getType() == Token.STRING && getToken(1).getType() ==
Token.SEMI) {
+
// This is a hint. Hints are empty statements that look like
// "localvar1:nomunge, localvar2:nomunge"; They allow developers
// to prevent specific symbols from getting obfuscated (some heretic
@@ -560,26 +613,36 @@
// of a hint. However, in the future, the right hand side may contain
// other values.
consumeToken();
+
String hints = token.getValue();
+
// Remove the leading and trailing quotes...
hints = hints.substring(1, hints.length() - 1).trim();
+
StringTokenizer st1 = new StringTokenizer(hints, ",");
+
while (st1.hasMoreTokens()) {
String hint = st1.nextToken();
int idx = hint.indexOf(':');
+
if (idx <= 0 || idx >= hint.length() - 1) {
if (mode == BUILDING_SYMBOL_TREE) {
+
// No need to report the error twice, hence the test...
warn("[WARNING] Invalid hint syntax: " + hint, true);
}
+
break;
}
+
String variableName = hint.substring(0, idx).trim();
String variableType = hint.substring(idx + 1).trim();
+
if (mode == BUILDING_SYMBOL_TREE) {
fnScope.addHint(variableName, variableType);
} else if (mode == CHECKING_SYMBOL_TREE) {
identifier = fnScope.getIdentifier(variableName);
+
if (identifier != null) {
if (variableType.equals("nomunge")) {
identifier.preventMunging();
@@ -597,7 +660,6 @@
}
private void parseCatch() {
-
String symbol;
JavaScriptToken token;
ScriptOrFnScope currentScope;
@@ -609,11 +671,11 @@
assert token.getType() == Token.LP;
token = consumeToken();
assert token.getType() == Token.NAME;
-
symbol = token.getValue();
currentScope = getCurrentScope();
if (mode == BUILDING_SYMBOL_TREE) {
+
// We must declare the exception identifier in the containing function
// scope to avoid errors related to the obfuscation process. No need to
// display a warning if the symbol was already declared here...
@@ -632,95 +694,93 @@
// Parse the expression until we encounter a comma or a semi-colon
// in the same brace nesting, bracket nesting and paren nesting.
// Parse functions if any...
-
String symbol;
JavaScriptToken token;
ScriptOrFnScope currentScope;
JavaScriptIdentifier identifier;
-
int expressionBraceNesting = braceNesting;
int bracketNesting = 0;
int parensNesting = 0;
-
int length = tokens.size();
while (offset < length) {
-
token = consumeToken();
currentScope = getCurrentScope();
switch (token.getType()) {
-
- case Token.SEMI:
- case Token.COMMA:
- if (braceNesting == expressionBraceNesting &&
- bracketNesting == 0 &&
- parensNesting == 0) {
+ case Token.SEMI :
+ case Token.COMMA :
+ if (braceNesting == expressionBraceNesting && bracketNesting
== 0 && parensNesting == 0) {
return;
}
+
break;
- case Token.FUNCTION:
+ case Token.FUNCTION :
parseFunctionDeclaration();
+
break;
- case Token.LC:
+ case Token.LC :
braceNesting++;
+
break;
- case Token.RC:
+ case Token.RC :
braceNesting--;
assert braceNesting >= expressionBraceNesting;
+
break;
- case Token.LB:
+ case Token.LB :
bracketNesting++;
+
break;
- case Token.RB:
+ case Token.RB :
bracketNesting--;
+
break;
- case Token.LP:
+ case Token.LP :
parensNesting++;
+
break;
- case Token.RP:
+ case Token.RP :
parensNesting--;
+
break;
- case Token.IECC:
+ case Token.IECC :
if (mode == BUILDING_SYMBOL_TREE) {
protectScopeFromObfuscation(currentScope);
- warn("[WARNING] Using JScript conditional comments is not
recommended..." + (munge ? "\n[INFO] Using JSCript conditional comments reduces
the level of compression!" : ""), true);
+ warn("[WARNING] Using JScript conditional comments is not
recommended..."
+ + (munge
+ ? "\n[INFO] Using JSCript conditional comments
reduces the level of compression!"
+ : ""), true);
}
+
break;
- case Token.NAME:
+ case Token.NAME :
symbol = token.getValue();
if (mode == BUILDING_SYMBOL_TREE) {
-
if (symbol.equals("eval")) {
-
protectScopeFromObfuscation(currentScope);
- warn("[WARNING] Using 'eval' is not
recommended..." + (munge ? "\n[INFO] Using 'eval' reduces the level of
compression!" : ""), true);
-
+ warn("[WARNING] Using 'eval' is not
recommended..."
+ + (munge ? "\n[INFO] Using 'eval' reduces
the level of compression!" : ""), true);
}
-
} else if (mode == CHECKING_SYMBOL_TREE) {
-
- if ((offset < 2 ||
- (getToken(-2).getType() != Token.DOT &&
- getToken(-2).getType() != Token.GET &&
- getToken(-2).getType() != Token.SET)) &&
- getToken(0).getType() != Token.OBJECTLIT) {
-
+ if ((offset < 2 || (getToken(-2).getType() != Token.DOT
&& getToken(
+ -2).getType() != Token.GET &&
getToken(-2).getType() != Token.SET)) && getToken(
+ 0).getType() != Token.OBJECTLIT) {
identifier = getIdentifier(symbol, currentScope);
if (identifier == null) {
+ if (symbol.length() <= 3 &&
!builtin.contains(symbol)) {
- if (symbol.length() <= 3 &&
!builtin.contains(symbol)) {
// Here, we found an undeclared and un-namespaced
symbol that is
// 3 characters or less in length. Declare it in the
global scope.
// We don't need to declare longer symbols since
they won't cause
@@ -728,134 +788,137 @@
globalScope.declareIdentifier(symbol);
warn("[WARNING] Found an undeclared symbol:
" + symbol, true);
}
-
} else {
-
identifier.incrementRefcount();
}
}
}
+
break;
}
}
}
private void parseScope(ScriptOrFnScope scope) {
-
String symbol;
JavaScriptToken token;
JavaScriptIdentifier identifier;
-
int length = tokens.size();
enterScope(scope);
while (offset < length) {
-
token = consumeToken();
switch (token.getType()) {
+ case Token.VAR :
+ case Token.CONST :
- case Token.VAR:
- case Token.CONST:
-
// The var keyword is followed by at least one symbol name.
// If several symbols follow, they are comma separated.
- for (; ;) {
+ for (;;) {
token = consumeToken();
-
assert token.getType() == Token.NAME;
if (mode == BUILDING_SYMBOL_TREE) {
symbol = token.getValue();
+
if (scope.getIdentifier(symbol) == null) {
scope.declareIdentifier(symbol);
} else {
- warn("[WARNING] The variable " + symbol +
" has already been declared in the same scope...", true);
+ warn("[WARNING] The variable " + symbol
+ + " has already been declared in the same
scope...", true);
}
}
token = getToken(0);
+ assert token.getType() == Token.SEMI || token.getType() ==
Token.ASSIGN
+ || token.getType() == Token.COMMA || token.getType() ==
Token.IN;
- assert token.getType() == Token.SEMI ||
- token.getType() == Token.ASSIGN ||
- token.getType() == Token.COMMA ||
- token.getType() == Token.IN;
-
if (token.getType() == Token.IN) {
break;
} else {
parseExpression();
token = getToken(-1);
+
if (token.getType() == Token.SEMI) {
break;
}
}
}
+
break;
- case Token.FUNCTION:
+ case Token.FUNCTION :
parseFunctionDeclaration();
+
break;
- case Token.LC:
+ case Token.LC :
braceNesting++;
+
break;
- case Token.RC:
+ case Token.RC :
braceNesting--;
assert braceNesting >= scope.getBraceNesting();
+
if (braceNesting == scope.getBraceNesting()) {
leaveCurrentScope();
+
return;
}
+
break;
- case Token.WITH:
+ case Token.WITH :
if (mode == BUILDING_SYMBOL_TREE) {
+
// Inside a 'with' block, it is impossible to figure out
// statically whether a symbol is a local variable or an
// object member. As a consequence, the only thing we can
// do is turn the obfuscation off for the highest scope
// containing the 'with' block.
protectScopeFromObfuscation(scope);
- warn("[WARNING] Using 'with' is not
recommended" + (munge ? "(and it reduces the level of compression)" :
""), true);
+ warn("[WARNING] Using 'with' is not
recommended"
+ + (munge ? "(and it reduces the level of
compression)" : ""), true);
}
+
break;
- case Token.CATCH:
+ case Token.CATCH :
parseCatch();
+
break;
- case Token.IECC:
+ case Token.IECC :
if (mode == BUILDING_SYMBOL_TREE) {
protectScopeFromObfuscation(scope);
- warn("[WARNING] Using JScript conditional comments is not
recommended..." + (munge ? "\n[INFO] Using JSCript conditional comments reduces
the level of compression!" : ""), true);
+ warn("[WARNING] Using JScript conditional comments is not
recommended..."
+ + (munge
+ ? "\n[INFO] Using JSCript conditional comments
reduces the level of compression!"
+ : ""), true);
}
+
break;
- case Token.NAME:
+ case Token.NAME :
symbol = token.getValue();
if (mode == BUILDING_SYMBOL_TREE) {
-
if (symbol.equals("eval")) {
-
protectScopeFromObfuscation(scope);
- warn("[WARNING] Using 'eval' is not
recommended..." + (munge ? "\n[INFO] Using 'eval' reduces the level of
compression!" : ""), true);
-
+ warn("[WARNING] Using 'eval' is not
recommended..."
+ + (munge ? "\n[INFO] Using 'eval' reduces
the level of compression!" : ""), true);
}
-
} else if (mode == CHECKING_SYMBOL_TREE) {
-
- if ((offset < 2 || getToken(-2).getType() != Token.DOT)
&&
- getToken(0).getType() != Token.OBJECTLIT) {
-
+ if ((offset < 2 || getToken(-2).getType() != Token.DOT)
+ && getToken(0).getType() != Token.OBJECTLIT) {
identifier = getIdentifier(symbol, scope);
if (identifier == null) {
+ if (symbol.length() <= 3 &&
!builtin.contains(symbol)) {
- if (symbol.length() <= 3 &&
!builtin.contains(symbol)) {
// Here, we found an undeclared and un-namespaced
symbol that is
// 3 characters or less in length. Declare it in the
global scope.
// We don't need to declare longer symbols since
they won't cause
@@ -863,13 +926,12 @@
globalScope.declareIdentifier(symbol);
warn("[WARNING] Found an undeclared symbol:
" + symbol, true);
}
-
} else {
-
identifier.incrementRefcount();
}
}
}
+
break;
}
}
@@ -886,7 +948,6 @@
}
private void mungeSymboltree() {
-
if (!munge) {
return;
}
@@ -895,12 +956,12 @@
// and un-namespaced global symbols that are 3 characters or less
// in length. Here is an example:
//
- // var declaredGlobalVar;
+ // var declaredGlobalVar;
//
- // function declaredGlobalFn() {
- // var localvar;
- // localvar = abc; // abc is an undeclared global symbol
- // }
+ // function declaredGlobalFn() {
+ // var localvar;
+ // localvar = abc; // abc is an undeclared global symbol
+ // }
//
// In the example above, there is a slim chance that localvar may be
// munged to 'abc', conflicting with the undeclared global symbol
@@ -911,7 +972,6 @@
//
// Note: Since we go through all the tokens to do this, we also use
// the opportunity to count how many times each identifier is used.
-
offset = 0;
braceNesting = 0;
scopes.clear();
@@ -920,9 +980,7 @@
globalScope.munge();
}
- private StringBuffer printSymbolTree(int linebreakpos, boolean
preserveAllSemiColons)
- throws IOException {
-
+ private StringBuffer printSymbolTree(int linebreakpos, boolean preserveAllSemiColons)
throws IOException {
offset = 0;
braceNesting = 0;
scopes.clear();
@@ -931,103 +989,112 @@
JavaScriptToken token;
ScriptOrFnScope currentScope;
JavaScriptIdentifier identifier;
-
int length = tokens.size();
StringBuffer result = new StringBuffer();
-
int linestartpos = 0;
enterScope(globalScope);
while (offset < length) {
-
token = consumeToken();
symbol = token.getValue();
currentScope = getCurrentScope();
switch (token.getType()) {
-
- case Token.NAME:
-
- if (offset >= 2 && getToken(-2).getType() == Token.DOT ||
- getToken(0).getType() == Token.OBJECTLIT) {
-
+ case Token.NAME :
+ if (offset >= 2 && getToken(-2).getType() == Token.DOT
+ || getToken(0).getType() == Token.OBJECTLIT) {
result.append(symbol);
-
} else {
+ identifier = getIdentifier(symbol, currentScope);
- identifier = getIdentifier(symbol, currentScope);
if (identifier != null) {
if (identifier.getMungedValue() != null) {
result.append(identifier.getMungedValue());
} else {
result.append(symbol);
}
+
if (currentScope != globalScope &&
identifier.getRefcount() == 0) {
- warn("[WARNING] The symbol " + symbol + "
is declared but is apparently never used.\nThis code can probably be written in a more
efficient way.", true);
+ warn("[WARNING] The symbol " + symbol
+ + " is declared but is apparently never
used.\nThis code can probably be written in a more efficient way.", true);
}
} else {
result.append(symbol);
}
}
+
break;
- case Token.REGEXP:
- case Token.NUMBER:
- case Token.STRING:
+ case Token.REGEXP :
+ case Token.NUMBER :
+ case Token.STRING :
result.append(symbol);
+
break;
- case Token.ADD:
- case Token.SUB:
+ case Token.ADD :
+ case Token.SUB :
result.append((String) literals.get(new Integer(token.getType())));
+
if (offset < length) {
token = getToken(0);
- if (token.getType() == Token.INC ||
- token.getType() == Token.DEC ||
- token.getType() == Token.ADD ||
- token.getType() == Token.DEC) {
+
+ if (token.getType() == Token.INC || token.getType() == Token.DEC
+ || token.getType() == Token.ADD || token.getType() ==
Token.DEC) {
+
// Handle the case x +/- ++/-- y
// We must keep a white space here. Otherwise, x +++ y would
be
// interpreted as x ++ + y by the compiler, which is a bug
(due
// to the implicit assignment being done on the wrong
variable)
result.append(" ");
- } else if (token.getType() == Token.POS &&
getToken(-1).getType() == Token.ADD ||
- token.getType() == Token.NEG &&
getToken(-1).getType() == Token.SUB) {
+ } else if (token.getType() == Token.POS &&
getToken(-1).getType() == Token.ADD
+ || token.getType() == Token.NEG &&
getToken(-1).getType() == Token.SUB) {
+
// Handle the case x + + y and x - - y
result.append(" ");
}
}
+
break;
- case Token.FUNCTION:
+ case Token.FUNCTION :
result.append("function");
token = consumeToken();
+
if (token.getType() == Token.NAME) {
result.append(" ");
symbol = token.getValue();
identifier = getIdentifier(symbol, currentScope);
assert identifier != null;
+
if (identifier.getMungedValue() != null) {
result.append(identifier.getMungedValue());
} else {
result.append(symbol);
}
+
if (currentScope != globalScope &&
identifier.getRefcount() == 0) {
- warn("[WARNING] The symbol " + symbol + " is
declared but is apparently never used.\nThis code can probably be written in a more
efficient way.", true);
+ warn("[WARNING] The symbol " + symbol
+ + " is declared but is apparently never used.\nThis
code can probably be written in a more efficient way.", true);
}
+
token = consumeToken();
}
+
assert token.getType() == Token.LP;
result.append("(");
currentScope = (ScriptOrFnScope) indexedScopes.get(new
Integer(offset));
enterScope(currentScope);
+
while ((token = consumeToken()).getType() != Token.RP) {
assert token.getType() == Token.NAME || token.getType() ==
Token.COMMA;
+
if (token.getType() == Token.NAME) {
symbol = token.getValue();
identifier = getIdentifier(symbol, currentScope);
assert identifier != null;
+
if (identifier.getMungedValue() != null) {
result.append(identifier.getMungedValue());
} else {
@@ -1037,111 +1104,137 @@
result.append(",");
}
}
+
result.append(")");
token = consumeToken();
assert token.getType() == Token.LC;
result.append("{");
braceNesting++;
token = getToken(0);
+
if (token.getType() == Token.STRING) {
+
// This is a hint. Skip it!
consumeToken();
token = getToken(0);
assert token.getType() == Token.SEMI;
consumeToken();
}
+
break;
- case Token.RETURN:
+ case Token.RETURN :
result.append("return");
+
// No space needed after 'return' when followed
// by '(', '[', '{', a string or a regexp.
if (offset < length) {
token = getToken(0);
- if (token.getType() != Token.LP &&
- token.getType() != Token.LB &&
- token.getType() != Token.LC &&
- token.getType() != Token.STRING &&
- token.getType() != Token.REGEXP) {
+
+ if (token.getType() != Token.LP && token.getType() !=
Token.LB && token.getType() != Token.LC
+ && token.getType() != Token.STRING &&
token.getType() != Token.REGEXP) {
result.append(" ");
}
}
+
break;
- case Token.CASE:
+ case Token.CASE :
result.append("case");
+
// White-space needed after 'case' when not followed by a
string.
if (offset < length && getToken(0).getType() !=
Token.STRING) {
result.append(" ");
}
+
break;
- case Token.THROW:
+ case Token.THROW :
+
// White-space needed after 'throw' when not followed by a
string.
result.append("throw");
+
if (offset < length && getToken(0).getType() !=
Token.STRING) {
result.append(" ");
}
+
break;
- case Token.BREAK:
+ case Token.BREAK :
result.append("break");
+
if (offset < length && getToken(0).getType() !=
Token.SEMI) {
+
// If 'break' is not followed by a semi-colon, it must
be
// followed by a label, hence the need for a white space.
result.append(" ");
}
+
break;
- case Token.CONTINUE:
+ case Token.CONTINUE :
result.append("continue");
+
if (offset < length && getToken(0).getType() !=
Token.SEMI) {
+
// If 'continue' is not followed by a semi-colon, it must
be
// followed by a label, hence the need for a white space.
result.append(" ");
}
+
break;
- case Token.LC:
+ case Token.LC :
result.append("{");
braceNesting++;
+
break;
- case Token.RC:
+ case Token.RC :
result.append("}");
braceNesting--;
assert braceNesting >= currentScope.getBraceNesting();
+
if (braceNesting == currentScope.getBraceNesting()) {
leaveCurrentScope();
}
+
break;
- case Token.SEMI:
+ case Token.SEMI :
+
// No need to output a semi-colon if the next character is a
right-curly...
- if (preserveAllSemiColons || offset < length &&
getToken(0).getType() != Token.RC)
+ if (preserveAllSemiColons || offset < length &&
getToken(0).getType() != Token.RC) {
result.append(";");
+ }
+
if (linebreakpos >= 0 && result.length() - linestartpos
> linebreakpos) {
+
// Some source control tools don't like it when files
containing lines longer
// than, say 8000 characters, are checked in. The linebreak
option is used in
// that case to split long lines after a specific column.
result.append("\n");
linestartpos = result.length();
}
+
break;
- case Token.IECC:
+ case Token.IECC :
result.append("/*");
result.append(symbol);
result.append("*/");
+
break;
- default:
+ default :
String literal = (String) literals.get(new
Integer(token.getType()));
+
if (literal != null) {
result.append(literal);
} else {
warn("[WARNING] This symbol cannot be printed: " +
symbol, true);
}
+
break;
}
}
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptErrorReporter.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -6,6 +6,8 @@
*
http://developer.yahoo.net/yui/license.txt
*/
+
+
package com.yahoo.platform.yui.compressor;
import org.mozilla.javascript.ErrorReporter;
@@ -14,35 +16,32 @@
import java.io.PrintStream;
class JavaScriptErrorReporter implements ErrorReporter {
-
- private boolean reportWarnings;
private PrintStream err;
+ private boolean reportWarnings;
JavaScriptErrorReporter(PrintStream err, boolean reportWarnings) {
this.err = err;
this.reportWarnings = reportWarnings;
}
- public void warning(String message, String sourceName,
- int line, String lineSource, int lineOffset) {
+ public void warning(String message, String sourceName, int line, String lineSource,
int lineOffset) {
if (reportWarnings) {
reportMessage(message, sourceName, line, lineSource, lineOffset);
}
}
- public EvaluatorException runtimeError(String message, String sourceName,
- int line, String lineSource, int lineOffset) {
+ public EvaluatorException runtimeError(String message, String sourceName, int line,
String lineSource,
+ int lineOffset) {
error(message, sourceName, line, lineSource, lineOffset);
+
return new EvaluatorException(message);
}
- public void error(String message, String sourceName,
- int line, String lineSource, int lineOffset) {
+ public void error(String message, String sourceName, int line, String lineSource, int
lineOffset) {
reportMessage(message, sourceName, line, lineSource, lineOffset);
}
- private void reportMessage(String message, String sourceName,
- int line, String lineSource, int lineOffset) {
+ private void reportMessage(String message, String sourceName, int line, String
lineSource, int lineOffset) {
if (line < 0) {
if (message.length() == 0) {
err.println("An unknown error occurred...");
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptIdentifier.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -6,6 +6,8 @@
*
http://developer.yahoo.net/yui/license.txt
*/
+
+
package com.yahoo.platform.yui.compressor;
import org.mozilla.javascript.Token;
@@ -14,11 +16,10 @@
* JavaScriptIdentifier represents a variable/function identifier.
*/
class JavaScriptIdentifier extends JavaScriptToken {
-
private int refcount = 0;
+ private boolean markedForMunging = true;
+ private ScriptOrFnScope declaredScope;
private String mungedValue;
- private ScriptOrFnScope declaredScope;
- private boolean markedForMunging = true;
JavaScriptIdentifier(String value, ScriptOrFnScope declaredScope) {
super(Token.NAME, value);
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/JavaScriptToken.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -6,10 +6,11 @@
*
http://developer.yahoo.net/yui/license.txt
*/
+
+
package com.yahoo.platform.yui.compressor;
public class JavaScriptToken {
-
private int type;
private String value;
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/com/yahoo/platform/yui/compressor/ScriptOrFnScope.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -6,6 +6,8 @@
*
http://developer.yahoo.net/yui/license.txt
*/
+
+
package com.yahoo.platform.yui.compressor;
import java.util.ArrayList;
@@ -13,18 +15,18 @@
import java.util.Hashtable;
class ScriptOrFnScope {
-
+ private Hashtable identifiers = new Hashtable();
+ private Hashtable hints = new Hashtable();
+ private boolean markedForMunging = true;
private int braceNesting;
private ScriptOrFnScope parentScope;
private ArrayList subScopes;
- private Hashtable identifiers = new Hashtable();
- private Hashtable hints = new Hashtable();
- private boolean markedForMunging = true;
ScriptOrFnScope(int braceNesting, ScriptOrFnScope parentScope) {
this.braceNesting = braceNesting;
this.parentScope = parentScope;
this.subScopes = new ArrayList();
+
if (parentScope != null) {
parentScope.subScopes.add(this);
}
@@ -40,10 +42,12 @@
JavaScriptIdentifier declareIdentifier(String symbol) {
JavaScriptIdentifier identifier = (JavaScriptIdentifier)
identifiers.get(symbol);
+
if (identifier == null) {
identifier = new JavaScriptIdentifier(symbol, this);
identifiers.put(symbol, identifier);
}
+
return identifier;
}
@@ -57,6 +61,7 @@
void preventMunging() {
if (parentScope != null) {
+
// The symbols in the global scope don't get munged,
// but the sub-scopes it contains do get munged.
markedForMunging = false;
@@ -66,30 +71,36 @@
private ArrayList getUsedSymbols() {
ArrayList result = new ArrayList();
Enumeration elements = identifiers.elements();
+
while (elements.hasMoreElements()) {
JavaScriptIdentifier identifier = (JavaScriptIdentifier)
elements.nextElement();
String mungedValue = identifier.getMungedValue();
+
if (mungedValue == null) {
mungedValue = identifier.getValue();
}
+
result.add(mungedValue);
}
+
return result;
}
private ArrayList getAllUsedSymbols() {
ArrayList result = new ArrayList();
ScriptOrFnScope scope = this;
+
while (scope != null) {
result.addAll(scope.getUsedSymbols());
scope = scope.parentScope;
}
+
return result;
}
void munge() {
+ if (!markedForMunging) {
- if (!markedForMunging) {
// Stop right here if this scope was flagged as unsafe for munging.
return;
}
@@ -98,30 +109,34 @@
// Do not munge symbols in the global scope!
if (parentScope != null) {
-
ArrayList freeSymbols = new ArrayList();
freeSymbols.addAll(JavaScriptCompressor.ones);
freeSymbols.removeAll(getAllUsedSymbols());
+
if (freeSymbols.size() == 0) {
pickFromSet = 2;
freeSymbols.addAll(JavaScriptCompressor.twos);
freeSymbols.removeAll(getAllUsedSymbols());
}
+
if (freeSymbols.size() == 0) {
pickFromSet = 3;
freeSymbols.addAll(JavaScriptCompressor.threes);
freeSymbols.removeAll(getAllUsedSymbols());
}
+
if (freeSymbols.size() == 0) {
System.err.println("The YUI Compressor ran out of symbols.
Aborting...");
System.exit(1);
}
Enumeration elements = identifiers.elements();
+
while (elements.hasMoreElements()) {
if (freeSymbols.size() == 0) {
pickFromSet++;
+
if (pickFromSet == 2) {
freeSymbols.addAll(JavaScriptCompressor.twos);
} else if (pickFromSet == 3) {
@@ -130,6 +145,7 @@
System.err.println("The YUI Compressor ran out of symbols.
Aborting...");
System.exit(1);
}
+
// It is essential to remove the symbols already used in
// the containing scopes, or some of the variables declared
// in the containing scopes will be redeclared, which can
@@ -139,17 +155,20 @@
String mungedValue;
JavaScriptIdentifier identifier = (JavaScriptIdentifier)
elements.nextElement();
+
if (identifier.isMarkedForMunging()) {
mungedValue = (String) freeSymbols.remove(0);
} else {
mungedValue = identifier.getValue();
}
+
identifier.setMungedValue(mungedValue);
}
}
for (int i = 0; i < subScopes.size(); i++) {
ScriptOrFnScope scope = (ScriptOrFnScope) subScopes.get(i);
+
scope.munge();
}
}
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/Aggregation.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -18,12 +18,15 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
+
+
+
package net.sf.alchim.mojo.yuicompressor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+
import java.util.ArrayList;
import java.util.List;
@@ -31,32 +34,39 @@
import org.codehaus.plexus.util.IOUtil;
public class Aggregation {
+ public boolean removeIncluded = false;
+ public boolean insertSemicolon = false;
+ public boolean insertNewLine = false;
+ public String[] excludes;
+ public String[] includes;
public File output;
public File sourceDirectory;
- public String[] includes;
- public String[] excludes;
- public boolean removeIncluded = false;
- public boolean insertNewLine = false;
- public boolean insertSemicolon = false;
-
+
public void run(File outputDirectory) throws Exception {
- if(null == sourceDirectory){
- sourceDirectory = outputDirectory;
- }
+ if (null == sourceDirectory) {
+ sourceDirectory = outputDirectory;
+ }
+
List<File> files = getIncludedFiles();
+
if (files.size() != 0) {
FileOutputStream out = new FileOutputStream(output);
+
try {
for (File file : files) {
FileInputStream in = new FileInputStream(file);
+
try {
IOUtil.copy(in, out);
+
if (insertSemicolon) {
- out.write(';');
+ out.write(';');
}
+
if (insertNewLine) {
out.write('\n');
}
+
if (removeIncluded) {
file.delete();
}
@@ -74,31 +84,39 @@
protected List<File> getIncludedFiles() throws Exception {
ArrayList<File> back = new ArrayList<File>();
+
if (includes != null) {
for (String include : includes) {
addInto(include, back);
}
}
+
return back;
}
private void addInto(String include, List<File> includedFiles) throws Exception
{
if (include.indexOf('*') > -1) {
DirectoryScanner scanner = newScanner();
- scanner.setIncludes(new String[] { include });
+
+ scanner.setIncludes(new String[] {include});
scanner.scan();
+
String[] rpaths = scanner.getIncludedFiles();
+
for (String rpath : rpaths) {
File file = new File(scanner.getBasedir(), rpath);
+
if (!includedFiles.contains(file)) {
includedFiles.add(file);
}
}
} else {
File file = new File(include);
+
if (!file.isAbsolute()) {
file = new File(output.getParentFile(), include);
}
+
if (!includedFiles.contains(file)) {
includedFiles.add(file);
}
@@ -107,11 +125,15 @@
private DirectoryScanner newScanner() throws Exception {
DirectoryScanner scanner = new DirectoryScanner();
+
scanner.setBasedir(sourceDirectory);
+
if ((excludes != null) && (excludes.length != 0)) {
scanner.setExcludes(excludes);
}
+
scanner.addDefaultExcludes();
+
return scanner;
}
}
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/BasicRhinoShell.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -33,6 +33,8 @@
*
* ***** END LICENSE BLOCK ***** */
+
+
package net.sf.alchim.mojo.yuicompressor;
import java.io.BufferedReader;
@@ -43,6 +45,7 @@
import java.io.InputStreamReader;
import org.codehaus.plexus.util.IOUtil;
+
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ErrorReporter;
import org.mozilla.javascript.EvaluatorException;
@@ -64,6 +67,7 @@
*/
@SuppressWarnings("serial")
public class BasicRhinoShell extends ScriptableObject {
+ private boolean quitting;
@Override
public String getClassName() {
@@ -78,36 +82,46 @@
* execution environment and begin to execute scripts.
*/
public static void exec(String args[], ErrorReporter reporter) {
+
// Associate a new Context with this thread
Context cx = Context.enter();
+
cx.setErrorReporter(reporter);
+
try {
+
// Initialize the standard objects (Object, Function, etc.)
// This must be done before scripts can be executed.
BasicRhinoShell BasicRhinoShell = new BasicRhinoShell();
+
cx.initStandardObjects(BasicRhinoShell);
// Define some global functions particular to the BasicRhinoShell.
// Note
// that these functions are not part of ECMA.
- String[] names = { "print", "quit", "version",
"load", "help", "readFile" };
+ String[] names = {
+ "print", "quit", "version",
"load", "help", "readFile"
+ };
+
BasicRhinoShell.defineFunctionProperties(names, BasicRhinoShell.class,
ScriptableObject.DONTENUM);
-
args = processOptions(cx, args);
// Set up "arguments" in the global scope to contain the command
// line arguments after the name of the script to execute
Object[] array;
+
if (args.length == 0) {
array = new Object[0];
} else {
int length = args.length - 1;
+
array = new Object[length];
System.arraycopy(args, 1, array, 0, length);
}
+
Scriptable argsObj = cx.newArray(BasicRhinoShell, array);
+
BasicRhinoShell.defineProperty("arguments", argsObj,
ScriptableObject.DONTENUM);
-
BasicRhinoShell.processSource(cx, args.length == 0 ? null : args[0]);
} finally {
Context.exit();
@@ -120,26 +134,36 @@
public static String[] processOptions(Context cx, String args[]) {
for (int i = 0; i < args.length; i++) {
String arg = args[i];
+
if (!arg.startsWith("-")) {
String[] result = new String[args.length - i];
+
for (int j = i; j < args.length; j++) {
result[j - i] = args[j];
}
+
return result;
}
+
if (arg.equals("-version")) {
if (++i == args.length) {
usage(arg);
}
+
double d = Context.toNumber(args[i]);
+
if (d != d) {
usage(arg);
}
+
cx.setLanguageVersion((int) d);
+
continue;
}
+
usage(arg);
}
+
return new String[0];
}
@@ -196,6 +220,7 @@
System.out.print(s);
}
+
System.out.println();
}
@@ -230,10 +255,13 @@
*/
public static double version(Context cx, Scriptable thisObj, Object[] args, Function
funObj) {
double result = cx.getLanguageVersion();
+
if (args.length > 0) {
double d = Context.toNumber(args[0]);
+
cx.setLanguageVersion((int) d);
}
+
return result;
}
@@ -245,6 +273,7 @@
*/
public static void load(Context cx, Scriptable thisObj, Object[] args, Function
funObj) {
BasicRhinoShell BasicRhinoShell = (BasicRhinoShell) getTopLevelScope(thisObj);
+
for (Object element : args) {
BasicRhinoShell.processSource(cx, Context.toString(element));
}
@@ -263,22 +292,31 @@
String sourceName = "<stdin>";
int lineno = 1;
boolean hitEOF = false;
+
do {
int startline = lineno;
+
System.err.print("js> ");
System.err.flush();
+
try {
String source = "";
+
// Collect lines of source to compile.
while (true) {
String newline;
+
newline = in.readLine();
+
if (newline == null) {
hitEOF = true;
+
break;
}
+
source = source + newline + "\n";
lineno++;
+
// Continue collecting as long as more lines
// are needed to complete the current
// statement. stringIsCompilableUnit is also
@@ -289,40 +327,51 @@
break;
}
}
+
Object result = cx.evaluateString(this, source, sourceName,
startline, null);
+
if (result != Context.getUndefinedValue()) {
System.err.println(Context.toString(result));
}
} catch (WrappedException we) {
+
// Some form of exception was caught by JavaScript and
// propagated up.
System.err.println(we.getWrappedException().toString());
we.printStackTrace();
} catch (EvaluatorException ee) {
+
// Some form of JavaScript error.
System.err.println("js: " + ee.getMessage());
} catch (JavaScriptException jse) {
+
// Some form of JavaScript error.
System.err.println("js: " + jse.getMessage());
} catch (IOException ioe) {
System.err.println(ioe.toString());
}
+
if (quitting) {
+
// The user executed the quit() function.
break;
}
} while (!hitEOF);
+
System.err.println();
} else {
FileReader in = null;
+
try {
in = new FileReader(filename);
} catch (FileNotFoundException ex) {
Context.reportError("Couldn't open file \"" + filename
+ "\".");
+
return;
}
try {
+
// Here we evalute the entire contents of the file as
// a script. Text is printed only if the print() function
// is called.
@@ -349,6 +398,4 @@
private static void p(String s) {
System.out.println(s);
}
-
- private boolean quitting;
}
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/ErrorReporter4Mojo.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -18,20 +18,22 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
+
+
+
package net.sf.alchim.mojo.yuicompressor;
import org.apache.maven.plugin.logging.Log;
+
import org.mozilla.javascript.ErrorReporter;
import org.mozilla.javascript.EvaluatorException;
public class ErrorReporter4Mojo implements ErrorReporter {
-
+ private boolean acceptWarn_;
private String defaultFilename_;
- private boolean acceptWarn_;
+ private int errorCnt_;
private Log log_;
private int warningCnt_;
- private int errorCnt_;
public ErrorReporter4Mojo(Log log, boolean jswarn) {
log_ = log;
@@ -42,6 +44,7 @@
if (v.length() == 0) {
v = null;
}
+
defaultFilename_ = v;
}
@@ -55,18 +58,22 @@
public void error(String message, String sourceName, int line, String lineSource, int
lineOffset) {
String fullMessage = newMessage(message, sourceName, line, lineSource,
lineOffset);
+
log_.error(fullMessage);
errorCnt_++;
}
- public EvaluatorException runtimeError(String message, String sourceName, int line,
String lineSource, int lineOffset) {
+ public EvaluatorException runtimeError(String message, String sourceName, int line,
String lineSource,
+ int lineOffset) {
error(message, sourceName, line, lineSource, lineOffset);
+
throw new EvaluatorException(message, sourceName, line, lineSource, lineOffset);
}
public void warning(String message, String sourceName, int line, String lineSource,
int lineOffset) {
if (acceptWarn_) {
String fullMessage = newMessage(message, sourceName, line, lineSource,
lineOffset);
+
log_.warn(fullMessage);
warningCnt_++;
}
@@ -74,29 +81,27 @@
private String newMessage(String message, String sourceName, int line, String
lineSource, int lineOffset) {
StringBuilder back = new StringBuilder();
+
if ((sourceName == null) || (sourceName.length() == 0)) {
sourceName = defaultFilename_;
}
+
if (sourceName != null) {
- back.append(sourceName)
- .append(":line ")
- .append(line)
- .append(":column ")
- .append(lineOffset)
- .append(':')
- ;
+ back.append(sourceName).append(":line
").append(line).append(":column ").append(lineOffset).append(':')
+ ;
}
+
if ((message != null) && (message.length() != 0)) {
back.append(message);
} else {
back.append("unknown error");
}
+
if ((lineSource != null) && (lineSource.length() != 0)) {
- back.append("\n\t")
- .append(lineSource)
- ;
+ back.append("\n\t").append(lineSource)
+ ;
}
+
return back.toString();
}
-
}
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintChecker.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -18,7 +18,9 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
+
+
+
package net.sf.alchim.mojo.yuicompressor;
import java.io.File;
@@ -26,6 +28,7 @@
import java.io.InputStream;
import org.codehaus.plexus.util.IOUtil;
+
import org.mozilla.javascript.ErrorReporter;
//TODO: use MojoErrorReporter
@@ -35,8 +38,10 @@
public JSLintChecker() throws Exception {
FileOutputStream out = null;
InputStream in = null;
+
try {
File jslint = File.createTempFile("jslint", ".js");
+
in = getClass().getResourceAsStream("/jslint.js");
out = new FileOutputStream(jslint);
IOUtil.copy(in, out);
@@ -49,11 +54,13 @@
public void check(File jsFile, ErrorReporter reporter) {
String[] args = new String[2];
+
args[0] = jslintPath_;
args[1] = jsFile.getAbsolutePath();
BasicRhinoShell.exec(args, reporter);
- //if (Main.exec(args) != 0) {
- // reporter.warning("warnings during checking of :" +
jsFile.getAbsolutePath(), null, -1, null, -1);
- //}
+
+ // if (Main.exec(args) != 0) {
+ // reporter.warning("warnings during checking of :" +
jsFile.getAbsolutePath(), null, -1, null, -1);
+ // }
}
}
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/JSLintMojo.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -18,10 +18,11 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
+
+
+
package net.sf.alchim.mojo.yuicompressor;
-
/**
* Check JS files with jslint.
*
@@ -31,13 +32,14 @@
* @author David Bernard
* @created 2007-08-29
*/
-// @SuppressWarnings("unchecked")
+
+//@SuppressWarnings("unchecked")
public class JSLintMojo extends MojoSupport {
private JSLintChecker jslint_;
@Override
protected String[] getDefaultIncludes() throws Exception {
- return new String[] { "**/**.js" };
+ return new String[] {"**/**.js"};
}
@Override
@@ -46,8 +48,7 @@
}
@Override
- public void afterProcess() throws Exception {
- }
+ public void afterProcess() throws Exception {}
@Override
protected void processFile(SourceFile src) throws Exception {
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/MojoSupport.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -18,10 +18,13 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
+
+
+
package net.sf.alchim.mojo.yuicompressor;
import java.io.File;
+
import java.util.List;
import org.apache.maven.model.Resource;
@@ -29,177 +32,186 @@
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
+
import org.codehaus.plexus.util.DirectoryScanner;
/**
* Common class for mojos.
- *
+ *
* @author David Bernard
* @created 2007-08-29
*/
-// @SuppressWarnings("unchecked")
+
+//@SuppressWarnings("unchecked")
public abstract class MojoSupport extends AbstractMojo {
- private static final String[] EMPTY_STRING_ARRAY = {};
+ private static final String[] EMPTY_STRING_ARRAY = {};
- /**
- * Javascript source directory. (result will be put to outputDirectory).
- * This allow project with "src/main/js" structure.
- *
- * @parameter default-value="${project.build.sourceDirectory}/../js"
- */
- private File sourceDirectory;
+ /**
+ * list of additionnal excludes
+ *
+ * @parameter
+ */
+ private List<String> excludes;
- /**
- * Single directory for extra files to include in the WAR.
- *
- * @parameter default-value="${basedir}/src/main/webapp"
- */
- private File warSourceDirectory;
+ /**
+ * define if plugin must stop/fail on warnings.
+ *
+ * @parameter expression="${maven.yuicompressor.failOnWarning}"
+ * default-value="false"
+ */
+ protected boolean failOnWarning;
- /**
- * The directory where the webapp is built.
- *
- * @parameter
default-value="${project.build.directory}/${project.build.finalName}"
- */
- protected File webappDirectory;
+ /**
+ * list of additionnal includes
+ *
+ * @parameter
+ */
+ private List<String> includes;
+ protected ErrorReporter4Mojo jsErrorReporter_;
- /**
- * The output directory into which to copy the resources.
- *
- * @parameter default-value="${project.build.outputDirectory}"
- */
- protected File outputDirectory;
+ /**
+ * [js only] Display possible errors in the code
+ *
+ * @parameter expression="${maven.yuicompressor.jswarm}"
+ * default-value="true"
+ */
+ protected boolean jswarn;
- /**
- * The list of resources we want to transfer.
- *
- * @parameter default-value="${project.resources}"
- */
- private List<Resource> resources;
+ /**
+ * The output directory into which to copy the resources.
+ *
+ * @parameter default-value="${project.build.outputDirectory}"
+ */
+ protected File outputDirectory;
- /**
- * list of additionnal excludes
- *
- * @parameter
- */
- private List<String> excludes;
+ /**
+ * @parameter expression="${project}"
+ * @readonly
+ * @required
+ */
+ protected MavenProject project;
- /**
- * list of additionnal includes
- *
- * @parameter
- */
- private List<String> includes;
+ /**
+ * The list of resources we want to transfer.
+ *
+ * @parameter default-value="${project.resources}"
+ */
+ private List<Resource> resources;
- /**
- * @parameter expression="${project}"
- * @readonly
- * @required
- */
- protected MavenProject project;
+ /**
+ * Javascript source directory. (result will be put to outputDirectory).
+ * This allow project with "src/main/js" structure.
+ *
+ * @parameter default-value="${project.build.sourceDirectory}/../js"
+ */
+ private File sourceDirectory;
- /**
- * [js only] Display possible errors in the code
- *
- * @parameter expression="${maven.yuicompressor.jswarm}"
- * default-value="true"
- */
- protected boolean jswarn;
+ /**
+ * Single directory for extra files to include in the WAR.
+ *
+ * @parameter default-value="${basedir}/src/main/webapp"
+ */
+ private File warSourceDirectory;
- /**
- * define if plugin must stop/fail on warnings.
- *
- * @parameter expression="${maven.yuicompressor.failOnWarning}"
- * default-value="false"
- */
- protected boolean failOnWarning;
- protected ErrorReporter4Mojo jsErrorReporter_;
+ /**
+ * The directory where the webapp is built.
+ *
+ * @parameter
default-value="${project.build.directory}/${project.build.finalName}"
+ */
+ protected File webappDirectory;
- @SuppressWarnings("unchecked")
- public void execute() throws MojoExecutionException, MojoFailureException {
- try {
- if (failOnWarning) {
- jswarn = true;
- }
- jsErrorReporter_ = new ErrorReporter4Mojo(getLog(), jswarn);
- beforeProcess();
- processDir(sourceDirectory, outputDirectory, null, null,
- true);
- for (Resource resource : resources) {
- File destRoot = outputDirectory;
- if (resource.getTargetPath() != null) {
- destRoot = new File(outputDirectory, resource
- .getTargetPath());
- }
- processDir(new File(resource.getDirectory()), destRoot,
- resource.getIncludes(), resource.getExcludes(), true);
- }
- processDir(warSourceDirectory, webappDirectory, null, null,
- false);
- afterProcess();
- getLog().info(
- String.format("nb warnings: %d, nb errors: %d",
- jsErrorReporter_.getWarningCnt(), jsErrorReporter_
- .getErrorCnt()));
- if (failOnWarning && (jsErrorReporter_.getWarningCnt() > 0)) {
- throw new MojoFailureException("warnings on "
- + this.getClass().getSimpleName()
- + "=> failure ! (see log)");
- }
- } catch (RuntimeException exc) {
- throw exc;
- } catch (MojoFailureException exc) {
- throw exc;
- } catch (MojoExecutionException exc) {
- throw exc;
- } catch (Exception exc) {
- throw new MojoExecutionException("wrap: " + exc.getMessage(), exc);
- }
- }
+ @SuppressWarnings("unchecked")
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ try {
+ if (failOnWarning) {
+ jswarn = true;
+ }
- protected abstract String[] getDefaultIncludes() throws Exception;
+ jsErrorReporter_ = new ErrorReporter4Mojo(getLog(), jswarn);
+ beforeProcess();
+ processDir(sourceDirectory, outputDirectory, null, null, true);
- protected abstract void beforeProcess() throws Exception;
+ for (Resource resource : resources) {
+ File destRoot = outputDirectory;
- protected abstract void afterProcess() throws Exception;
+ if (resource.getTargetPath() != null) {
+ destRoot = new File(outputDirectory, resource.getTargetPath());
+ }
- protected void processDir(File srcRoot, File destRoot,
- List<String> srcIncludes, List<String> srcExcludes,
- boolean destAsSource) throws Exception {
- if ((srcRoot == null) || (!srcRoot.exists())) {
- return;
- }
- if (destRoot == null) {
- throw new MojoFailureException("destination directory for "
- + srcRoot + " is null");
- }
- DirectoryScanner scanner = new DirectoryScanner();
- scanner.setBasedir(srcRoot);
- if ((srcIncludes != null) && !srcIncludes.isEmpty()) {
- scanner.setIncludes(srcIncludes.toArray(EMPTY_STRING_ARRAY));
- }
- if ((includes != null) && !includes.isEmpty()) {
- scanner.setIncludes(includes.toArray(EMPTY_STRING_ARRAY));
- } else {
- scanner.setIncludes(getDefaultIncludes());
- }
- if ((srcExcludes != null) && !srcExcludes.isEmpty()) {
- scanner.setExcludes(srcExcludes.toArray(EMPTY_STRING_ARRAY));
- }
- if ((excludes != null) && !excludes.isEmpty()) {
- scanner.setExcludes(excludes.toArray(EMPTY_STRING_ARRAY));
- }
- scanner.addDefaultExcludes();
- scanner.scan();
- for (String name : scanner.getIncludedFiles()) {
- SourceFile src = new SourceFile(srcRoot, destRoot, name,
- destAsSource);
- jsErrorReporter_.setDefaultFileName("..."
- + src.toFile().getAbsolutePath().substring(
- project.getBasedir().getAbsolutePath().length()));
- processFile(src);
- }
- }
+ processDir(new File(resource.getDirectory()), destRoot,
resource.getIncludes(), resource.getExcludes(),
+ true);
+ }
- protected abstract void processFile(SourceFile src) throws Exception;
+ processDir(warSourceDirectory, webappDirectory, null, null, false);
+ afterProcess();
+ getLog().info(String.format("nb warnings: %d, nb errors: %d",
jsErrorReporter_.getWarningCnt(),
+ jsErrorReporter_.getErrorCnt()));
+
+ if (failOnWarning && (jsErrorReporter_.getWarningCnt() > 0)) {
+ throw new MojoFailureException("warnings on " +
this.getClass().getSimpleName()
+ + "=> failure ! (see log)");
+ }
+ } catch (RuntimeException exc) {
+ throw exc;
+ } catch (MojoFailureException exc) {
+ throw exc;
+ } catch (MojoExecutionException exc) {
+ throw exc;
+ } catch (Exception exc) {
+ throw new MojoExecutionException("wrap: " + exc.getMessage(),
exc);
+ }
+ }
+
+ protected abstract String[] getDefaultIncludes() throws Exception;
+
+ protected abstract void beforeProcess() throws Exception;
+
+ protected abstract void afterProcess() throws Exception;
+
+ protected void processDir(File srcRoot, File destRoot, List<String>
srcIncludes, List<String> srcExcludes,
+ boolean destAsSource)
+ throws Exception {
+ if ((srcRoot == null) || (!srcRoot.exists())) {
+ return;
+ }
+
+ if (destRoot == null) {
+ throw new MojoFailureException("destination directory for " +
srcRoot + " is null");
+ }
+
+ DirectoryScanner scanner = new DirectoryScanner();
+
+ scanner.setBasedir(srcRoot);
+
+ if ((srcIncludes != null) && !srcIncludes.isEmpty()) {
+ scanner.setIncludes(srcIncludes.toArray(EMPTY_STRING_ARRAY));
+ }
+
+ if ((includes != null) && !includes.isEmpty()) {
+ scanner.setIncludes(includes.toArray(EMPTY_STRING_ARRAY));
+ } else {
+ scanner.setIncludes(getDefaultIncludes());
+ }
+
+ if ((srcExcludes != null) && !srcExcludes.isEmpty()) {
+ scanner.setExcludes(srcExcludes.toArray(EMPTY_STRING_ARRAY));
+ }
+
+ if ((excludes != null) && !excludes.isEmpty()) {
+ scanner.setExcludes(excludes.toArray(EMPTY_STRING_ARRAY));
+ }
+
+ scanner.addDefaultExcludes();
+ scanner.scan();
+
+ for (String name : scanner.getIncludedFiles()) {
+ SourceFile src = new SourceFile(srcRoot, destRoot, name, destAsSource);
+
+ jsErrorReporter_.setDefaultFileName("..."
+ +
src.toFile().getAbsolutePath().substring(project.getBasedir().getAbsolutePath().length()));
+ processFile(src);
+ }
+ }
+
+ protected abstract void processFile(SourceFile src) throws Exception;
}
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/SourceFile.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -18,26 +18,29 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
+
+
+
package net.sf.alchim.mojo.yuicompressor;
import java.io.File;
public class SourceFile {
-
- private File srcRoot_;
+ private boolean destAsSource_;
private File destRoot_;
- private boolean destAsSource_;
+ private String extension_;
private String rpath_;
- private String extension_;
+ private File srcRoot_;
public SourceFile(File srcRoot, File destRoot, String name, boolean destAsSource)
throws Exception {
srcRoot_ = srcRoot;
destRoot_ = destRoot;
destAsSource_ = destAsSource;
rpath_ = name;
+
int sep = rpath_.lastIndexOf('.');
- if (sep>0) {
+
+ if (sep > 0) {
extension_ = rpath_.substring(sep);
rpath_ = rpath_.substring(0, sep);
} else {
@@ -47,12 +50,15 @@
public File toFile() {
String frpath = rpath_ + extension_;
+
if (destAsSource_) {
File defaultDest = new File(destRoot_, frpath);
+
if (defaultDest.exists() && defaultDest.canRead()) {
return defaultDest;
}
}
+
return new File(srcRoot_, frpath);
}
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/net/sf/alchim/mojo/yuicompressor/YuiCompressorMojo.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -18,7 +18,9 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
+
+
+
package net.sf.alchim.mojo.yuicompressor;
import java.io.File;
@@ -26,9 +28,11 @@
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
+
import java.util.zip.GZIPOutputStream;
import org.apache.maven.plugin.MojoExecutionException;
+
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
@@ -44,10 +48,20 @@
* @author David Bernard
* @created 2007-08-28
*/
-// @SuppressWarnings("unchecked")
+
+//@SuppressWarnings("unchecked")
public class YuiCompressorMojo extends MojoSupport {
/**
+ * a list of aggregation/concatenation to do after processing,
+ * for example to create big js files that contain several small js files.
+ * Aggregation could be done on any type of file (js, css, ...).
+ *
+ * @parameter
+ */
+ private Aggregation[] aggregations;
+
+ /**
* Read the input file using "encoding".
*
* @parameter expression="${file.encoding}"
default-value="UTF-8"
@@ -55,18 +69,20 @@
private String encoding;
/**
- * The output filename suffix.
+ * force the compression of every files,
+ * else if compressed file already exists and is younger than source file, nothing is
done.
*
- * @parameter expression="${maven.yuicompressor.suffix}"
default-value="-min"
+ * @parameter expression="${maven.yuicompressor.force}"
default-value="false"
*/
- private String suffix;
+ private boolean force;
/**
- * If no "suffix" must be add to output filename (maven's configuration
manage empty suffix like default).
+ * request to create a gzipped version of the yuicompressed/aggregation files.
*
- * @parameter expression="${maven.yuicompressor.nosuffix}"
default-value="false"
+ * @parameter expression="${maven.yuicompressor.gzip}"
default-value="false"
*/
- private boolean nosuffix;
+ private boolean gzip;
+ private long inSizeTotal_;
/**
* Insert line breaks in output after the specified column number.
@@ -83,6 +99,14 @@
private boolean nomunge;
/**
+ * If no "suffix" must be add to output filename (maven's configuration
manage empty suffix like default).
+ *
+ * @parameter expression="${maven.yuicompressor.nosuffix}"
default-value="false"
+ */
+ private boolean nosuffix;
+ private long outSizeTotal_;
+
+ /**
* [js only] Preserve unnecessary semicolons.
*
* @parameter expression="${maven.yuicompressor.preserveAllSemiColons}"
default-value="false"
@@ -97,42 +121,22 @@
private boolean preserveStringLiterals;
/**
- * force the compression of every files,
- * else if compressed file already exists and is younger than source file, nothing is
done.
+ * show statistics (compression ratio).
*
- * @parameter expression="${maven.yuicompressor.force}"
default-value="false"
+ * @parameter expression="${maven.yuicompressor.statistics}"
default-value="true"
*/
- private boolean force;
+ private boolean statistics;
/**
- * a list of aggregation/concatenation to do after processing,
- * for example to create big js files that contain several small js files.
- * Aggregation could be done on any type of file (js, css, ...).
+ * The output filename suffix.
*
- * @parameter
+ * @parameter expression="${maven.yuicompressor.suffix}"
default-value="-min"
*/
- private Aggregation[] aggregations;
+ private String suffix;
- /**
- * request to create a gzipped version of the yuicompressed/aggregation files.
- *
- * @parameter expression="${maven.yuicompressor.gzip}"
default-value="false"
- */
- private boolean gzip;
-
- /**
- * show statistics (compression ratio).
- *
- * @parameter expression="${maven.yuicompressor.statistics}"
default-value="true"
- */
- private boolean statistics;
-
- private long inSizeTotal_;
- private long outSizeTotal_;
-
@Override
protected String[] getDefaultIncludes() throws Exception {
- return new String[]{"**/*.css", "**/*.js"};
+ return new String[] {"**/*.css", "**/*.js"};
}
@Override
@@ -145,18 +149,25 @@
@Override
protected void afterProcess() throws Exception {
if (statistics && (inSizeTotal_ > 0)) {
- getLog().info(String.format("total input (%db) -> output
(%db)[%d%%]", inSizeTotal_, outSizeTotal_, ((outSizeTotal_ * 100)/inSizeTotal_)));
+ getLog().info(String.format("total input (%db) -> output
(%db)[%d%%]", inSizeTotal_, outSizeTotal_,
+ ((outSizeTotal_ * 100) / inSizeTotal_)));
}
+
if (aggregations != null) {
- for(Aggregation aggregation : aggregations) {
+ for (Aggregation aggregation : aggregations) {
getLog().info("generate aggregation : " + aggregation.output);
aggregation.run(outputDirectory);
+
File gzipped = gzipIfRequested(aggregation.output);
+
if (statistics) {
if (gzipped != null) {
- getLog().info(String.format("%s (%db) -> %s
(%db)[%d%%]", aggregation.output.getName(), aggregation.output.length(),
gzipped.getName(), gzipped.length(), ratioOfSize(aggregation.output, gzipped)));
- } else if (aggregation.output.exists()){
- getLog().info(String.format("%s (%db)",
aggregation.output.getName(), aggregation.output.length()));
+ getLog().info(String.format("%s (%db) -> %s
(%db)[%d%%]", aggregation.output.getName(),
+ aggregation.output.length(),
gzipped.getName(), gzipped.length(),
+ ratioOfSize(aggregation.output,
gzipped)));
+ } else if (aggregation.output.exists()) {
+ getLog().info(String.format("%s (%db)",
aggregation.output.getName(),
+ aggregation.output.length()));
} else {
getLog().warn(String.format("%s not created",
aggregation.output.getName()));
}
@@ -165,59 +176,77 @@
}
}
-
@Override
protected void processFile(SourceFile src) throws Exception {
if (getLog().isDebugEnabled()) {
- getLog().debug("compress file :" + src.toFile()+ " to " +
src.toDestFile(suffix));
+ getLog().debug("compress file :" + src.toFile() + " to "
+ src.toDestFile(suffix));
}
+
File inFile = src.toFile();
File outFile = src.toDestFile(suffix);
getLog().debug("only compress if input file is youger than existing output
file");
+
if (!force && outFile.exists() && (outFile.lastModified() >
inFile.lastModified())) {
if (getLog().isInfoEnabled()) {
- getLog().info("nothing to do, " + outFile + " is younger
than original, use 'force' option or clean your target");
+ getLog().info("nothing to do, " + outFile
+ + " is younger than original, use 'force'
option or clean your target");
}
+
return;
}
InputStreamReader in = null;
OutputStreamWriter out = null;
+
try {
in = new InputStreamReader(new FileInputStream(inFile), encoding);
+
if (!outFile.getParentFile().exists() &&
!outFile.getParentFile().mkdirs()) {
- throw new MojoExecutionException( "Cannot create resource output
directory: " + outFile.getParentFile() );
+ throw new MojoExecutionException("Cannot create resource output
directory: " + outFile.getParentFile());
}
+
getLog().debug("use a temporary outputfile (in case in == out)");
+
File outFileTmp = new File(outFile.getAbsolutePath() + ".tmp");
+
FileUtils.forceDelete(outFileTmp);
-
getLog().debug("start compression");
out = new OutputStreamWriter(new FileOutputStream(outFileTmp), encoding);
+
if (".js".equalsIgnoreCase(src.getExtension())) {
JavaScriptCompressor compressor = new JavaScriptCompressor(in,
jsErrorReporter_);
+
compressor.compress(out, linebreakpos, !nomunge, jswarn,
preserveAllSemiColons, preserveStringLiterals);
} else if (".css".equalsIgnoreCase(src.getExtension())) {
CssCompressor compressor = new CssCompressor(in);
+
compressor.compress(out, linebreakpos);
}
+
getLog().debug("end compression");
+
// Close output file before rename.
- IOUtil.close(out);out=null;
+ IOUtil.close(out);
+ out = null;
FileUtils.forceDelete(outFile);
FileUtils.rename(outFileTmp, outFile);
} finally {
IOUtil.close(in);
IOUtil.close(out);
}
+
File gzipped = gzipIfRequested(outFile);
+
if (statistics) {
inSizeTotal_ += inFile.length();
outSizeTotal_ += outFile.length();
- getLog().info(String.format("%s (%db) -> %s (%db)[%d%%]",
inFile.getName(), inFile.length(), outFile.getName(), outFile.length(),
ratioOfSize(inFile, outFile)));
+ getLog().info(String.format("%s (%db) -> %s (%db)[%d%%]",
inFile.getName(), inFile.length(),
+ outFile.getName(), outFile.length(),
ratioOfSize(inFile, outFile)));
+
if (gzipped != null) {
- getLog().info(String.format("%s (%db) -> %s (%db)[%d%%]",
inFile.getName(), inFile.length(), gzipped.getName(), gzipped.length(),
ratioOfSize(inFile, gzipped)));
+ getLog().info(String.format("%s (%db) -> %s (%db)[%d%%]",
inFile.getName(), inFile.length(),
+ gzipped.getName(), gzipped.length(),
ratioOfSize(inFile, gzipped)));
}
}
}
@@ -226,13 +255,18 @@
if (!gzip || (file == null) || (!file.exists())) {
return null;
}
+
if (".gz".equalsIgnoreCase(FileUtils.getExtension(file.getName()))) {
return null;
}
- File gzipped = new File(file.getAbsolutePath()+".gz");
+
+ File gzipped = new File(file.getAbsolutePath() + ".gz");
+
getLog().debug(String.format("create gzip version : %s",
gzipped.getName()));
+
GZIPOutputStream out = null;
FileInputStream in = null;
+
try {
out = new GZIPOutputStream(new FileOutputStream(gzipped));
in = new FileInputStream(file);
@@ -241,12 +275,14 @@
IOUtil.close(in);
IOUtil.close(out);
}
+
return gzipped;
}
protected long ratioOfSize(File file100, File fileX) throws Exception {
long v100 = Math.max(file100.length(), 1);
long vX = Math.max(fileX.length(), 1);
- return (vX * 100)/v100;
+
+ return (vX * 100) / v100;
}
}
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Decompiler.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -39,6 +39,8 @@
*
* ***** END LICENSE BLOCK ***** */
+
+
package org.mozilla.javascript;
/**
@@ -47,7 +49,7 @@
* 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
@@ -74,18 +76,17 @@
* the final constant pool entry from information available at parse
* time.
*/
-public class Decompiler
-{
+public class Decompiler {
+
/**
- * Flag to indicate that the decompilation should omit the
- * function header and trailing brace.
+ * Decompilation property to specify identation offset for case labels.
*/
- public static final int ONLY_BODY_FLAG = 1 << 0;
+ public static final int CASE_GAP_PROP = 3;
/**
- * Flag to indicate that the decompilation generates toSource result.
+ * Decompilation property to specify default identation offset.
*/
- public static final int TO_SOURCE_FLAG = 1 << 1;
+ public static final int INDENT_GAP_PROP = 2;
/**
* Decompilation property to specify initial ident value.
@@ -93,186 +94,206 @@
public static final int INITIAL_INDENT_PROP = 1;
/**
- * Decompilation property to specify default identation offset.
+ * Flag to indicate that the decompilation should omit the
+ * function header and trailing brace.
*/
- public static final int INDENT_GAP_PROP = 2;
+ public static final int ONLY_BODY_FLAG = 1 << 0;
/**
- * Decompilation property to specify identation offset for case labels.
+ * Flag to indicate that the decompilation generates toSource result.
*/
- public static final int CASE_GAP_PROP = 3;
+ public static final int TO_SOURCE_FLAG = 1 << 1;
// 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()
- {
+// whether to do a debug print of the source information, when decompiling.
+ private static final boolean printSource = false;
+ 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;
+
+ String getEncodedSource() {
return sourceToString(0);
}
- int getCurrentOffset()
- {
+ int getCurrentOffset() {
return sourceTop;
}
- int markFunctionStart(int functionType)
- {
+ int markFunctionStart(int functionType) {
int savedOffset = getCurrentOffset();
+
addToken(Token.FUNCTION);
- append((char)functionType);
+ append((char) functionType);
+
return savedOffset;
}
- int markFunctionEnd(int functionStart)
- {
+ int markFunctionEnd(int functionStart) {
int offset = getCurrentOffset();
- append((char)FUNCTION_END);
+
+ append((char) FUNCTION_END);
+
return offset;
}
- void addToken(int token)
- {
- if (!(0 <= token && token <= Token.LAST_TOKEN))
+ void addToken(int token) {
+ if (!(0 <= token && token <= Token.LAST_TOKEN)) {
throw new IllegalArgumentException();
+ }
- append((char)token);
+ append((char) token);
}
- void addEOL(int token)
- {
- if (!(0 <= token && token <= Token.LAST_TOKEN))
+ void addEOL(int token) {
+ if (!(0 <= token && token <= Token.LAST_TOKEN)) {
throw new IllegalArgumentException();
+ }
- append((char)token);
- append((char)Token.EOL);
+ append((char) token);
+ append((char) Token.EOL);
}
- void addName(String str)
- {
+ void addName(String str) {
addToken(Token.NAME);
appendString(str);
}
- void addString(String str)
- {
+ void addString(String str) {
addToken(Token.STRING);
appendString(str);
}
- void addRegexp(String regexp, String flags)
- {
+ void addRegexp(String regexp, String flags) {
addToken(Token.REGEXP);
appendString('/' + regexp + '/' + flags);
}
- void addJScriptConditionalComment(String str)
- {
+ void addJScriptConditionalComment(String str) {
addToken(Token.IECC);
appendString(str);
}
- void addNumber(double n)
- {
+ void addNumber(double n) {
addToken(Token.NUMBER);
- /* encode the number in the source stream.
+ /*
+ * 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;
- 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 {
+ 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();
+ 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((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);
+ append((char) (lbits >> 48));
+ append((char) (lbits >> 32));
+ append((char) (lbits >> 16));
+ append((char) lbits);
}
}
}
- private void appendString(String str)
- {
+ 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));
+ sourceBuffer[sourceTop] = (char) (0x8000 | (L >>> 16));
++sourceTop;
}
- sourceBuffer[sourceTop] = (char)L;
+
+ sourceBuffer[sourceTop] = (char) L;
++sourceTop;
str.getChars(0, L, sourceBuffer, sourceTop);
sourceTop = nextTop;
}
- private void append(char c)
- {
+ private void append(char c) {
if (sourceTop == sourceBuffer.length) {
increaseSourceCapacity(sourceTop + 1);
}
+
sourceBuffer[sourceTop] = c;
++sourceTop;
}
- private void increaseSourceCapacity(int minimalCapacity)
- {
+ private void increaseSourceCapacity(int minimalCapacity) {
+
// Call this only when capacity increase is must
- if (minimalCapacity <= sourceBuffer.length) Kit.codeBug();
+ 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();
+ private String sourceToString(int offset) {
+ if (offset < 0 || sourceTop < offset) {
+ Kit.codeBug();
+ }
+
return new String(sourceBuffer, offset, sourceTop - offset);
}
@@ -292,19 +313,31 @@
* @param properties indentation properties
*
*/
- public static String decompile(String source, int flags,
- UintMap properties)
- {
+ public static String decompile(String source, int flags, UintMap properties) {
int length = source.length();
- if (length == 0) { return ""; }
+ if (length == 0) {
+ return "";
+ }
+
int indent = properties.getInt(INITIAL_INDENT_PROP, 0);
- if (indent < 0) throw new IllegalArgumentException();
+
+ if (indent < 0) {
+ throw new IllegalArgumentException();
+ }
+
int indentGap = properties.getInt(INDENT_GAP_PROP, 4);
- if (indentGap < 0) throw new IllegalArgumentException();
+
+ if (indentGap < 0) {
+ throw new IllegalArgumentException();
+ }
+
int caseGap = properties.getInt(CASE_GAP_PROP, 2);
- if (caseGap < 0) throw new IllegalArgumentException();
+ 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));
@@ -313,26 +346,27 @@
// 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))
- + "'");
+
+ 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();
}
@@ -340,6 +374,7 @@
boolean afterFirstEOL = false;
int i = 0;
int topFunctionType;
+
if (source.charAt(i) == Token.SCRIPT) {
++i;
topFunctionType = -1;
@@ -348,10 +383,13 @@
}
if (!toSource) {
+
// add an initial newline to exactly match js.
result.append('\n');
- for (int j = 0; j < indent; j++)
+
+ for (int j = 0; j < indent; j++) {
result.append(' ');
+ }
} else {
if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) {
result.append('(');
@@ -359,473 +397,602 @@
}
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;
+ 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);
- case Token.NAME:
- case Token.REGEXP: // re-wrapped in '/'s in parser...
- i = printSourceString(source, i + 1, false, result);
- continue;
+ // Now increment one more to get past the FUNCTION token
+ ++i;
- case Token.STRING:
- i = printSourceString(source, i + 1, true, result);
- continue;
+ break;
- case Token.NUMBER:
- i = printSourceNumber(source, i + 1, result);
- continue;
+ case Token.NAME :
+ case Token.REGEXP : // re-wrapped in '/'s in parser...
+ i = printSourceString(source, i + 1, false, result);
- case Token.TRUE:
- result.append("true");
- break;
+ continue;
+ case Token.STRING :
+ i = printSourceString(source, i + 1, true, result);
- case Token.FALSE:
- result.append("false");
- break;
+ continue;
+ case Token.NUMBER :
+ i = printSourceNumber(source, i + 1, result);
- case Token.NULL:
- result.append("null");
- break;
+ continue;
+ case Token.TRUE :
+ result.append("true");
- case Token.THIS:
- result.append("this");
- break;
+ break;
- case Token.FUNCTION:
- ++i; // skip function type
- result.append("function ");
- break;
+ case Token.FALSE :
+ result.append("false");
- case FUNCTION_END:
- // Do nothing
- break;
+ break;
- case Token.COMMA:
- result.append(", ");
- break;
+ case Token.NULL :
+ result.append("null");
- case Token.LC:
- ++braceNesting;
- if (Token.EOL == getNext(source, length, i))
- indent += indentGap;
- result.append('{');
- break;
+ 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)
+ case Token.THIS :
+ result.append("this");
+
break;
- result.append('}');
- switch (getNext(source, length, i)) {
- case Token.EOL:
- case FUNCTION_END:
- indent -= indentGap;
+ 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;
- case Token.WHILE:
- case Token.ELSE:
- indent -= indentGap;
+ }
+
+ 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;
- }
- break;
- }
- case Token.LP:
- result.append('(');
- break;
+ }
- case Token.RP:
- result.append(')');
- if (Token.LC == getNext(source, length, i))
- result.append(' ');
- break;
+ boolean newLine = true;
- case Token.LB:
- result.append('[');
- break;
+ if (!afterFirstEOL) {
+ afterFirstEOL = true;
- case Token.RB:
- result.append(']');
- break;
+ if (justFunctionBody) {
- 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;
+ /*
+ * 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;
+ if (newLine) {
+ result.append('\n');
}
- /* elaborate check against label... skip past a
- * following inlined NAME and look for a COLON.
+ /*
+ * add indent if any tokens remain,
+ * less setback if next token is
+ * a label, case or default.
*/
- else if (nextToken == Token.NAME) {
- int afterName = getSourceStringEnd(source, i + 2);
- if (source.charAt(afterName) == Token.COLON)
+ 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(' ');
+ }
}
- for (; less < indent; less++)
- result.append(' ');
+ break;
}
- break;
- }
- case Token.DOT:
- result.append('.');
- break;
- case Token.NEW:
- result.append("new ");
- break;
+ case Token.DOT :
+ result.append('.');
- case Token.DELPROP:
- result.append("delete ");
- break;
+ break;
- case Token.IF:
- result.append("if ");
- break;
+ case Token.NEW :
+ result.append("new ");
- case Token.ELSE:
- result.append("else ");
- break;
+ break;
- case Token.FOR:
- result.append("for ");
- break;
+ case Token.DELPROP :
+ result.append("delete ");
- case Token.IN:
- result.append(" in ");
- break;
+ break;
- case Token.WITH:
- result.append("with ");
- break;
+ case Token.IF :
+ result.append("if ");
- case Token.WHILE:
- result.append("while ");
- break;
+ break;
- case Token.DO:
- result.append("do ");
- break;
+ case Token.ELSE :
+ result.append("else ");
- case Token.TRY:
- result.append("try ");
- break;
+ break;
- case Token.CATCH:
- result.append("catch ");
- break;
+ case Token.FOR :
+ result.append("for ");
- case Token.FINALLY:
- result.append("finally ");
- break;
+ break;
- case Token.THROW:
- result.append("throw ");
- break;
+ case Token.IN :
+ result.append(" in ");
- case Token.SWITCH:
- result.append("switch ");
- break;
+ break;
- case Token.BREAK:
- result.append("break");
- if (Token.NAME == getNext(source, length, i))
- result.append(' ');
- break;
+ case Token.WITH :
+ result.append("with ");
- case Token.CONTINUE:
- result.append("continue");
- if (Token.NAME == getNext(source, length, i))
- result.append(' ');
- break;
+ break;
- case Token.CASE:
- result.append("case ");
- break;
+ case Token.WHILE :
+ result.append("while ");
- case Token.DEFAULT:
- result.append("default");
- break;
+ break;
- case Token.RETURN:
- result.append("return");
- if (Token.SEMI != getNext(source, length, i))
- result.append(' ');
- break;
+ case Token.DO :
+ result.append("do ");
- case Token.VAR:
- result.append("var ");
- break;
+ break;
- case Token.SEMI:
- result.append(';');
- if (Token.EOL != getNext(source, length, i)) {
- // separators in FOR
- result.append(' ');
- }
- break;
+ case Token.TRY :
+ result.append("try ");
- case Token.ASSIGN:
- result.append(" = ");
- break;
+ break;
- case Token.ASSIGN_ADD:
- result.append(" += ");
- break;
+ case Token.CATCH :
+ result.append("catch ");
- case Token.ASSIGN_SUB:
- result.append(" -= ");
- break;
+ break;
- case Token.ASSIGN_MUL:
- result.append(" *= ");
- break;
+ case Token.FINALLY :
+ result.append("finally ");
- case Token.ASSIGN_DIV:
- result.append(" /= ");
- break;
+ break;
- case Token.ASSIGN_MOD:
- result.append(" %= ");
- break;
+ case Token.THROW :
+ result.append("throw ");
- case Token.ASSIGN_BITOR:
- result.append(" |= ");
- break;
+ break;
- case Token.ASSIGN_BITXOR:
- result.append(" ^= ");
- break;
+ case Token.SWITCH :
+ result.append("switch ");
- case Token.ASSIGN_BITAND:
- result.append(" &= ");
- break;
+ break;
- case Token.ASSIGN_LSH:
- result.append(" <<= ");
- break;
+ case Token.BREAK :
+ result.append("break");
- case Token.ASSIGN_RSH:
- result.append(" >>= ");
- break;
+ if (Token.NAME == getNext(source, length, i)) {
+ result.append(' ');
+ }
- case Token.ASSIGN_URSH:
- result.append(" >>>= ");
- break;
+ break;
- case Token.HOOK:
- result.append(" ? ");
- break;
+ case Token.CONTINUE :
+ result.append("continue");
- 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;
+ if (Token.NAME == getNext(source, length, i)) {
+ result.append(' ');
+ }
- case Token.COLON:
- if (Token.EOL == getNext(source, length, i))
- // it's the end of a label
+ 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(':');
- else
- // it's the middle part of a ternary
- result.append(" : ");
- break;
- case Token.OR:
- result.append(" || ");
- break;
+ break;
- case Token.AND:
- result.append(" && ");
- break;
+ case Token.COLON :
+ if (Token.EOL == getNext(source, length, i)) {
- case Token.BITOR:
- result.append(" | ");
- break;
+ // it's the end of a label
+ result.append(':');
+ } else {
- case Token.BITXOR:
- result.append(" ^ ");
- break;
+ // it's the middle part of a ternary
+ result.append(" : ");
+ }
- case Token.BITAND:
- result.append(" & ");
- break;
+ break;
- case Token.SHEQ:
- result.append(" === ");
- break;
+ case Token.OR :
+ result.append(" || ");
- case Token.SHNE:
- result.append(" !== ");
- break;
+ break;
- case Token.EQ:
- result.append(" == ");
- break;
+ case Token.AND :
+ result.append(" && ");
- case Token.NE:
- result.append(" != ");
- break;
+ break;
- case Token.LE:
- result.append(" <= ");
- break;
+ case Token.BITOR :
+ result.append(" | ");
- case Token.LT:
- result.append(" < ");
- break;
+ break;
- case Token.GE:
- result.append(" >= ");
- break;
+ case Token.BITXOR :
+ result.append(" ^ ");
- case Token.GT:
- result.append(" > ");
- break;
+ break;
- case Token.INSTANCEOF:
- result.append(" instanceof ");
- break;
+ case Token.BITAND :
+ result.append(" & ");
- case Token.LSH:
- result.append(" << ");
- break;
+ break;
- case Token.RSH:
- result.append(" >> ");
- break;
+ case Token.SHEQ :
+ result.append(" === ");
- case Token.URSH:
- result.append(" >>> ");
- break;
+ break;
- case Token.TYPEOF:
- result.append("typeof ");
- break;
+ case Token.SHNE :
+ result.append(" !== ");
- case Token.VOID:
- result.append("void ");
- break;
+ break;
- case Token.CONST:
- result.append("const ");
- break;
+ case Token.EQ :
+ result.append(" == ");
- case Token.NOT:
- result.append('!');
- break;
+ break;
- case Token.BITNOT:
- result.append('~');
- break;
+ case Token.NE :
+ result.append(" != ");
- case Token.POS:
- result.append('+');
- break;
+ break;
- case Token.NEG:
- result.append('-');
- break;
+ case Token.LE :
+ result.append(" <= ");
- case Token.INC:
- result.append("++");
- break;
+ break;
- case Token.DEC:
- result.append("--");
- break;
+ case Token.LT :
+ result.append(" < ");
- case Token.ADD:
- result.append(" + ");
- break;
+ break;
- case Token.SUB:
- result.append(" - ");
- break;
+ case Token.GE :
+ result.append(" >= ");
- case Token.MUL:
- result.append(" * ");
- break;
+ break;
- case Token.DIV:
- result.append(" / ");
- break;
+ case Token.GT :
+ result.append(" > ");
- case Token.MOD:
- result.append(" % ");
- break;
+ break;
- case Token.COLONCOLON:
- result.append("::");
- break;
+ case Token.INSTANCEOF :
+ result.append(" instanceof ");
- case Token.DOTDOT:
- result.append("..");
- break;
+ break;
- case Token.DOTQUERY:
- result.append(".(");
- break;
+ case Token.LSH :
+ result.append(" << ");
- case Token.XMLATTR:
- result.append('@');
- break;
+ break;
- default:
- // If we don't know how to decompile it, raise an exception.
- throw new RuntimeException("Token: " +
- Token.name(source.charAt(i)));
+ 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)
+ if (!justFunctionBody) {
result.append('\n');
+ }
} else {
if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION) {
result.append(')');
@@ -835,28 +1002,27 @@
return result.toString();
}
- private static int getNext(String source, int length, int i)
- {
+ 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)
- {
+ 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)
- {
+ 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 {
@@ -865,52 +1031,51 @@
sb.append('"');
}
}
+
return offset + length;
}
- private static int printSourceNumber(String source, int offset,
- StringBuffer sb)
- {
+ 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 = (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;
-
}
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Parser.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -43,10 +43,13 @@
*
* ***** END LICENSE BLOCK ***** */
+
+
package org.mozilla.javascript;
import java.io.Reader;
import java.io.IOException;
+
import java.util.Hashtable;
/**
@@ -60,97 +63,81 @@
* @author Mike McCabe
* @author Brendan Eich
*/
+public class Parser {
-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
-
+ 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
+ boolean calledByCompileFunction;
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;
-
+// The following are per function variables and should be saved/restored
+// during function parsing.
+// XXX Move to separated class?
+ ScriptOrFnNode currentScriptOrFn;
private Decompiler decompiler;
private String encodedSource;
+ private ErrorReporter errorReporter;
+ private int functionEndFlags;
-// The following are per function variables and should be saved/restored
-// during function parsing.
-// XXX Move to separated class?
- ScriptOrFnNode currentScriptOrFn;
- private int nestingOfWith;
+// end of per function variables
+ private boolean hasReturnValue;
private Hashtable labelSet; // map of label names into nodes
+ private ObjArray loopAndSwitchSet;
private ObjArray loopSet;
- private ObjArray loopAndSwitchSet;
- private boolean hasReturnValue;
- private int functionEndFlags;
-// end of per function variables
+ private int nestingOfFunction;
+ private int nestingOfWith;
+ private IRFactory nf;
+ private String sourceURI;
+ private int syntaxErrorCount;
+ private TokenStream ts;
- // Exception to unwind
- private static class ParserException extends RuntimeException
- {
- static final long serialVersionUID = 5882582646773765630L;
- }
-
- public Parser(CompilerEnvirons compilerEnv, ErrorReporter errorReporter)
- {
+ public Parser(CompilerEnvirons compilerEnv, ErrorReporter errorReporter) {
this.compilerEnv = compilerEnv;
this.errorReporter = errorReporter;
}
- protected Decompiler createDecompiler(CompilerEnvirons compilerEnv)
- {
+ protected Decompiler createDecompiler(CompilerEnvirons compilerEnv) {
return new Decompiler();
}
- void addStrictWarning(String messageId, String messageArg)
- {
- if (compilerEnv.isStrictMode())
+ void addStrictWarning(String messageId, String messageArg) {
+ if (compilerEnv.isStrictMode()) {
addWarning(messageId, messageArg);
+ }
}
- void addWarning(String messageId, String 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());
+ 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)
- {
+ void addError(String messageId) {
++syntaxErrorCount;
+
String message = ScriptRuntime.getMessage0(messageId);
- errorReporter.error(message, sourceURI, ts.getLineno(),
- ts.getLine(), ts.getOffset());
+
+ errorReporter.error(message, sourceURI, ts.getLineno(), ts.getLine(),
ts.getOffset());
}
- void addError(String messageId, String messageArg)
- {
+ void addError(String messageId, String messageArg) {
++syntaxErrorCount;
+
String message = ScriptRuntime.getMessage1(messageId, messageArg);
- errorReporter.error(message, sourceURI, ts.getLineno(),
- ts.getLine(), ts.getOffset());
+
+ errorReporter.error(message, sourceURI, ts.getLineno(), ts.getLine(),
ts.getOffset());
}
- RuntimeException reportError(String messageId)
- {
+ RuntimeException reportError(String messageId) {
addError(messageId);
// Throw a ParserException exception to unwind the recursive descent
@@ -158,13 +145,12 @@
throw new ParserException();
}
- private int peekToken()
- throws IOException
- {
+ private int peekToken() throws IOException {
int tt = currentFlaggedToken;
+
if (tt == Token.EOF) {
+ while ((tt = ts.getToken()) == Token.IECC) {
- while ((tt = ts.getToken()) == Token.IECC) {
/* Support for JScript conditional comments */
decompiler.addJScriptConditionalComment(ts.getString());
}
@@ -174,138 +160,139 @@
tt = ts.getToken();
if (tt == Token.IECC) {
+
/* Support for JScript conditional comments */
decompiler.addJScriptConditionalComment(ts.getString());
}
+ } while (tt == Token.EOL || tt == Token.IECC);
- } while (tt == Token.EOL || tt == Token.IECC);
tt |= TI_AFTER_EOL;
}
+
currentFlaggedToken = tt;
}
+
return tt & CLEAR_TI_MASK;
}
- private int peekFlaggedToken()
- throws IOException
- {
+ private int peekFlaggedToken() throws IOException {
peekToken();
+
return currentFlaggedToken;
}
- private void consumeToken()
- {
+ private void consumeToken() {
currentFlaggedToken = Token.EOF;
}
- private int nextToken()
- throws IOException
- {
+ private int nextToken() throws IOException {
int tt = peekToken();
+
consumeToken();
+
return tt;
}
- private int nextFlaggedToken()
- throws IOException
- {
+ private int nextFlaggedToken() throws IOException {
peekToken();
+
int ttFlagged = currentFlaggedToken;
+
consumeToken();
+
return ttFlagged;
}
- private boolean matchToken(int toMatch)
- throws IOException
- {
+ private boolean matchToken(int toMatch) throws IOException {
int tt = peekToken();
+
if (tt != toMatch) {
return false;
}
+
consumeToken();
+
return true;
}
- private int peekTokenOrEOL()
- throws IOException
- {
+ 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)
+ 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
- {
+ private void mustMatchToken(int toMatch, String messageId) throws IOException,
ParserException {
if (!matchToken(toMatch)) {
reportError(messageId);
}
}
- private void mustHaveXML()
- {
+ private void mustHaveXML() {
if (!compilerEnv.isXmlAvailable()) {
reportError("msg.XML.not.available");
}
}
- public String getEncodedSource()
- {
+ public String getEncodedSource() {
return encodedSource;
}
- public boolean eof()
- {
+ public boolean eof() {
return ts.eof();
}
- boolean insideFunction()
- {
+ boolean insideFunction() {
return nestingOfFunction != 0;
}
- private Node enterLoop(Node loopLabel)
- {
+ 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()
- {
+ private void exitLoop() {
loopSet.pop();
loopAndSwitchSet.pop();
}
- private Node enterSwitch(Node switchSelector, int lineno)
- {
+ 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()
- {
+ private void exitSwitch() {
loopAndSwitchSet.pop();
}
@@ -317,14 +304,14 @@
* parse failure will result in a call to the ErrorReporter from
* CompilerEnvirons.)
*/
- public ScriptOrFnNode parse(String sourceString,
- String sourceURI, int lineno)
- {
+ 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();
}
@@ -338,32 +325,31 @@
* parse failure will result in a call to the ErrorReporter from
* CompilerEnvirons.)
*/
- public ScriptOrFnNode parse(Reader sourceReader,
- String sourceURI, int lineno)
- throws IOException
- {
+ 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
- {
+ 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
+ int baseLineno = ts.getLineno(); // line number where source starts
- /* so we have something to add nodes to until
- * we've collected all the source */
+ /*
+ * so we have something to add nodes to until
+ * we've collected all the source
+ */
Node pn = nf.createLeaf(Token.BLOCK);
try {
@@ -375,32 +361,34 @@
}
Node n;
+
if (tt == Token.FUNCTION) {
consumeToken();
+
try {
n = function(calledByCompileFunction
- ? FunctionNode.FUNCTION_EXPRESSION
- : FunctionNode.FUNCTION_STATEMENT);
+ ? 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);
+ 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);
+
+ throw errorReporter.runtimeError(msg, sourceURI, baseLineno, null, 0);
}
currentScriptOrFn.setSourceName(sourceURI);
@@ -408,14 +396,14 @@
currentScriptOrFn.setEndLineno(ts.getLineno());
int sourceEndOffset = decompiler.getCurrentOffset();
- currentScriptOrFn.setEncodedSourceBounds(sourceStartOffset,
- sourceEndOffset);
+ currentScriptOrFn.setEncodedSourceBounds(sourceStartOffset, sourceEndOffset);
nf.initScript(currentScriptOrFn, pn);
if (compilerEnv.isGeneratingSource()) {
encodedSource = decompiler.getEncodedSource();
}
+
this.decompiler = null; // It helps GC
return currentScriptOrFn;
@@ -427,32 +415,38 @@
* it'd only be useful for checking argument hiding, which
* I'm not doing anyway...
*/
- private Node parseFunctionBody()
- throws IOException
- {
+ private Node parseFunctionBody() throws IOException {
++nestingOfFunction;
+
Node pn = nf.createBlock(ts.getLineno());
+
try {
- bodyLoop: for (;;) {
+ bodyLoop:for (;;) {
Node n;
int tt = peekToken();
+
switch (tt) {
- case Token.ERROR:
- case Token.EOF:
- case Token.RC:
- break bodyLoop;
+ 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;
+ 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;
@@ -461,39 +455,45 @@
return pn;
}
- private Node function(int functionType)
- throws IOException, ParserException
- {
+ private Node function(int functionType) throws IOException, ParserException {
int syntheticType = functionType;
- int baseLineno = ts.getLineno(); // line number where source starts
-
+ 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");
}
@@ -502,9 +502,10 @@
}
boolean nested = insideFunction();
+ FunctionNode fnNode = nf.createFunction(name);
- 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
@@ -514,65 +515,80 @@
}
int functionIndex = currentScriptOrFn.addFunction(fnNode);
-
int functionSourceEnd;
+ ScriptOrFnNode savedScriptOrFn = currentScriptOrFn;
- 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;
- Node body;
try {
decompiler.addToken(Token.LP);
+
if (!matchToken(Token.RP)) {
boolean first = true;
+
do {
- if (!first)
+ 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);
+ 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 {
+ } finally {
hasReturnValue = savedHasReturnValue;
functionEndFlags = savedFunctionEndFlags;
loopAndSwitchSet = savedLoopAndSwitchSet;
@@ -588,69 +604,74 @@
fnNode.setEndLineno(ts.getLineno());
if (name != null) {
- int index = currentScriptOrFn.getParamOrVarIndex(name);
- if (index >= 0 && index < currentScriptOrFn.getParamCount())
- addStrictWarning("msg.var.hides.arg", name);
+ 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
- {
+ private Node statements() throws IOException {
Node pn = nf.createBlock(ts.getLineno());
+ int tt;
- int tt;
- while((tt = peekToken()) > Token.EOF && tt != Token.RC) {
+ while ((tt = peekToken()) > Token.EOF && tt != Token.RC) {
nf.addChildToBack(pn, statement());
}
return pn;
}
- private Node condition()
- throws IOException, ParserException
- {
+ 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))
- {
+ 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
- {
+ private Node matchJumpLabelName() throws IOException, ParserException {
Node label = null;
+ int tt = peekTokenOrEOL();
- int tt = peekTokenOrEOL();
if (tt == Token.NAME) {
consumeToken();
+
String name = ts.getString();
+
decompiler.addName(name);
+
if (labelSet != null) {
- label = (Node)labelSet.get(name);
+ label = (Node) labelSet.get(name);
}
+
if (label == null) {
reportError("msg.undef.label");
}
@@ -659,31 +680,36 @@
return label;
}
- private Node statement()
- throws IOException
- {
+ private Node statement() throws IOException {
try {
Node pn = statementHelper(null);
+
if (pn != null) {
- if (compilerEnv.isStrictMode() && !pn.hasSideEffects())
+ if (compilerEnv.isStrictMode() && !pn.hasSideEffects()) {
addStrictWarning("msg.no.side.effects", "");
+ }
+
return pn;
}
- } catch (ParserException e) { }
+ } catch (ParserException e) {}
// skip to end of statement
int lineno = ts.getLineno();
- guessingStatementEnd: for (;;) {
+
+ guessingStatementEnd:for (;;) {
int tt = peekTokenOrEOL();
+
consumeToken();
+
switch (tt) {
- case Token.ERROR:
- case Token.EOF:
- case Token.EOL:
- case Token.SEMI:
- break guessingStatementEnd;
+ case Token.ERROR :
+ case Token.EOF :
+ case Token.EOL :
+ case Token.SEMI :
+ break guessingStatementEnd;
}
}
+
return nf.createExprStatement(nf.createName("error"), lineno);
}
@@ -691,552 +717,646 @@
* Whether the "catch (e: e instanceof Exception) { ... }" syntax
* is implemented.
*/
-
- private Node statementHelper(Node statementLabel)
- throws IOException, ParserException
- {
+ private Node statementHelper(Node statementLabel) throws IOException, ParserException
{
Node pn = null;
-
int tt;
tt = peekToken();
- switch(tt) {
- case Token.IF: {
- consumeToken();
+ switch (tt) {
+ case Token.IF : {
+ consumeToken();
+ decompiler.addToken(Token.IF);
- 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);
+ int lineno = ts.getLineno();
+ Node cond = condition();
+
decompiler.addEOL(Token.LC);
- ifFalse = statement();
+
+ 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;
}
- decompiler.addEOL(Token.RC);
- pn = nf.createIf(cond, ifTrue, ifFalse, lineno);
- return pn;
- }
- case Token.SWITCH: {
- consumeToken();
+ case Token.SWITCH : {
+ consumeToken();
+ decompiler.addToken(Token.SWITCH);
- 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);
+ int lineno = ts.getLineno();
- boolean hasDefault = false;
- switchLoop: for (;;) {
- tt = nextToken();
- Node caseExpression;
- switch (tt) {
- case Token.RC:
- break switchLoop;
+ mustMatchToken(Token.LP, "msg.no.paren.switch");
+ decompiler.addToken(Token.LP);
+ pn = enterSwitch(expr(false), lineno);
- case Token.CASE:
- decompiler.addToken(Token.CASE);
- caseExpression = expr(false);
- mustMatchToken(Token.COLON, "msg.no.colon.case");
- decompiler.addEOL(Token.COLON);
- break;
+ try {
+ mustMatchToken(Token.RP, "msg.no.paren.after.switch");
+ decompiler.addToken(Token.RP);
+ mustMatchToken(Token.LC, "msg.no.brace.switch");
+ decompiler.addEOL(Token.LC);
- case Token.DEFAULT:
- if (hasDefault) {
- reportError("msg.double.switch.default");
+ 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;
}
- 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);
- Node block = nf.createLeaf(Token.BLOCK);
- while ((tt = peekToken()) != Token.RC
- && tt != Token.CASE
- && tt != Token.DEFAULT
- && tt != Token.EOF)
- {
- nf.addChildToBack(block, statement());
+ 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);
}
- // caseExpression == null => add default lable
- nf.addSwitchCase(pn, caseExpression, block);
+ decompiler.addEOL(Token.RC);
+ nf.closeSwitch(pn);
+ } finally {
+ exitSwitch();
}
- decompiler.addEOL(Token.RC);
- nf.closeSwitch(pn);
- } finally {
- exitSwitch();
+
+ return pn;
}
- return pn;
- }
- case Token.WHILE: {
- consumeToken();
- decompiler.addToken(Token.WHILE);
+ 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();
+ 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;
}
- return pn;
- }
- case Token.DO: {
- consumeToken();
- decompiler.addToken(Token.DO);
- decompiler.addEOL(Token.LC);
+ 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();
+ 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;
}
- // 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);
+ case Token.FOR : {
+ consumeToken();
- Node loop = enterLoop(statementLabel);
- try {
+ boolean isForEach = false;
- 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;
+ decompiler.addToken(Token.FOR);
- // 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");
+ 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);
+ 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);
+ }
}
- 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 {
+ 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.SEMI, "msg.no.semi.for.cond");
- decompiler.addToken(Token.SEMI);
- if (peekToken() == Token.RP) {
- incr = nf.createLeaf(Token.EMPTY);
+ 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 {
- incr = expr(false);
+ pn = nf.createFor(loop, init, cond, incr, body);
}
+ } finally {
+ exitLoop();
}
- mustMatchToken(Token.RP, "msg.no.paren.for.ctrl");
- decompiler.addToken(Token.RP);
+ 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);
- body = statement();
+ tryblock = statement();
decompiler.addEOL(Token.RC);
+ catchblocks = nf.createLeaf(Token.BLOCK);
- 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;
- }
+ boolean sawDefaultCatch = false;
+ int peek = peekToken();
- case Token.TRY: {
- consumeToken();
- int lineno = ts.getLineno();
+ if (peek == Token.CATCH) {
+ while (matchToken(Token.CATCH)) {
+ if (sawDefaultCatch) {
+ reportError("msg.catch.unreachable");
+ }
- Node tryblock;
- Node catchblocks = null;
- Node finallyblock = null;
+ decompiler.addToken(Token.CATCH);
+ mustMatchToken(Token.LP, "msg.no.paren.catch");
+ decompiler.addToken(Token.LP);
+ mustMatchToken(Token.NAME, "msg.bad.catchcond");
- decompiler.addToken(Token.TRY);
- decompiler.addEOL(Token.LC);
- tryblock = statement();
- decompiler.addEOL(Token.RC);
+ String varName = ts.getString();
- catchblocks = nf.createLeaf(Token.BLOCK);
+ decompiler.addName(varName);
- 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);
+ Node catchCond = null;
- mustMatchToken(Token.NAME, "msg.bad.catchcond");
- String varName = ts.getString();
- decompiler.addName(varName);
+ if (matchToken(Token.IF)) {
+ decompiler.addToken(Token.IF);
+ catchCond = expr(false);
+ } else {
+ sawDefaultCatch = true;
+ }
- 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");
+ }
- mustMatchToken(Token.RP, "msg.bad.catchcond");
- decompiler.addToken(Token.RP);
- mustMatchToken(Token.LC, "msg.no.brace.catchblock");
+ if (matchToken(Token.FINALLY)) {
+ decompiler.addToken(Token.FINALLY);
decompiler.addEOL(Token.LC);
-
- nf.addChildToBack(catchblocks,
- nf.createCatch(varName, catchCond,
- statements(),
- ts.getLineno()));
-
- mustMatchToken(Token.RC, "msg.no.brace.after.body");
+ finallyblock = statement();
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;
}
- pn = nf.createTryCatchFinally(tryblock, catchblocks,
- finallyblock, lineno);
+ case Token.THROW : {
+ consumeToken();
- return pn;
- }
+ if (peekTokenOrEOL() == Token.EOL) {
- 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");
+ // 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;
}
- int lineno = ts.getLineno();
- decompiler.addToken(Token.THROW);
- pn = nf.createThrow(expr(false), lineno);
- break;
- }
+ case Token.BREAK : {
+ consumeToken();
- case Token.BREAK: {
- consumeToken();
- int lineno = ts.getLineno();
+ int lineno = ts.getLineno();
- decompiler.addToken(Token.BREAK);
+ 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;
+ // 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();
}
- breakStatement = (Node)loopAndSwitchSet.peek();
+
+ pn = nf.createBreak(breakStatement, lineno);
+
+ break;
}
- pn = nf.createBreak(breakStatement, lineno);
- break;
- }
- case Token.CONTINUE: {
- consumeToken();
- int lineno = ts.getLineno();
+ case Token.CONTINUE : {
+ consumeToken();
- decompiler.addToken(Token.CONTINUE);
+ int lineno = ts.getLineno();
- 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;
+ 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;
+ }
}
- loop = (Node)loopSet.peek();
- } else {
- loop = nf.getLabelLoop(label);
- if (loop == null) {
- reportError("msg.continue.nonloop");
- return null;
- }
+
+ pn = nf.createContinue(loop, lineno);
+
+ break;
}
- pn = nf.createContinue(loop, lineno);
- break;
- }
- case Token.WITH: {
- consumeToken();
+ case Token.WITH : {
+ consumeToken();
+ decompiler.addToken(Token.WITH);
- 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);
+ int lineno = ts.getLineno();
- ++nestingOfWith;
- Node body;
- try {
- body = statement();
- } finally {
- --nestingOfWith;
- }
+ mustMatchToken(Token.LP, "msg.no.paren.with");
+ decompiler.addToken(Token.LP);
- decompiler.addEOL(Token.RC);
+ Node obj = expr(false);
- pn = nf.createWith(obj, body, lineno);
- return pn;
- }
+ mustMatchToken(Token.RP, "msg.no.paren.after.with");
+ decompiler.addToken(Token.RP);
+ decompiler.addEOL(Token.LC);
+ ++nestingOfWith;
- case Token.CONST:
- case Token.VAR: {
- consumeToken();
- pn = variables(tt);
- break;
- }
+ Node body;
- case Token.RETURN: {
- if (!insideFunction()) {
- reportError("msg.bad.return");
+ try {
+ body = statement();
+ } finally {
+ --nestingOfWith;
+ }
+
+ decompiler.addEOL(Token.RC);
+ pn = nf.createWith(obj, body, lineno);
+
+ return pn;
}
- 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;
+ case Token.CONST :
+ case Token.VAR : {
+ consumeToken();
+ pn = variables(tt);
+
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", "");
+ case Token.RETURN : {
+ if (!insideFunction()) {
+ reportError("msg.bad.return");
+ }
- functionEndFlags |= Node.END_RETURNS;
- } else {
- if (functionEndFlags == Node.END_RETURNS)
- addStrictWarning("msg.return.inconsistent", "");
+ consumeToken();
+ decompiler.addToken(Token.RETURN);
- functionEndFlags |= Node.END_RETURNS_VALUE;
- }
+ int lineno = ts.getLineno();
+ Node retExpr;
- break;
- }
+ /* This is ugly, but we don't want to require a semicolon. */
+ tt = peekTokenOrEOL();
- 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;
+ switch (tt) {
+ case Token.SEMI :
+ case Token.RC :
+ case Token.EOF :
+ case Token.EOL :
+ case Token.ERROR :
+ retExpr = null;
- 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;
+ break;
- case Token.FUNCTION: {
- consumeToken();
- pn = function(FunctionNode.FUNCTION_EXPRESSION_STATEMENT);
- return pn;
- }
+ default :
+ retExpr = expr(false);
+ hasReturnValue = true;
+ }
- case Token.DEFAULT :
- consumeToken();
- mustHaveXML();
+ pn = nf.createReturn(retExpr, lineno);
- decompiler.addToken(Token.DEFAULT);
- int nsLine = ts.getLineno();
+ // see if we need a strict mode warning
+ if (retExpr == null) {
+ if (functionEndFlags == Node.END_RETURNS_VALUE) {
+ addStrictWarning("msg.return.inconsistent",
"");
+ }
- if (!(matchToken(Token.NAME)
- && ts.getString().equals("xml")))
- {
- reportError("msg.bad.namespace");
- }
- decompiler.addName(" xml");
+ functionEndFlags |= Node.END_RETURNS;
+ } else {
+ if (functionEndFlags == Node.END_RETURNS) {
+ addStrictWarning("msg.return.inconsistent",
"");
+ }
- if (!(matchToken(Token.NAME)
- && ts.getString().equals("namespace")))
- {
- reportError("msg.bad.namespace");
- }
- decompiler.addName(" namespace");
+ functionEndFlags |= Node.END_RETURNS_VALUE;
+ }
- if (!matchToken(Token.ASSIGN)) {
- reportError("msg.bad.namespace");
+ break;
}
- decompiler.addToken(Token.ASSIGN);
- Node expr = expr(false);
- pn = nf.createDefaultNamespace(expr, nsLine);
- break;
+ case Token.LC :
+ consumeToken();
- 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();
+ 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();
- // depend on decompiling lookahead to guess that that
- // last name was a label.
- decompiler.addName(name);
- decompiler.addEOL(Token.COLON);
+ pn = nf.createLeaf(Token.EMPTY);
- if (labelSet == null) {
- labelSet = new Hashtable();
- } else if (labelSet.containsKey(name)) {
- reportError("msg.dup.label");
+ 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");
}
- 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;
+ decompiler.addName(" xml");
+
+ if (!(matchToken(Token.NAME) &&
ts.getString().equals("namespace"))) {
+ reportError("msg.bad.namespace");
}
- labelSet.put(name, statementLabel);
- try {
- pn = statementHelper(statementLabel);
- } finally {
- labelSet.remove(name);
+
+ decompiler.addName(" namespace");
+
+ if (!matchToken(Token.ASSIGN)) {
+ reportError("msg.bad.namespace");
}
- if (firstLabel) {
- pn = nf.createLabeledStatement(statementLabel, pn);
+
+ 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;
}
- return pn;
+
+ break;
}
- break;
- }
- default: {
- int lineno = ts.getLineno();
- pn = expr(false);
- pn = nf.createExprStatement(pn, lineno);
- 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;
+ 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;
@@ -1251,13 +1371,11 @@
* @throws IOException
* @throws ParserException
*/
- private Node variables(int context)
- throws IOException, ParserException
- {
+ private Node variables(int context) throws IOException, ParserException {
Node pn;
boolean first = true;
- if (context == Token.CONST){
+ if (context == Token.CONST) {
pn = nf.createVariables(Token.CONST, ts.getLineno());
decompiler.addToken(Token.CONST);
} else {
@@ -1268,70 +1386,81 @@
for (;;) {
Node name;
Node init;
+
mustMatchToken(Token.NAME, "msg.bad.var");
+
String s = ts.getString();
- if (!first)
+ 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)
+ if (currentScriptOrFn.addVar(s) != ScriptOrFnNode.DUPLICATE_CONST) {
addError("msg.var.redecl", s);
- else
+ } else {
addError("msg.const.redecl", s);
+ }
}
} else {
int dupState = currentScriptOrFn.addVar(s);
- if (dupState == ScriptOrFnNode.DUPLICATE_CONST)
+
+ if (dupState == ScriptOrFnNode.DUPLICATE_CONST) {
addError("msg.const.redecl", s);
- else if (dupState == ScriptOrFnNode.DUPLICATE_PARAMETER)
+ } else if (dupState == ScriptOrFnNode.DUPLICATE_PARAMETER) {
addStrictWarning("msg.var.hides.arg", s);
- else if (dupState == ScriptOrFnNode.DUPLICATE_VAR)
+ } 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))
+
+ if (!matchToken(Token.COMMA)) {
break;
+ }
}
+
return pn;
}
- private Node expr(boolean inForInit)
- throws IOException, ParserException
- {
+ 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())
+
+ 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
- {
+ private Node assignExpr(boolean inForInit) throws IOException, ParserException {
Node pn = condExpr(inForInit);
+ int tt = peekToken();
- int tt = peekToken();
if (Token.FIRST_ASSIGN <= tt && tt <= Token.LAST_ASSIGN) {
consumeToken();
decompiler.addToken(tt);
@@ -1341,27 +1470,28 @@
return pn;
}
- private Node condExpr(boolean inForInit)
- throws IOException, ParserException
- {
+ 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
- {
+ 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));
@@ -1370,10 +1500,9 @@
return pn;
}
- private Node andExpr(boolean inForInit)
- throws IOException, ParserException
- {
+ 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));
@@ -1382,334 +1511,382 @@
return pn;
}
- private Node bitOrExpr(boolean inForInit)
- throws IOException, ParserException
- {
+ 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
- {
+ 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
- {
+ 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
- {
+ 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;
+ 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;
+
+ decompiler.addToken(decompilerToken);
+ pn = nf.createBinary(parseToken, pn, relExpr(inForInit));
+
+ continue;
}
+
break;
}
+
return pn;
}
- private Node relExpr(boolean inForInit)
- throws IOException, ParserException
- {
+ private Node relExpr(boolean inForInit) throws IOException, ParserException {
Node pn = shiftExpr();
+
for (;;) {
int tt = peekToken();
+
switch (tt) {
- case Token.IN:
- if (inForInit)
- break;
+ 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;
+ 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
- {
+ 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;
+ 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
- {
+ 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
- {
+ 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;
+ 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
- {
+ 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());
+ switch (tt) {
+ case Token.VOID :
+ case Token.NOT :
+ case Token.BITNOT :
+ case Token.TYPEOF :
+ consumeToken();
+ decompiler.addToken(tt);
- case Token.ADD:
- consumeToken();
- // Convert to special POS token in decompiler and parse tree
- decompiler.addToken(Token.POS);
- return nf.createUnary(Token.POS, unaryExpr());
+ return nf.createUnary(tt, 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.ADD :
+ consumeToken();
- case Token.INC:
- case Token.DEC:
- consumeToken();
- decompiler.addToken(tt);
- return nf.createIncDec(tt, false, memberExpr(true));
+ // Convert to special POS token in decompiler and parse tree
+ decompiler.addToken(Token.POS);
- case Token.DELPROP:
- consumeToken();
- decompiler.addToken(Token.DELPROP);
- return nf.createUnary(Token.DELPROP, unaryExpr());
+ return nf.createUnary(Token.POS, unaryExpr());
- case Token.ERROR:
- consumeToken();
- break;
+ case Token.SUB :
+ consumeToken();
- // XML stream encountered in expression.
- case Token.LT:
- if (compilerEnv.isXmlAvailable()) {
+ // 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();
- Node pn = xmlInitializer();
- return memberExprTail(true, pn);
- }
+ 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);
- default:
- Node pn = memberExpr(true);
+ // Don't look across a newline boundary for a postfix incop.
+ tt = peekTokenOrEOL();
- // 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;
+ 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
- {
+ 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");
- Node pn = nf.createName(fAnonymous ? "XMLList" : "XML");
nf.addChildToBack(pnXML, pn);
+ pn = null;
- pn = null;
Node expr;
- for (;;tt = ts.getNextXMLToken()) {
+
+ 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));
- }
+ 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);
- nf.addChildToBack(pnXML, pn);
- return pnXML;
- default:
- reportError("msg.syntax");
- return null;
+ 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
- {
+ private void argumentList(Node listNode) throws IOException, ParserException {
boolean matched;
+
matched = matchToken(Token.RP);
+
if (!matched) {
boolean first = true;
+
do {
- if (!first)
+ 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
- {
+ 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);
@@ -1719,20 +1896,24 @@
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
+ /*
+ * 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,
+ /*
+ * 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());
}
@@ -1743,95 +1924,106 @@
return memberExprTail(allowCallSyntax, pn);
}
- private Node memberExprTail(boolean allowCallSyntax, Node pn)
- throws IOException, ParserException
- {
- tailLoop:
- for (;;) {
+ private Node memberExprTail(boolean allowCallSyntax, Node pn) throws IOException,
ParserException {
+ tailLoop:for (;;) {
int tt = peekToken();
+
switch (tt) {
-
- case Token.DOT:
- case Token.DOTDOT:
- {
+ 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: name, ns::name, ns::*, ns::[expr]
+ case Token.NAME :
+ s = ts.getString();
+ decompiler.addName(s);
+ pn = propertyName(pn, s, memberTypeFlags);
- // handles: '@attr', '@ns::attr', '@ns::*',
'@ns::*',
- // '@::attr', '@::*', '@*',
'@*::attr', '@*::*'
- case Token.XMLATTR:
- decompiler.addToken(Token.XMLATTR);
- pn = attributeAccess(pn, memberTypeFlags);
- break;
+ break;
- default:
- reportError("msg.no.name.after.dot");
+ // 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.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);
- case Token.LP:
- if (!allowCallSyntax) {
+ 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;
- }
- 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;
}
@@ -1839,40 +2031,44 @@
* Xml attribute expression:
* '@attr', '@ns::attr', '@ns::*', '@ns::*',
'@*', '@*::attr', '@*::*'
*/
- private Node attributeAccess(Node pn, int memberTypeFlags)
- throws IOException
- {
+ 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:
- {
+
+ // 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;
+ // handles: @*, @*::name, @*::*, @*::[expr]
+ case Token.MUL :
+ decompiler.addName("*");
+ pn = propertyName(pn, "*", memberTypeFlags);
- default:
- reportError("msg.no.name.after.xmlAttr");
- pn = nf.createPropertyGet(pn, null, "?", memberTypeFlags);
- break;
+ 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;
@@ -1881,262 +2077,311 @@
/**
* Check if :: follows name in which case it becomes qualified name
*/
- private Node propertyName(Node pn, String name, int memberTypeFlags)
- throws IOException, ParserException
- {
+ 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::name
+ case Token.NAME :
+ name = ts.getString();
+ decompiler.addName(name);
- // 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;
+ break;
- default:
- reportError("msg.no.name.after.coloncolon");
- name = "?";
+ // 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
- {
+ private Node primaryExpr() throws IOException, ParserException {
Node pn;
-
int ttFlagged = nextFlaggedToken();
int tt = ttFlagged & CLEAR_TI_MASK;
- switch(tt) {
+ switch (tt) {
+ case Token.FUNCTION :
+ return function(FunctionNode.FUNCTION_EXPRESSION);
- case Token.FUNCTION:
- return function(FunctionNode.FUNCTION_EXPRESSION);
+ case Token.LB : {
+ ObjArray elems = new ObjArray();
+ int skipCount = 0;
- case Token.LB: {
- ObjArray elems = new ObjArray();
- int skipCount = 0;
- decompiler.addToken(Token.LB);
- boolean after_lb_or_comma = true;
- for (;;) {
- tt = peekToken();
+ decompiler.addToken(Token.LB);
- if (tt == Token.COMMA) {
- consumeToken();
- decompiler.addToken(Token.COMMA);
- if (!after_lb_or_comma) {
- after_lb_or_comma = true;
+ 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 {
- elems.add(null);
- ++skipCount;
+ if (!after_lb_or_comma) {
+ reportError("msg.no.bracket.arg");
+ }
+
+ elems.add(assignExpr(false));
+ after_lb_or_comma = false;
}
- } 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);
}
- return nf.createArrayLiteral(elems, skipCount);
- }
- case Token.LC: {
- ObjArray elems = new ObjArray();
- decompiler.addToken(Token.LC);
- if (!matchToken(Token.RC)) {
+ case Token.LC : {
+ ObjArray elems = new ObjArray();
- boolean first = true;
- commaloop:
- do {
- Object property;
+ decompiler.addToken(Token.LC);
- if (!first)
- decompiler.addToken(Token.COMMA);
- else
- first = false;
+ if (!matchToken(Token.RC)) {
+ boolean first = true;
- 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);
+ commaloop:do {
+ Object property;
+
+ if (!first) {
+ decompiler.addToken(Token.COMMA);
+ } else {
+ first = false;
+ }
+
+ tt = peekToken();
+
+ switch (tt) {
+ case Token.NAME :
+ case Token.STRING :
consumeToken();
- s = ts.getString();
- decompiler.addName(s);
+
+ // 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);
- if (!getterSetterProperty(elems, property,
- true))
- break commaloop;
+ plainProperty(elems, property);
+
break;
- } else if (s.equals("set") &&
- peekToken() == Token.NAME) {
- decompiler.addToken(Token.SET);
+
+ case Token.NUMBER :
consumeToken();
- s = ts.getString();
- decompiler.addName(s);
- property = ScriptRuntime.getIndexObject(s);
- if (!getterSetterProperty(elems, property,
- false))
- break commaloop;
+
+ double n = ts.getNumber();
+
+ decompiler.addNumber(n);
+ property = ScriptRuntime.getIndexObject(n);
+ plainProperty(elems, property);
+
break;
- }
- decompiler.addName(s);
- } else {
- decompiler.addString(s);
+
+ case Token.RC :
+
+ // trailing comma is OK.
+ break commaloop;
+
+ default :
+ reportError("msg.bad.prop");
+
+ break commaloop;
}
- property = ScriptRuntime.getIndexObject(s);
- plainProperty(elems, property);
- break;
+ } while (matchToken(Token.COMMA));
- case Token.NUMBER:
- consumeToken();
- double n = ts.getNumber();
- decompiler.addNumber(n);
- property = ScriptRuntime.getIndexObject(n);
- plainProperty(elems, property);
- break;
+ mustMatchToken(Token.RC, "msg.no.brace.prop");
+ }
- case Token.RC:
- // trailing comma is OK.
- break commaloop;
- default:
- reportError("msg.bad.prop");
- break commaloop;
- }
- } while (matchToken(Token.COMMA));
+ decompiler.addToken(Token.RC);
- mustMatchToken(Token.RC, "msg.no.brace.prop");
+ return nf.createObjectLiteral(elems);
}
- decompiler.addToken(Token.RC);
- return nf.createObjectLiteral(elems);
- }
- case Token.LP:
+ 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;
+ /*
+ * 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");
- case Token.XMLATTR:
- mustHaveXML();
- decompiler.addToken(Token.XMLATTR);
- pn = attributeAccess(null, 0);
- return pn;
+ 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());
+ 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;
}
- decompiler.addName(name);
- if (compilerEnv.isXmlAvailable()) {
- pn = propertyName(null, name, 0);
- } else {
- pn = nf.createName(name);
+ case Token.NUMBER : {
+ double n = ts.getNumber();
+
+ decompiler.addNumber(n);
+
+ return nf.createNumber(n);
}
- return pn;
- }
- case Token.NUMBER: {
- double n = ts.getNumber();
- decompiler.addNumber(n);
- return nf.createNumber(n);
- }
+ case Token.STRING : {
+ String s = ts.getString();
- case Token.STRING: {
- String s = ts.getString();
- decompiler.addString(s);
- return nf.createString(s);
- }
+ decompiler.addString(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);
- }
+ return nf.createString(s);
+ }
- case Token.NULL:
- case Token.THIS:
- case Token.FALSE:
- case Token.TRUE:
- decompiler.addToken(tt);
- return nf.createLeaf(tt);
+ case Token.DIV :
+ case Token.ASSIGN_DIV : {
- case Token.RESERVED:
- reportError("msg.reserved.id");
- break;
+ // Got / or /= which should be treated as regexp in fact
+ ts.readRegExp(tt);
- case Token.ERROR:
- /* the scanner or one of its subroutines reported the error. */
- break;
+ String flags = ts.regExpFlags;
- case Token.EOF:
- reportError("msg.unexpected.eof");
- break;
+ ts.regExpFlags = null;
- default:
- reportError("msg.syntax");
- break;
+ 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
+
+ return null; // should never reach here
}
- private void plainProperty(ObjArray elems, Object property)
- throws IOException {
+ private void plainProperty(ObjArray elems, Object property) throws IOException {
mustMatchToken(Token.COLON, "msg.no.colon.prop");
// OBJLIT is used as ':' in object literal for
@@ -2146,25 +2391,37 @@
elems.add(assignExpr(false));
}
- private boolean getterSetterProperty(ObjArray elems, Object property,
- boolean isGetter) throws IOException {
+ 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;
}
+
+ // Exception to unwind
+ private static class ParserException extends RuntimeException {
+ static final long serialVersionUID = 5882582646773765630L;
+ }
}
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/Token.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -40,6 +40,8 @@
*
* ***** END LICENSE BLOCK ***** */
+
+
package org.mozilla.javascript;
/**
@@ -53,366 +55,582 @@
* @author Mike McCabe
* @author Brendan Eich
*/
+public class Token {
-public class Token
-{
-
// debug flags
public static final boolean printTrees = false;
+ static final boolean printNames = printTrees || printICode;
static final boolean printICode = false;
- static final boolean printNames = printTrees || printICode;
+ // 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, IECC = 152, // Internet Explorer
conditional comment
+ LAST_TOKEN = 153;
+
/**
* 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
+ // 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,
+ 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
- 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.
+ 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,
+ public static String name(int token) {
+ if (!printNames) {
+ return String.valueOf(token);
+ }
- 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
+ switch (token) {
+ case ERROR :
+ return "ERROR";
- 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; // %=
+ case EOF :
+ return "EOF";
- public final static int
- FIRST_ASSIGN = ASSIGN,
- LAST_ASSIGN = ASSIGN_MOD,
+ case EOL :
+ return "EOL";
- 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
+ case ENTERWITH :
+ return "ENTERWITH";
- EMPTY = 124,
+ case LEAVEWITH :
+ return "LEAVEWITH";
- /* types used for the parse tree - these never get returned
- * by the scanner.
- */
+ case RETURN :
+ return "RETURN";
- 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
+ case GOTO :
+ return "GOTO";
- // 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,
+ case IFEQ :
+ return "IFEQ";
- // Optimizer-only-tokens
- TO_OBJECT = 145,
- TO_DOUBLE = 146,
+ case IFNE :
+ return "IFNE";
- GET = 147, // JS 1.5 get pseudo keyword
- SET = 148, // JS 1.5 set pseudo keyword
- CONST = 149,
- SETCONST = 150,
- SETCONSTVAR = 151,
+ case SETNAME :
+ return "SETNAME";
- IECC = 152, // Internet Explorer conditional comment
+ case BITOR :
+ return "BITOR";
- LAST_TOKEN = 153;
+ case BITXOR :
+ return "BITXOR";
- public static String name(int token)
- {
- if (!printNames) {
- return String.valueOf(token);
+ 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";
}
- 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));
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/main/java/org/mozilla/javascript/TokenStream.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -42,6 +42,8 @@
*
* ***** END LICENSE BLOCK ***** */
+
+
package org.mozilla.javascript;
import java.io.*;
@@ -57,272 +59,633 @@
* @author Mike McCabe
* @author Brendan Eich
*/
+class TokenStream {
-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;
+ private final static int EOF_CHAR = -1;
+ private int lineEndChar = -1;
+ private int lineStart = 0;
- TokenStream(Parser parser, Reader sourceReader, String sourceString,
- int lineno)
- {
+ // 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 char[] stringBuffer = new char[128];
+ 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 boolean hitEOF = false;
+
+ // stuff other than whitespace since start of line
+ private boolean dirtyLine;
+ private int lineno;
+ private double number;
+ private Parser parser;
+ String regExpFlags;
+ private char[] sourceBuffer;
+ private int sourceCursor;
+ private int sourceEnd;
+ private Reader sourceReader;
+ private String sourceString;
+ private int stringBufferTop;
+ private int ungetCursor;
+
+ // for xml tokenizer
+ private boolean xmlIsAttribute;
+ private boolean xmlIsTagContent;
+ private int xmlOpenTagsCount;
+
+ TokenStream(Parser parser, Reader sourceReader, String sourceString, int lineno) {
this.parser = parser;
this.lineno = lineno;
+
if (sourceReader != null) {
- if (sourceString != null) Kit.codeBug();
+ if (sourceString != null) {
+ Kit.codeBug();
+ }
+
this.sourceReader = sourceReader;
this.sourceBuffer = new char[512];
this.sourceEnd = 0;
} else {
- if (sourceString == null) Kit.codeBug();
+ 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
+ /*
+ * 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)
- {
+ 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.STRING :
+ case Token.REGEXP :
+ case Token.NAME :
+ return name + " `" + this.string + "'";
- case Token.NUMBER:
- return "NUMBER " + this.number;
+ case Token.NUMBER :
+ return "NUMBER " + this.number;
}
return name;
}
+
return "";
}
- static boolean isKeyword(String s)
- {
+ 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,
+ private static int stringToKeyword(String name) {
- // 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;
+// #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;} }
+
+// #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 '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;} }
+
+ 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 '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;} }
+
+ 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 '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; }
+
+ 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 'o': c=s.charAt(0);
- if (c=='f') { X="float";id=Id_float; }
- else if (c=='s') { X="short";id=Id_short; }
+
+ 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 '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; }
+
+ 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 '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;
+
+ 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;
+
+ if (X != null && X != s && !X.equals(s)) {
+ id = 0;
+ }
}
-// #/generated#
-// #/string_id_map#
- if (id == 0) { return Token.EOF; }
+
+// #/generated#
+// #/string_id_map#
+ if (id == 0) {
+ return Token.EOF;
+ }
+
return id & 0xff;
}
- final int getLineno() { return lineno; }
+ final int getLineno() {
+ return lineno;
+ }
- final String getString() { return string; }
+ final String getString() {
+ return string;
+ }
- final double getNumber() { return number; }
+ final double getNumber() {
+ return number;
+ }
- final boolean eof() { return hitEOF; }
+ final boolean eof() {
+ return hitEOF;
+ }
- final int getToken() throws IOException
- {
+ final int getToken() throws IOException {
int c;
- retry:
- for (;;) {
+ 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;
+ 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;
@@ -333,7 +696,8 @@
c = '\\';
}
} else {
- identifierStart = Character.isJavaIdentifierStart((char)c);
+ identifierStart = Character.isJavaIdentifierStart((char) c);
+
if (identifierStart) {
stringBufferTop = 0;
addToString(c);
@@ -342,8 +706,10 @@
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
@@ -351,56 +717,67 @@
// 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) {
+ 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))
- {
+ 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())
- {
+ } 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
@@ -408,18 +785,21 @@
}
}
}
- this.string = (String)allStrings.intern(str);
+
+ this.string = (String) allStrings.intern(str);
+
return Token.NAME;
}
// is it a number?
if (isDigit(c) || (c == '.' && isDigit(peekChar()))) {
+ stringBufferTop = 0;
- stringBufferTop = 0;
int base = 10;
if (c == '0') {
c = getChar();
+
if (c == 'x' || c == 'X') {
base = 16;
c = getChar();
@@ -437,6 +817,7 @@
}
} else {
while ('0' <= c && c <= '9') {
+
/*
* We permit 08 and 09 as decimal numbers, which
* makes our behavior a superset of the ECMA
@@ -444,10 +825,10 @@
* permissive, so we warn about it.
*/
if (base == 8 && c >= '8') {
- parser.addWarning("msg.bad.octal.literal",
- c == '8' ? "8" :
"9");
+ parser.addWarning("msg.bad.octal.literal", c ==
'8' ? "8" : "9");
base = 10;
}
+
addToString(c);
c = getChar();
}
@@ -457,40 +838,49 @@
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;
- double dval;
if (base == 10 && !isInteger) {
try {
+
// Use Java conversion to number from string...
dval = Double.valueOf(numString).doubleValue();
- }
- catch (NumberFormatException ex) {
+ } catch (NumberFormatException ex) {
parser.addError("msg.caught.nfe");
+
return Token.ERROR;
}
} else {
@@ -498,54 +888,59 @@
}
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;
- int quoteChar = c;
stringBufferTop = 0;
+ c = getChar();
- c = getChar();
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
-
c = getChar();
switch (c) {
+ case '\\' : // backslash
+ case 'b' : // backspace
+ case 'f' : // form feed
+ case 'n' : // line feed
+ case 'r' : // carriage return
+ case 't' : // horizontal tab
+ case 'v' : // vertical tab
+ case 'd' : // octal sequence
+ case 'u' : // unicode sequence
+ case 'x' : // hexadecimal sequence
- case '\\': // backslash
- case 'b': // backspace
- case 'f': // form feed
- case 'n': // line feed
- case 'r': // carriage return
- case 't': // horizontal tab
- case 'v': // vertical tab
- case 'd': // octal sequence
- case 'u': // unicode sequence
- case 'x': // hexadecimal sequence
-
// Only keep the '\' character for those
// characters that need to be escaped...
// Don't escape quoting characters...
addToString('\\');
+
break;
- case '\n':
+ case '\n' :
+
// Remove line terminator after escape
c = getChar();
+
break;
}
}
@@ -555,228 +950,257 @@
}
String str = getStringFromBuffer();
- this.string = (String)allStrings.intern(str);
+
+ 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 ';' :
+ return Token.SEMI;
- case '|':
- if (matchChar('|')) {
- return Token.OR;
- } else if (matchChar('=')) {
- return Token.ASSIGN_BITOR;
- } else {
- return Token.BITOR;
- }
+ case '[' :
+ return Token.LB;
- case '^':
- if (matchChar('=')) {
- return Token.ASSIGN_BITXOR;
- } else {
- return Token.BITXOR;
- }
+ case ']' :
+ return Token.RB;
- case '&':
- if (matchChar('&')) {
- return Token.AND;
- } else if (matchChar('=')) {
- return Token.ASSIGN_BITAND;
- } else {
- return Token.BITAND;
- }
+ case '{' :
+ return Token.LC;
- case '=':
- if (matchChar('=')) {
- if (matchChar('='))
- return Token.SHEQ;
- else
- return Token.EQ;
- } else {
- return Token.ASSIGN;
- }
+ case '}' :
+ return Token.RC;
- case '!':
- if (matchChar('=')) {
- if (matchChar('='))
- return Token.SHNE;
- else
- return Token.NE;
- } else {
- return Token.NOT;
- }
+ case '(' :
+ return Token.LP;
- case '<':
- /* NB:treat HTML begin-comment as comment-till-eol */
- if (matchChar('!')) {
- if (matchChar('-')) {
- if (matchChar('-')) {
- skipLine();
- continue retry;
- }
- ungetChar('-');
+ case ')' :
+ return Token.RP;
+
+ case ',' :
+ return Token.COMMA;
+
+ case '?' :
+ return Token.HOOK;
+
+ case ':' :
+ if (matchChar(':')) {
+ return Token.COLONCOLON;
+ } else {
+ return Token.COLON;
}
- ungetChar('!');
- }
- if (matchChar('<')) {
+ 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_LSH;
+ return Token.ASSIGN_BITXOR;
} else {
- return Token.LSH;
+ return Token.BITXOR;
}
- } else {
+ case '&' :
+ if (matchChar('&')) {
+ return Token.AND;
+ } else if (matchChar('=')) {
+ return Token.ASSIGN_BITAND;
+ } else {
+ return Token.BITAND;
+ }
+ case '=' :
if (matchChar('=')) {
- return Token.LE;
+ if (matchChar('=')) {
+ return Token.SHEQ;
+ } else {
+ return Token.EQ;
+ }
} else {
- return Token.LT;
+ return Token.ASSIGN;
}
- }
+ case '!' :
+ if (matchChar('=')) {
+ if (matchChar('=')) {
+ return Token.SHNE;
+ } else {
+ return Token.NE;
+ }
+ } else {
+ return Token.NOT;
+ }
+ case '<' :
- case '>':
- if (matchChar('>')) {
- if (matchChar('>')) {
+ /* 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_URSH;
+ return Token.ASSIGN_LSH;
} else {
- return Token.URSH;
+ return Token.LSH;
}
} else {
if (matchChar('=')) {
- return Token.ASSIGN_RSH;
+ return Token.LE;
} else {
- return Token.RSH;
+ return Token.LT;
}
}
- } else {
+ 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.GE;
+ return Token.ASSIGN_MUL;
} else {
- return Token.GT;
+ return Token.MUL;
}
- }
+ case '/' :
- case '*':
- if (matchChar('=')) {
- return Token.ASSIGN_MUL;
- } else {
- return Token.MUL;
- }
+ // is it a // comment?
+ if (matchChar('/')) {
+ skipLine();
- case '/':
- // is it a // comment?
- if (matchChar('/')) {
- skipLine();
- continue retry;
- }
- if (matchChar('*')) {
- boolean lookForSlash = false;
- StringBuffer sb = new StringBuffer();
- for (;;) {
- c = getChar();
- if (c == EOF_CHAR) {
- parser.addError("msg.unterminated.comment");
- return Token.ERROR;
- }
- sb.append((char) c);
- if (c == '*') {
- lookForSlash = true;
- } else if (c == '/') {
- if (lookForSlash) {
- sb.delete(sb.length()-2, sb.length());
- String s = sb.toString();
- if (s.startsWith("@cc_on") ||
- s.startsWith("@if") ||
- s.startsWith("@elif") ||
- s.startsWith("@else") ||
- s.startsWith("@end")) {
- this.string = s;
- return Token.IECC;
- } else {
- continue retry;
+ continue retry;
+ }
+
+ if (matchChar('*')) {
+ boolean lookForSlash = false;
+ StringBuffer sb = new StringBuffer();
+
+ for (;;) {
+ c = getChar();
+
+ if (c == EOF_CHAR) {
+ parser.addError("msg.unterminated.comment");
+
+ return Token.ERROR;
+ }
+
+ sb.append((char) c);
+
+ if (c == '*') {
+ lookForSlash = true;
+ } else if (c == '/') {
+ if (lookForSlash) {
+ sb.delete(sb.length() - 2, sb.length());
+
+ String s = sb.toString();
+
+ if (s.startsWith("@cc_on") ||
s.startsWith("@if") || s.startsWith("@elif")
+ || s.startsWith("@else") ||
s.startsWith("@end")) {
+ this.string = s;
+
+ return Token.IECC;
+ } else {
+ continue retry;
+ }
}
+ } else {
+ lookForSlash = false;
}
- } else {
- lookForSlash = false;
}
}
- }
- if (matchChar('=')) {
- return Token.ASSIGN_DIV;
- } else {
- return Token.DIV;
- }
+ 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_MOD;
- } else {
- return Token.MOD;
- }
+ 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) {
- case '~':
- return Token.BITNOT;
+ // treat HTML end-comment after possible whitespace
+ // after line start as comment-utill-eol
+ if (matchChar('>')) {
+ skipLine();
- case '+':
- if (matchChar('=')) {
- return Token.ASSIGN_ADD;
- } else if (matchChar('+')) {
- return Token.INC;
- } else {
- return Token.ADD;
- }
+ continue retry;
+ }
+ }
- 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;
}
- c = Token.DEC;
- } else {
- c = Token.SUB;
- }
- dirtyLine = true;
- return c;
- default:
- parser.addError("msg.illegal.character");
- return Token.ERROR;
+ dirtyLine = true;
+
+ return c;
+
+ default :
+ parser.addError("msg.illegal.character");
+
+ return Token.ERROR;
}
}
}
- private static boolean isAlpha(int c)
- {
+ private static boolean isAlpha(int c) {
+
// Use 'Z' < 'a'
if (c <= 'Z') {
return 'A' <= c;
@@ -785,50 +1209,52 @@
}
}
- static boolean isDigit(int c)
- {
+ static boolean isDigit(int c) {
return '0' <= c && c <= '9';
}
- /* As defined in ECMA. jsscan.c uses C isspace() (which allows
+ /*
+ * 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)
- {
+ 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;
+ 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;
+ 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
- {
+ void readRegExp(int startToken) throws IOException {
stringBufferTop = 0;
+
if (startToken == Token.ASSIGN_DIV) {
+
// Miss-scanned /=
addToString('=');
} else {
- if (startToken != Token.DIV) Kit.codeBug();
+ 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();
@@ -836,17 +1262,19 @@
addToString(c);
}
+
int reEnd = stringBufferTop;
while (true) {
- if (matchChar('g'))
+ if (matchChar('g')) {
addToString('g');
- else if (matchChar('i'))
+ } else if (matchChar('i')) {
addToString('i');
- else if (matchChar('m'))
+ } else if (matchChar('m')) {
addToString('m');
- else
+ } else {
break;
+ }
}
if (isAlpha(peekChar())) {
@@ -854,164 +1282,215 @@
}
this.string = new String(stringBuffer, 0, reEnd);
- this.regExpFlags = new String(stringBuffer, reEnd,
- stringBufferTop - reEnd);
+ this.regExpFlags = new String(stringBuffer, reEnd, stringBufferTop - reEnd);
}
- boolean isXMLAttribute()
- {
+ boolean isXMLAttribute() {
return xmlIsAttribute;
}
- int getFirstXMLToken() throws IOException
- {
+ int getFirstXMLToken() throws IOException {
xmlOpenTagsCount = 0;
xmlIsAttribute = false;
xmlIsTagContent = false;
ungetChar('<');
+
return getNextXMLToken();
}
- int getNextXMLToken() throws IOException
- {
+ 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();
+ case '>' :
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;
+ 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 !
+ case '<' :
addToString(c);
c = peekChar();
+
switch (c) {
- case '-':
- c = getChar(); // Skip -
- addToString(c);
- c = getChar();
- if (c == '-') {
+ case '!' :
+ c = getChar(); // Skip !
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;
+ c = peekChar();
- } 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;
+ 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 '?':
- c = getChar(); // Skip ?
+
+ case '{' :
+ ungetChar(c);
+ this.string = getStringFromBuffer();
+
+ return Token.XML;
+
+ default :
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;
}
}
}
@@ -1019,114 +1498,135 @@
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
- {
+ private boolean readQuotedString(int quote) throws IOException {
for (int c = getChar(); c != EOF_CHAR; c = getChar()) {
addToString(c);
- if (c == quote) return true;
+
+ 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;) {
+ 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;) {
+ 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
- {
+ 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;
+ 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
- {
+ 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;
}
}
@@ -1134,81 +1634,93 @@
stringBufferTop = 0; // throw away the string in progress
this.string = null;
parser.addError("msg.XML.bad.form");
+
return false;
}
- private String getStringFromBuffer()
- {
+ private String getStringFromBuffer() {
return new String(stringBuffer, 0, stringBufferTop);
}
- private void addToString(int c)
- {
+ 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;
+
+ stringBuffer[N] = (char) c;
stringBufferTop = N + 1;
}
- private void ungetChar(int c)
- {
+ private void ungetChar(int c) {
+
// can not unread past across line boundary
- if (ungetCursor != 0 && ungetBuffer[ungetCursor - 1] == '\n')
+ if (ungetCursor != 0 && ungetBuffer[ungetCursor - 1] == '\n') {
Kit.codeBug();
+ }
+
ungetBuffer[ungetCursor++] = c;
}
- private boolean matchChar(int test) throws IOException
- {
+ 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
- {
+ private int peekChar() throws IOException {
int c = getChar();
+
ungetChar(c);
+
return c;
}
- private int getChar() throws IOException
- {
+ private int getChar() throws IOException {
if (ungetCursor != 0) {
return ungetBuffer[--ungetCursor];
}
- for(;;) {
+ 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++;
@@ -1223,137 +1735,124 @@
if (isJSFormatChar(c)) {
continue;
}
+
if (ScriptRuntime.isJSLineTerminator(c)) {
lineEndChar = c;
c = '\n';
}
}
+
return c;
}
}
- private void skipLine() throws IOException
- {
+ private void skipLine() throws IOException {
+
// skip to end of line
int c;
- while ((c = getChar()) != EOF_CHAR && c != '\n') { }
+
+ while ((c = getChar()) != EOF_CHAR && c != '\n') {}
+
ungetChar(c);
}
- final int getOffset()
- {
+ final int getOffset() {
int n = sourceCursor - lineStart;
- if (lineEndChar >= 0) { --n; }
+
+ if (lineEndChar >= 0) {
+ --n;
+ }
+
return n;
}
- final String getLine()
- {
+ 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) {
+ for (; ; ++lineLength) {
int i = lineStart + lineLength;
+
if (i == sourceEnd) {
try {
- if (!fillSourceBuffer()) { break; }
+ 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();
+ 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);
+ 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);
+
+ 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;
}
Modified:
root/cdk/trunk/plugins/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java
===================================================================
---
root/cdk/trunk/plugins/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java 2009-11-01
16:28:50 UTC (rev 15792)
+++
root/cdk/trunk/plugins/maven-javascript-plugin/src/test/java/net/sf/alchim/mojo/yuicompressor/AggregationTestCase.java 2009-11-01
16:30:05 UTC (rev 15793)
@@ -18,7 +18,9 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
+
+
+
package net.sf.alchim.mojo.yuicompressor;
import java.io.File;
@@ -44,31 +46,30 @@
public void test0to1() throws Exception {
Aggregation target = new Aggregation();
+
target.output = new File(dir_, "output.js");
-
assertFalse(target.output.exists());
target.run(dir_);
assertFalse(target.output.exists());
-
- target.includes = new String[]{};
+ target.includes = new String[] {};
assertFalse(target.output.exists());
target.run(dir_);
assertFalse(target.output.exists());
-
- target.includes = new String[]{"**/*.js"};
+ target.includes = new String[] {"**/*.js"};
assertFalse(target.output.exists());
target.run(dir_);
assertFalse(target.output.exists());
}
-
public void test1to1() throws Exception {
File f1 = new File(dir_, "01.js");
+
FileUtils.fileWrite(f1.getAbsolutePath(), "1");
+
Aggregation target = new Aggregation();
+
target.output = new File(dir_, "output.js");
- target.includes = new String[]{f1.getName()};
-
+ target.includes = new String[] {f1.getName()};
assertFalse(target.output.exists());
target.run(dir_);
assertTrue(target.output.exists());
@@ -77,46 +78,49 @@
public void test2to1() throws Exception {
File f1 = new File(dir_, "01.js");
+
FileUtils.fileWrite(f1.getAbsolutePath(), "1");
File f2 = new File(dir_, "02.js");
+
FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
Aggregation target = new Aggregation();
+
target.output = new File(dir_, "output.js");
-
- target.includes = new String[]{f1.getName(), f2.getName()};
+ target.includes = new String[] {f1.getName(), f2.getName()};
assertFalse(target.output.exists());
target.run(dir_);
assertTrue(target.output.exists());
assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2),
FileUtils.fileRead(target.output));
-
target.output.delete();
- target.includes = new String[]{"*.js"};
+ target.includes = new String[] {"*.js"};
assertFalse(target.output.exists());
target.run(dir_);
assertTrue(target.output.exists());
-// assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2),
FileUtils.fileRead(target.output));
+
+// assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2),
FileUtils.fileRead(target.output));
}
public void testNoDuplicateAggregation() throws Exception {
File f1 = new File(dir_, "01.js");
+
FileUtils.fileWrite(f1.getAbsolutePath(), "1");
File f2 = new File(dir_, "02.js");
+
FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
Aggregation target = new Aggregation();
+
target.output = new File(dir_, "output.js");
-
- target.includes = new String[]{f1.getName(), f1.getName(), f2.getName()};
+ target.includes = new String[] {f1.getName(), f1.getName(), f2.getName()};
assertFalse(target.output.exists());
target.run(dir_);
assertTrue(target.output.exists());
assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2),
FileUtils.fileRead(target.output));
-
target.output.delete();
- target.includes = new String[]{f1.getName(), "*.js"};
+ target.includes = new String[] {f1.getName(), "*.js"};
assertFalse(target.output.exists());
target.run(dir_);
assertTrue(target.output.exists());
@@ -125,15 +129,17 @@
public void test2to1Order() throws Exception {
File f1 = new File(dir_, "01.js");
+
FileUtils.fileWrite(f1.getAbsolutePath(), "1");
File f2 = new File(dir_, "02.js");
+
FileUtils.fileWrite(f2.getAbsolutePath(), "2");
Aggregation target = new Aggregation();
+
target.output = new File(dir_, "output.js");
-
- target.includes = new String[]{f2.getName(), f1.getName()};
+ target.includes = new String[] {f2.getName(), f1.getName()};
assertFalse(target.output.exists());
target.run(dir_);
assertTrue(target.output.exists());
@@ -142,16 +148,18 @@
public void test2to1WithNewLine() throws Exception {
File f1 = new File(dir_, "01.js");
+
FileUtils.fileWrite(f1.getAbsolutePath(), "1");
File f2 = new File(dir_, "02.js");
+
FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
Aggregation target = new Aggregation();
+
target.output = new File(dir_, "output.js");
target.insertNewLine = true;
- target.includes = new String[]{f1.getName(), f2.getName()};
-
+ target.includes = new String[] {f1.getName(), f2.getName()};
assertFalse(target.output.exists());
target.run(dir_);
assertTrue(target.output.exists());
@@ -160,15 +168,17 @@
public void testAbsolutePathFromInside() throws Exception {
File f1 = new File(dir_, "01.js");
+
FileUtils.fileWrite(f1.getAbsolutePath(), "1");
File f2 = new File(dir_, "02.js");
+
FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
Aggregation target = new Aggregation();
+
target.output = new File(dir_, "output.js");
-
- target.includes = new String[]{f1.getAbsolutePath(), f2.getName()};
+ target.includes = new String[] {f1.getAbsolutePath(), f2.getName()};
assertFalse(target.output.exists());
target.run(dir_);
assertTrue(target.output.exists());
@@ -177,16 +187,18 @@
public void testAbsolutePathFromOutside() throws Exception {
File f1 = File.createTempFile("test-01", ".js");
+
try {
FileUtils.fileWrite(f1.getAbsolutePath(), "1");
File f2 = new File(dir_, "02.js");
+
FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22");
Aggregation target = new Aggregation();
+
target.output = new File(dir_, "output.js");
-
- target.includes = new String[]{f1.getAbsolutePath(), f2.getName()};
+ target.includes = new String[] {f1.getAbsolutePath(), f2.getName()};
assertFalse(target.output.exists());
target.run(dir_);
assertTrue(target.output.exists());