changeset 128:3b222c90b7de

Merge
author jlaskey
date Sat, 02 Mar 2013 11:26:47 -0400
parents 1d3dca059b3e (current diff) 7e9fbe621d87 (diff)
children f90810d79b57
files
diffstat 28 files changed, 403 insertions(+), 884 deletions(-) [+]
line wrap: on
line diff
--- a/make/build.xml	Wed Feb 27 14:12:45 2013 +0000
+++ b/make/build.xml	Sat Mar 02 11:26:47 2013 -0400
@@ -21,7 +21,7 @@
  or visit www.oracle.com if you need additional information or have any
  questions.
 -->
-<project name="nashorn" default="all" basedir="..">
+<project name="nashorn" default="test" basedir="..">
   <import file="build-nasgen.xml"/>
   <import file="build-benchmark.xml"/>
   <import file="code_coverage.xml"/>
--- a/make/project.properties	Wed Feb 27 14:12:45 2013 +0000
+++ b/make/project.properties	Sat Mar 02 11:26:47 2013 -0400
@@ -24,7 +24,7 @@
 application.title=nashorn
 
 # location of JDK embedded ASM sources
-jdk.asm.src.dir=../jdk/src/share/classes/jdk/internal
+jdk.asm.src.dir=../jdk/src/share/classes/jdk/internal/org/objectweb/asm
 
 # source and target levels
 build.compiler=modern
--- a/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java	Sat Mar 02 11:26:47 2013 -0400
@@ -83,7 +83,6 @@
 
 package jdk.internal.dynalink.beans;
 
-import java.beans.Introspector;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
@@ -136,16 +135,16 @@
             // Add the method as a property getter and/or setter
             if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) {
                 // Property getter
-                setPropertyGetter(Introspector.decapitalize(name.substring(3)), introspector.unreflect(
+                setPropertyGetter(decapitalize(name.substring(3)), introspector.unreflect(
                         getMostGenericGetter(method)), ValidationType.INSTANCE_OF);
             } else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 &&
                     method.getReturnType() == boolean.class) {
                 // Boolean property getter
-                setPropertyGetter(Introspector.decapitalize(name.substring(2)), introspector.unreflect(
+                setPropertyGetter(decapitalize(name.substring(2)), introspector.unreflect(
                         getMostGenericGetter(method)), ValidationType.INSTANCE_OF);
             } else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) {
                 // Property setter
-                addMember(Introspector.decapitalize(name.substring(3)), methodHandle, propertySetters);
+                addMember(decapitalize(name.substring(3)), methodHandle, propertySetters);
             }
         }
 
@@ -170,6 +169,27 @@
         }
     }
 
+    private static String decapitalize(String str) {
+        assert str != null;
+        if(str.isEmpty()) {
+            return str;
+        }
+
+        final char c0 = str.charAt(0);
+        if(Character.isLowerCase(c0)) {
+            return str;
+        }
+
+        // If it has two consecutive upper-case characters, i.e. "URL", don't decapitalize
+        if(str.length() > 1 && Character.isUpperCase(str.charAt(1))) {
+            return str;
+        }
+
+        final char c[] = str.toCharArray();
+        c[0] = Character.toLowerCase(c0);
+        return new String(c);
+    }
+
     abstract FacetIntrospector createFacetIntrospector();
 
     void setPropertyGetter(String name, MethodHandle handle, ValidationType validationType) {
--- a/src/jdk/internal/dynalink/beans/BeansLinker.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/internal/dynalink/beans/BeansLinker.java	Sat Mar 02 11:26:47 2013 -0400
@@ -83,7 +83,6 @@
 
 package jdk.internal.dynalink.beans;
 
-import java.beans.BeanInfo;
 import java.lang.invoke.MethodHandles;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.DynamicLinkerFactory;
@@ -99,11 +98,9 @@
  * <ul>
  * <li>expose all public methods of form {@code setXxx()}, {@code getXxx()}, and {@code isXxx()} as property setters and
  * getters for {@code dyn:setProp} and {@code dyn:getProp} operations;</li>
- * <li>expose all property getters and setters declared by the class' {@link BeanInfo};</li>
- * <li>expose all public methods and methods declared by the class' {@link BeanInfo} for invocation through
- * {@code dyn:callMethod} operation;</li>
- * <li>expose all public methods and methods declared by the class' {@link BeanInfo} for retrieval for
- * {@code dyn:getMethod} operation; the methods thus retrieved can then be invoked using {@code dyn:call};</li>
+ * <li>expose all public methods for invocation through {@code dyn:callMethod} operation;</li>
+ * <li>expose all public methods for retrieval for {@code dyn:getMethod} operation; the methods thus retrieved can then
+ * be invoked using {@code dyn:call};</li>
  * <li>expose all public fields as properties, unless there are getters or setters for the properties of the same name;</li>
  * <li>expose {@code dyn:getLength}, {@code dyn:getElem} and {@code dyn:setElem} on native Java arrays, as well as
  * {@link java.util.List} and {@link java.util.Map} objects; ({@code dyn:getLength} works on any
--- a/src/jdk/nashorn/internal/codegen/ClassEmitter.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/codegen/ClassEmitter.java	Sat Mar 02 11:26:47 2013 -0400
@@ -95,7 +95,7 @@
  * <p>
  * There is also a very nice debug interface that can emit formatted
  * bytecodes that have been written. This is enabled by setting the
- * environment "nashorn.codegen.debug" to true, or --log=codegen:<level>
+ * environment "nashorn.codegen.debug" to true, or --log=codegen:{@literal <level>}
  * <p>
  * A ClassEmitter implements an Emitter - i.e. it needs to have
  * well defined start and end calls for whatever it is generating. Assertions
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Sat Mar 02 11:26:47 2013 -0400
@@ -46,7 +46,6 @@
 import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL;
 import static jdk.nashorn.internal.ir.Symbol.IS_TEMP;
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_FAST_SCOPE;
-import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_FUNCTION_DECLARATION;
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_SCOPE;
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
 
@@ -2052,9 +2051,6 @@
 
         if (needsScope) {
             int flags = CALLSITE_SCOPE | getCallSiteFlags();
-            if (varNode.isFunctionVarNode()) {
-                flags |= CALLSITE_FUNCTION_DECLARATION;
-            }
             final IdentNode identNode = varNode.getName();
             final Type type = identNode.getType();
             if (varSymbol.isFastScope(getCurrentFunctionNode())) {
--- a/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Sat Mar 02 11:26:47 2013 -0400
@@ -112,7 +112,7 @@
     private final Context context;
 
     /**
-     * The list of available accessor types in width order. This order is used for type guesses narrow->wide
+     * The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide
      *  in the dual--fields world
      */
     public static final List<Type> ACCESSOR_TYPES = Collections.unmodifiableList(
@@ -184,7 +184,7 @@
 
     /**
      * Return the accessor type based on its index in [0..getNumberOfAccessorTypes())
-     * Indexes are ordered narrower->wider / optimistic->pessimistic. Invalidations always
+     * Indexes are ordered narrower{@literal ->}wider / optimistic{@literal ->}pessimistic. Invalidations always
      * go to a type of higher index
      *
      * @param index accessor type index
--- a/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java	Sat Mar 02 11:26:47 2013 -0400
@@ -459,120 +459,120 @@
     }
 
     /**
-     * Specialized version of < operator for two int arguments. Do not call directly.
+     * Specialized version of {@literal <} operator for two int arguments. Do not call directly.
      * @param a int
      * @param b int
-     * @return a < b
+     * @return a {@code <} b
      */
     public static boolean LT(final int a, final int b) {
         return a < b;
     }
 
     /**
-     * Specialized version of < operator for two double arguments. Do not call directly.
+     * Specialized version of {@literal <} operator for two double arguments. Do not call directly.
      * @param a double
      * @param b double
-     * @return a < b
+     * @return a {@literal <} b
      */
     public static boolean LT(final double a, final double b) {
         return a < b;
     }
 
     /**
-     * Specialized version of < operator for two long arguments. Do not call directly.
+     * Specialized version of {@literal <} operator for two long arguments. Do not call directly.
      * @param a long
      * @param b long
-     * @return a < b
+     * @return a {@literal <} b
      */
     public static boolean LT(final long a, final long b) {
         return a < b;
     }
 
     /**
-     * Specialized version of <= operator for two int arguments. Do not call directly.
+     * Specialized version of {@literal <=} operator for two int arguments. Do not call directly.
      * @param a int
      * @param b int
-     * @return a <= b
+     * @return a {@literal <=} b
      */
     public static boolean LE(final int a, final int b) {
         return a <= b;
     }
 
     /**
-     * Specialized version of <= operator for two double arguments. Do not call directly.
+     * Specialized version of {@literal <=} operator for two double arguments. Do not call directly.
      * @param a double
      * @param b double
-     * @return a <= b
+     * @return a {@literal <=} b
      */
     public static boolean LE(final double a, final double b) {
         return a <= b;
     }
 
     /**
-     * Specialized version of <= operator for two long arguments. Do not call directly.
+     * Specialized version of {@literal <=} operator for two long arguments. Do not call directly.
      * @param a long
      * @param b long
-     * @return a <= b
+     * @return a {@literal <=} b
      */
     public static boolean LE(final long a, final long b) {
         return a <= b;
     }
 
     /**
-     * Specialized version of > operator for two int arguments. Do not call directly.
+     * Specialized version of {@literal >} operator for two int arguments. Do not call directly.
      * @param a int
      * @param b int
-     * @return a > b
+     * @return a {@literal >} b
      */
     public static boolean GT(final int a, final int b) {
         return a > b;
     }
 
     /**
-     * Specialized version of > operator for two double arguments. Do not call directly.
+     * Specialized version of {@literal >} operator for two double arguments. Do not call directly.
      * @param a double
      * @param b double
-     * @return a > b
+     * @return a {@literal >} b
      */
     public static boolean GT(final double a, final double b) {
         return a > b;
     }
 
     /**
-     * Specialized version of > operator for two long arguments. Do not call directly.
+     * Specialized version of {@literal >} operator for two long arguments. Do not call directly.
      * @param a long
      * @param b long
-     * @return a > b
+     * @return a {@literal >} b
      */
     public static boolean GT(final long a, final long b) {
         return a > b;
     }
 
     /**
-     * Specialized version of >= operator for two int arguments. Do not call directly.
+     * Specialized version of {@literal >=} operator for two int arguments. Do not call directly.
      * @param a int
      * @param b int
-     * @return a >= b
+     * @return a {@literal >=} b
      */
     public static boolean GE(final int a, final int b) {
         return a >= b;
     }
 
     /**
-     * Specialized version of >= operator for two double arguments. Do not call directly.
+     * Specialized version of {@literal >=} operator for two double arguments. Do not call directly.
      * @param a double
      * @param b double
-     * @return a >= b
+     * @return a {@literal >=} b
      */
     public static boolean GE(final double a, final double b) {
         return a >= b;
     }
 
     /**
-     * Specialized version of >= operator for two long arguments. Do not call directly.
+     * Specialized version of {@literal >=} operator for two long arguments. Do not call directly.
      * @param a long
      * @param b long
-     * @return a >= b
+     * @return a {@code >=} b
      */
     public static boolean GE(final long a, final long b) {
         return a >= b;
--- a/src/jdk/nashorn/internal/ir/Assignment.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/ir/Assignment.java	Sat Mar 02 11:26:47 2013 -0400
@@ -46,18 +46,4 @@
      * @return get the assignment source node
      */
     public Node getAssignmentSource();
-
-    /**
-     * Reset the assignment source
-     *
-     * @param newSource new source node
-     */
-    public void setAssignmentSource(final Node newSource);
-
-    /**
-     * Reset the assignment destination
-     *
-     * @param newDest new destination node
-     */
-    public void setAssignmentDest(final D newDest);
 }
--- a/src/jdk/nashorn/internal/ir/BinaryNode.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/ir/BinaryNode.java	Sat Mar 02 11:26:47 2013 -0400
@@ -140,21 +140,11 @@
     }
 
     @Override
-    public void setAssignmentDest(final Node node) {
-        setLHS(node);
-    }
-
-    @Override
     public Node getAssignmentSource() {
         return rhs();
     }
 
     @Override
-    public void setAssignmentSource(final Node source) {
-        setRHS(source);
-    }
-
-    @Override
     public boolean equals(final Object other) {
         if (!super.equals(other)) {
             return false;
--- a/src/jdk/nashorn/internal/ir/RuntimeNode.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java	Sat Mar 02 11:26:47 2013 -0400
@@ -64,17 +64,17 @@
         EQ_STRICT(TokenType.EQ_STRICT, Type.BOOLEAN, 2, true),
         /** == operator with at least one object */
         EQ(TokenType.EQ, Type.BOOLEAN, 2, true),
-        /** >= operator with at least one object */
+        /** {@literal >=} operator with at least one object */
         GE(TokenType.GE, Type.BOOLEAN, 2, true),
-        /** > operator with at least one object */
+        /** {@literal >} operator with at least one object */
         GT(TokenType.GT, Type.BOOLEAN, 2, true),
         /** in operator */
         IN(TokenType.IN, Type.BOOLEAN, 2),
         /** instanceof operator */
         INSTANCEOF(TokenType.INSTANCEOF, Type.BOOLEAN, 2),
-        /** <= operator with at least one object */
+        /** {@literal <=} operator with at least one object */
         LE(TokenType.LE, Type.BOOLEAN, 2, true),
-        /** < operator with at least one object */
+        /** {@literal <} operator with at least one object */
         LT(TokenType.LT, Type.BOOLEAN, 2, true),
         /** !== operator with at least one object */
         NE_STRICT(TokenType.NE_STRICT, Type.BOOLEAN, 2, true),
@@ -184,7 +184,7 @@
 
         /**
          * If this request can be reversed, return the reverse request
-         * Eq EQ -> NE.
+         * Eq EQ {@literal ->} NE.
          *
          * @param request request to reverse
          *
--- a/src/jdk/nashorn/internal/ir/UnaryNode.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/ir/UnaryNode.java	Sat Mar 02 11:26:47 2013 -0400
@@ -109,16 +109,6 @@
     }
 
     @Override
-    public void setAssignmentSource(final Node source) {
-        setAssignmentDest(source);
-    }
-
-    @Override
-    public void setAssignmentDest(final Node source) {
-        setRHS(source);
-    }
-
-    @Override
     public boolean equals(final Object other) {
         if (!super.equals(other)) {
             return false;
--- a/src/jdk/nashorn/internal/ir/VarNode.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/ir/VarNode.java	Sat Mar 02 11:26:47 2013 -0400
@@ -83,20 +83,10 @@
     }
 
     @Override
-    public void setAssignmentDest(final IdentNode node) {
-        setName(name);
-    }
-
-    @Override
     public Node getAssignmentSource() {
         return isAssignment() ? getInit() : null;
     }
 
-    @Override
-    public void setAssignmentSource(final Node source) {
-        setInit(source);
-    }
-
     /**
      * Does this variable declaration have an init value
      * @return true if an init exists, false otherwise
--- a/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Sat Mar 02 11:26:47 2013 -0400
@@ -542,7 +542,7 @@
     }
 
     /**
-     * Binary enter - callback for entering && operator
+     * Binary enter - callback for entering {@literal &&} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -552,7 +552,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving a && operator
+     * Binary leave - callback for leaving a {@literal &&} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
@@ -602,7 +602,7 @@
     }
 
     /**
-     * Binary enter - callback for entering &= operator
+     * Binary enter - callback for entering {@literal &=} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -612,7 +612,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving a &= operator
+     * Binary leave - callback for leaving a {@literal &=} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
@@ -722,7 +722,7 @@
     }
 
     /**
-     * Binary enter - callback for entering >>= operator
+     * Binary enter - callback for entering {@literal >>=} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -732,7 +732,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving a >>= operator
+     * Binary leave - callback for leaving a {@literal >>=} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
@@ -742,7 +742,7 @@
     }
 
     /**
-     * Binary enter - callback for entering a <<= operator
+     * Binary enter - callback for entering a {@literal <<=} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -752,7 +752,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving a <<= operator
+     * Binary leave - callback for leaving a {@literal <<=} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
@@ -762,7 +762,7 @@
     }
 
     /**
-     * Binary enter - callback for entering >>>= operator
+     * Binary enter - callback for entering {@literal >>>=} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -772,7 +772,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving a >>>= operator
+     * Binary leave - callback for leaving a {@literal >>>=} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
@@ -822,7 +822,7 @@
     }
 
     /**
-     * Binary enter - callback for entering & operator
+     * Binary enter - callback for entering {@literal &} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -832,7 +832,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving a & operator
+     * Binary leave - callback for leaving a {@literal &} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
@@ -986,7 +986,7 @@
     }
 
     /**
-     * Binary enter - callback for entering >= operator
+     * Binary enter - callback for entering {@literal >=} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -996,7 +996,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving >= operator
+     * Binary leave - callback for leaving {@literal >=} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
@@ -1006,7 +1006,7 @@
     }
 
     /**
-     * Binary enter - callback for entering > operator
+     * Binary enter - callback for entering {@literal >} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -1016,7 +1016,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving > operator
+     * Binary leave - callback for leaving {@literal >} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
@@ -1066,7 +1066,7 @@
     }
 
     /**
-     * Binary enter - callback for entering <= operator
+     * Binary enter - callback for entering {@literal <=} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -1076,7 +1076,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving <= operator
+     * Binary leave - callback for leaving {@literal <=} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
@@ -1086,7 +1086,7 @@
     }
 
     /**
-     * Binary enter - callback for entering < operator
+     * Binary enter - callback for entering {@literal <} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -1096,7 +1096,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving < operator
+     * Binary leave - callback for leaving {@literal <} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
@@ -1205,7 +1205,7 @@
     }
 
     /**
-     * Binary enter - callback for entering >> operator
+     * Binary enter - callback for entering {@literal >>} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -1215,7 +1215,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving >> operator
+     * Binary leave - callback for leaving {@literal >>} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
@@ -1225,7 +1225,7 @@
     }
 
     /**
-     * Binary enter - callback for entering << operator
+     * Binary enter - callback for entering {@literal <<} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -1235,7 +1235,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving << operator
+     * Binary leave - callback for leaving {@literal <<} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
@@ -1244,7 +1244,7 @@
         return leaveDefault(binaryNode);
     }
     /**
-     * Binary enter - callback for entering >>> operator
+     * Binary enter - callback for entering {@literal >>>} operator
      *
      * @param  binaryNode the node
      * @return processed node
@@ -1254,7 +1254,7 @@
     }
 
     /**
-     * Binary leave - callback for leaving >>> operator
+     * Binary leave - callback for leaving {@literal >>>} operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
--- a/src/jdk/nashorn/internal/objects/DateParser.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/objects/DateParser.java	Sat Mar 02 11:26:47 2013 -0400
@@ -221,7 +221,7 @@
      *
      * <p>English month names and selected time zone names as well as AM/PM markers are recognized
      * and handled properly. Additionally, numeric time zone offsets such as <tt>(+|-)hh:mm</tt> or
-     * <tt></tt>(+|-)hhmm</tt> are recognized. If the string does not contain a time zone offset
+     * <tt>(+|-)hhmm</tt> are recognized. If the string does not contain a time zone offset
      * the <tt>TIMEZONE</tt>field is left undefined, meaning the local time zone should be applied.</p>
      *
      * <p>English weekday names are recognized but ignored. All text in parentheses is ignored as well.
--- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Sat Mar 02 11:26:47 2013 -0400
@@ -74,13 +74,16 @@
  *    delete x.p;                 // calls y.__delete__
  *    for (i in x) { print(i); }  // calls y.__getIds__
  * </pre>
+ * <p>
  * JavaScript caller of adapter object is isolated from the fact that the property access/mutation/deletion are really
  * calls to JavaScript methods on adaptee.
- * </p><p>
+ * </p>
+ * <p>
  * JSAdapter constructor can optionally receive an "overrides" object. Properties of overrides object is copied to
  * JSAdapter instance. When user accessed property is one of these, then adaptee's methods like {@code __get__},
  * {@code __put__} etc. are not called for those. This can be used to make certain "preferred" properties that can be
  * accessed in the usual/faster way avoiding proxy mechanism. Example:
+ * </p>
  * <pre>
  *     var x = new JSAdapter({ foo: 444, bar: 6546 }) {
  *          __get__: function(name) { return name; }
--- a/src/jdk/nashorn/internal/objects/NativeJava.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/objects/NativeJava.java	Sat Mar 02 11:26:47 2013 -0400
@@ -65,6 +65,7 @@
     }
 
     /**
+     * <p>
      * Given a name of a Java type, returns an object representing that type in Nashorn. The Java class of the objects
      * used to represent Java types in Nashorn is not {@link java.lang.Class} but rather {@link StaticClass}. They are
      * the objects that you can use with the {@code new} operator to create new instances of the class as well as to
@@ -75,7 +76,8 @@
      * different expression (e.g. {@code java.io.File}) as an argument in "new" and to address statics, and it is
      * distinct from the {@code Class} object (e.g. {@code java.io.File.class}). Below we cover in details the
      * properties of the type objects.
-     * <h2>Constructing Java objects</h2>
+     * </p>
+     * <p><b>Constructing Java objects</b></p>
      * Examples:
      * <pre>
      * var arrayListType = Java.type("java.util.ArrayList")
@@ -104,19 +106,24 @@
      * var arctype = Java.type("java.awt.geom.Arc2D")
      * var ftype = arctype.Float
      * </pre>
+     * <p>
      * You can access both static and non-static inner classes. If you want to create an instance of a non-static
      * inner class, remember to pass an instance of its outer class as the first argument to the constructor.
-     * </p><p>
+     * </p>
+     * <p>
      * If the type is abstract, you can instantiate an anonymous subclass of it using an argument list that is
      * applicable to any of its public or protected constructors, but inserting a JavaScript object with functions
      * properties that provide JavaScript implementations of the abstract methods. If method names are overloaded, the
      * JavaScript function will provide implementation for all overloads. E.g.:
+     * </p>
      * <pre>
      * var TimerTask =  Java.type("java.util.TimerTask")
      * var task = new TimerTask({ run: function() { print("Hello World!") } })
      * </pre>
+     * <p>
      * Nashorn supports a syntactic extension where a "new" expression followed by an argument is identical to
      * invoking the constructor and passing the argument to it, so you can write the above example also as:
+     * </p>
      * <pre>
      * var task = new TimerTask {
      *     run: function() {
@@ -124,30 +131,38 @@
      *     }
      * }
      * </pre>
+     * <p>
      * which is very similar to Java anonymous inner class definition. On the other hand, if the type is an abstract
      * type with a single abstract method (commonly referred to as a "SAM type") or all abstract methods it has share
      * the same overloaded name), then instead of an object, you can just pass a function, so the above example can
      * become even more simplified to:
+     * </p>
      * <pre>
      * var task = new TimerTask(function() { print("Hello World!") })
      * </pre>
+     * <p>
      * Note that in every one of these cases if you are trying to instantiate an abstract class that has constructors
      * that take some arguments, you can invoke those simply by specifying the arguments after the initial
      * implementation object or function.
-     * </p><p>The use of functions can be taken even further; if you are invoking a Java method that takes a SAM type,
+     * </p>
+     * <p>The use of functions can be taken even further; if you are invoking a Java method that takes a SAM type,
      * you can just pass in a function object, and Nashorn will know what you meant:
+     * </p>
      * <pre>
      * var timer = new Java.type("java.util.Timer")
      * timer.schedule(function() { print("Hello World!") })
      * </pre>
+     * <p>
      * Here, {@code Timer.schedule()} expects a {@code TimerTask} as its argument, so Nashorn creates an instance of a
      * {@code TimerTask} subclass and uses the passed function to implement its only abstract method, {@code run()}. In
      * this usage though, you can't use non-default constructors; the type must be either an interface, or must have a
      * protected or public no-arg constructor.
-     * </p><p>
+     * </p>
+     * <p>
      * You can also subclass non-abstract classes; for that you will need to use the {@link #extend(Object, Object...)}
      * method.
-     * <h2>Accessing static members</h2>
+     * </p>
+     * <p><b>Accessing static members</b></p>
      * Examples:
      * <pre>
      * var File = Java.type("java.io.File")
@@ -176,7 +191,7 @@
      * var File = Java.type("java.io.File")
      * print(File.class.static === File) // prints true
      * </pre>
-     * <h2>{@code instanceof} operator</h2>
+     * <p><b>{@code instanceof} operator</b></p>
      * The standard ECMAScript {@code instanceof} operator is extended to recognize Java objects and their type objects:
      * <pre>
      * var File = Java.type("java.io.File")
@@ -368,6 +383,7 @@
      * <li>If the Java method is overloaded (as in the above example {@code List.add()}), then your JavaScript adapter
      * must be prepared to deal with all overloads.</li>
      * <li>You can't invoke {@code super.*()} from adapters for now.</li>
+     * </ul>
      * @param self not used
      * @param types the original types. The caller must pass at least one Java type object of class {@link StaticClass}
      * representing either a public interface or a non-final public class with at least one public or protected
--- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java	Sat Mar 02 11:26:47 2013 -0400
@@ -30,7 +30,7 @@
  * As only the code generating package (i.e. Context) knows about
  * the ScriptLoader and it would be a security hazard otherwise
  * the Compiler is given an installation interface for its code.
- * <p>>
+ * <p>
  * The compiler still retains most of the state around code emission
  * and management internally, so this is to avoid passing around any
  * logic that isn't directly related to installing a class
--- a/src/jdk/nashorn/internal/runtime/Context.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/runtime/Context.java	Sat Mar 02 11:26:47 2013 -0400
@@ -509,7 +509,7 @@
      *
      * @param fullName  full name of class, e.g. jdk.nashorn.internal.objects.JO$2P1 contains 2 fields and 1 parameter.
      *
-     * @return the Class<?> for this structure
+     * @return the {@code Class<?>} for this structure
      *
      * @throws ClassNotFoundException if structure class cannot be resolved
      */
@@ -523,7 +523,7 @@
      *
      * @param fullName full name of class to load
      *
-     * @return the Class<?> for the name
+     * @return the {@code Class<?>} for the name
      *
      * @throws ClassNotFoundException if class cannot be resolved
      */
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Sat Mar 02 11:26:47 2013 -0400
@@ -1463,7 +1463,7 @@
     }
 
     /**
-     * Returns the set of <property, value> entries that make up this
+     * Returns the set of {@literal <property, value>} entries that make up this
      * ScriptObject's properties
      * (java.util.Map-like method to help ScriptObjectMirror implementation)
      *
@@ -1524,7 +1524,7 @@
      * of their keys to their values
      * (java.util.Map-like method to help ScriptObjectMirror implementation)
      *
-     * @param otherMap a <key,value> map of properties to add
+     * @param otherMap a {@literal <key,value>} map of properties to add
      */
     public void putAll(final Map<?, ?> otherMap) {
         final boolean strict = getContext()._strict;
--- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java	Sat Mar 02 11:26:47 2013 -0400
@@ -815,7 +815,7 @@
     }
 
     /**
-     * ECMA 11.8.1 - The less than operator (<) - generic implementation
+     * ECMA 11.8.1 - The less than operator ({@literal <}) - generic implementation
      *
      * @param x first object to compare
      * @param y second object to compare
@@ -828,7 +828,7 @@
     }
 
     /**
-     * ECMA 11.8.2 - The greater than operator (>) - generic implementation
+     * ECMA 11.8.2 - The greater than operator ({@literal >}) - generic implementation
      *
      * @param x first object to compare
      * @param y second object to compare
@@ -841,7 +841,7 @@
     }
 
     /**
-     * ECMA 11.8.3 - The less than or equal operator (<=) - generic implementation
+     * ECMA 11.8.3 - The less than or equal operator ({@literal <=}) - generic implementation
      *
      * @param x first object to compare
      * @param y second object to compare
@@ -854,7 +854,7 @@
     }
 
     /**
-     * ECMA 11.8.4 - The greater than or equal operator (>=) - generic implementation
+     * ECMA 11.8.4 - The greater than or equal operator ({@literal >=}) - generic implementation
      *
      * @param x first object to compare
      * @param y second object to compare
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java	Sat Mar 02 11:26:47 2013 -0400
@@ -87,7 +87,7 @@
 import jdk.nashorn.internal.runtime.Undefined;
 
 /**
- * A factory class that generates adapter classes. Adapter classes allow implementation of Java interfaces and
+ * <p>A factory class that generates adapter classes. Adapter classes allow implementation of Java interfaces and
  * extending of Java classes from JavaScript. For every combination of a superclass to extend and interfaces to
  * implement (collectively: "original types"), exactly one adapter class is generated that extends the specified
  * superclass and implements the specified interfaces.
--- a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Sat Mar 02 11:26:47 2013 -0400
@@ -43,8 +43,6 @@
     public static final int CALLSITE_SCOPE                = 0x01;
     /** Flags that the call site is in code that uses ECMAScript strict mode. */
     public static final int CALLSITE_STRICT               = 0x02;
-    /** Flags that a property setter call site is part of a function declaration that assigns the function object to a name. */
-    public static final int CALLSITE_FUNCTION_DECLARATION = 0x04;
     /** Flags that a property getter or setter call site references a scope variable that is not in the global scope
      * (it is in a function lexical scope), and the function's scope object class is fixed and known in advance. Such
      * getters and setters can often be linked more optimally using these assumptions. */
@@ -182,7 +180,7 @@
     /**
      * Returns the named operand in this descriptor's name. Equivalent to
      * {@code getNameToken(CallSiteDescriptor.NAME_OPERAND)}. E.g. for operation {@code "dyn:getProp:color"}, returns
-     * {@code "color"}. For call sites without named operands (e.g. {@link "dyn:new"}) returns null.
+     * {@code "color"}. For call sites without named operands (e.g. {@code "dyn:new"}) returns null.
      * @return the named operand in this descriptor's name.
      */
     public String getOperand() {
--- a/src/jdk/nashorn/internal/runtime/options/Options.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/runtime/options/Options.java	Sat Mar 02 11:26:47 2013 -0400
@@ -200,7 +200,7 @@
 
     /**
      * Return an option given its resource key. If the key doesn't begin with
-     * <resource>.option it will be completed using the resource from this
+     * {@literal <resource>}.option it will be completed using the resource from this
      * instance
      *
      * @param key key for option
--- a/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java	Sat Mar 02 11:26:47 2013 -0400
@@ -117,10 +117,6 @@
             return new JoniRegExp(pattern, flags);
         }
 
-        @Override
-        protected String replaceToken(final String str) {
-            return str.equals("[^]") ? "[\\s\\S]" : str;
-        }
     }
 
     class JoniMatcher implements RegExpMatcher {
--- a/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java	Sat Mar 02 11:26:47 2013 -0400
@@ -68,25 +68,6 @@
     }
 
     /**
-     * Replace a regexp token as suitable for regexp instances created by this factory.
-     *
-     * @param str a regular expression token
-     * @return the replacement token
-     */
-    protected String replaceToken(final String str) {
-        switch (str) {
-            case "\\s":
-                return "[" + Lexer.getWhitespaceRegExp() + "]";
-            case "\\S":
-                return "[^" + Lexer.getWhitespaceRegExp() + "]";
-            case "[^]":
-                return "[\\s\\S]";
-            default:
-                return str;
-        }
-    }
-
-    /**
      * Compile a regexp with the given {@code source} and {@code flags}.
      *
      * @param pattern RegExp pattern string
@@ -99,16 +80,6 @@
     }
 
     /**
-     * Replace a regexp token as needed by the currently installed factory instance.
-     *
-     * @param token a regexp token
-     * @return the replacement token
-     */
-    public static String replace(final String token) {
-        return instance.replaceToken(token);
-    }
-
-    /**
      * Validate a regexp with the given {@code source} and {@code flags}.
      *
      * @param pattern RegExp pattern string
@@ -120,4 +91,13 @@
     public static void validate(final String pattern, final String flags) throws ParserException {
         instance.compile(pattern, flags);
     }
+
+    /**
+     * Returns true if the instance uses the JDK's {@code java.util.regex} package.
+     *
+     * @return true if instance uses JDK regex package
+     */
+    public static boolean usesJavaUtilRegex() {
+        return instance != null && instance.getClass() == RegExpFactory.class;
+    }
 }
--- a/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java	Sat Mar 02 11:26:47 2013 -0400
@@ -25,15 +25,15 @@
 
 package jdk.nashorn.internal.runtime.regexp;
 
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.regex.PatternSyntaxException;
 
+import jdk.nashorn.internal.parser.Lexer;
 import jdk.nashorn.internal.parser.Scanner;
 import jdk.nashorn.internal.runtime.BitVector;
 
@@ -44,17 +44,13 @@
 final class RegExpScanner extends Scanner {
 
     /**
-     * String builder to accumulate the result - this contains verbatim parsed JavaScript.
-     * to get the java equivalent we need to create a Pattern token and return its toString()
+     * String builder used to rewrite the pattern for the currently used regexp factory.
      */
     private final StringBuilder sb;
 
     /** Is this the special case of a regexp that never matches anything */
     private boolean neverMatches;
 
-    /** The resulting java.util.regex pattern string. */
-    private String javaPattern;
-
     /** Expected token table */
     private final Map<Character, Integer> expected = new HashMap<>();
 
@@ -62,11 +58,14 @@
     private final List<Capture> caps = new LinkedList<>();
 
     /** Forward references to capturing parenthesis to be resolved later.*/
-    private final Map<Integer, Token> forwardReferences = new LinkedHashMap<>();
+    private final Set<Integer> forwardReferences = new LinkedHashSet<>();
 
     /** Current level of zero-width negative lookahead assertions. */
     private int negativeLookaheadLevel;
 
+    /** Are we currently inside a character class? */
+    private boolean inCharClass = false;
+
     private static final String NON_IDENT_ESCAPES = "$^*+(){}[]|\\.?";
 
     private static class Capture {
@@ -74,11 +73,6 @@
          * Zero-width negative lookaheads enclosing the capture.
          */
         private final int negativeLookaheadLevel;
-        /**
-         * Captures that live inside a negative lookahead are dead after the
-         * lookahead and will be undefined if referenced from outside.
-         */
-        private boolean isDead;
 
         Capture(final int negativeLookaheadLevel) {
             this.negativeLookaheadLevel = negativeLookaheadLevel;
@@ -88,336 +82,6 @@
             return negativeLookaheadLevel;
         }
 
-        public boolean isDead() {
-            return isDead;
-        }
-
-        public void setDead() {
-            this.isDead = true;
-        }
-    }
-
-    /**
-     * This is a token - the JavaScript regexp is scanned into a token tree
-     * A token has other tokens as children as well as "atoms", i.e. Strings.
-     */
-    private static class Token {
-
-        private enum Type {
-            PATTERN,
-            DISJUNCTION,
-            ALTERNATIVE,
-            TERM,
-            ASSERTION,
-            QUANTIFIER,
-            QUANTIFIER_PREFIX,
-            ATOM,
-            PATTERN_CHARACTER,
-            ATOM_ESCAPE,
-            CHARACTER_ESCAPE,
-            CONTROL_ESCAPE,
-            CONTROL_LETTER,
-            IDENTITY_ESCAPE,
-            DECIMAL_ESCAPE,
-            CHARACTERCLASS_ESCAPE,
-            CHARACTERCLASS,
-            CLASSRANGES,
-            NON_EMPTY_CLASSRANGES,
-            NON_EMPTY_CLASSRANGES_NODASH,
-            CLASSATOM,
-            CLASSATOM_NODASH,
-            CLASS_ESCAPE,
-            DECIMALDIGITS,
-            HEX_ESCAPESEQUENCE,
-            UNICODE_ESCAPESEQUENCE,
-        }
-
-        /**
-         * Token tyoe
-         */
-        private final Token.Type type;
-
-        /**
-         * Child nodes
-         */
-        private final List<Object> children;
-
-        /**
-         * Parent node
-         */
-        private Token parent;
-
-        /**
-         * Dead code flag
-         */
-        private boolean isDead;
-
-        private static final Map<Type, ToString> toStringMap = new HashMap<>();
-        private static final ToString DEFAULT_TOSTRING = new ToString();
-
-        private static String unicode(final int value) {
-            final StringBuilder sb = new StringBuilder();
-            final String hex = Integer.toHexString(value);
-            sb.append('u');
-            for (int i = 0; i < 4 - hex.length(); i++) {
-                sb.append('0');
-            }
-            sb.append(hex);
-
-            return sb.toString();
-        }
-
-        static {
-            toStringMap.put(Type.CHARACTERCLASS, new ToString() {
-                @Override
-                public String toString(final Token token) {
-                    return super.toString(token).replace("\\b", "\b");
-                }
-            });
-
-            // for some reason java regexps don't like control characters on the
-            // form "\\ca".match([string with ascii 1 at char0]). Translating
-            // them to unicode does it though.
-            toStringMap.put(Type.CHARACTER_ESCAPE, new ToString() {
-                @Override
-                public String toString(final Token token) {
-                    final String str = super.toString(token);
-                    if (str.length() == 2) {
-                        return Token.unicode(Character.toLowerCase(str.charAt(1)) - 'a' + 1);
-                    }
-                    return str;
-                }
-            });
-
-            toStringMap.put(Type.DECIMAL_ESCAPE, new ToString() {
-                @Override
-                public String toString(final Token token) {
-                    final String str = super.toString(token);
-
-                    if ("\0".equals(str)) {
-                        return str;
-                    }
-
-                    int value;
-
-                    if (!token.hasParentOfType(Type.CLASSRANGES)) {
-                        return str;
-                    }
-
-                    value = Integer.parseInt(str, 8); //throws exception that leads to SyntaxError if not octal
-                    if (value > 0xff) {
-                        throw new NumberFormatException(str);
-                    }
-
-                    return Token.unicode(value);
-                }
-            });
-
-        }
-
-        /**
-         * JavaScript Token to Java regex substring framework.
-         */
-        private static class ToString {
-            String toString(final Token token) {
-                final Object[] children = token.getChildren();
-
-                // Allow the installed regexp factory to perform global substitutions.
-                switch (children.length) {
-                    case 0:
-                        return "";
-                    case 1:
-                        return RegExpFactory.replace(children[0].toString());
-                    default:
-                        final StringBuilder sb = new StringBuilder();
-                        for (final Object child : children) {
-                            sb.append(child);
-                        }
-                        return RegExpFactory.replace(sb.toString());
-                }
-            }
-        }
-
-        /**
-         * Token iterator. Doesn't return "atom" children. i.e. string representations,
-         * just tokens
-         *
-         */
-        private static class TokenIterator implements Iterator<Token> {
-            private final List<Token> preorder;
-
-            private void init(final Token root) {
-                preorder.add(root);
-                for (final Object child : root.getChildren()) {
-                    if (child instanceof Token) {
-                        init((Token)child);
-                    }
-                }
-            }
-
-            TokenIterator(final Token root) {
-                preorder = new ArrayList<>();
-                init(root);
-            }
-
-            @Override
-            public boolean hasNext() {
-                return !preorder.isEmpty();
-            }
-
-            @Override
-            public Token next() {
-                return preorder.remove(0);
-            }
-
-            @Override
-            public void remove() {
-                next();
-            }
-        }
-
-        /**
-         * Constructor
-         * @param type the token type
-         */
-        Token(final Token.Type type) {
-            this.type = type;
-            children = new ArrayList<>();
-        }
-
-        /**
-         * Add a an "atom" child to a token
-         * @param child the child to add
-         * @return the token (for chaining)
-         */
-        public Token add(final String child) {
-            children.add(child);
-            return this;
-        }
-
-        /**
-         * Add a child to a token
-         * @param child the child
-         * @return the token (for chaining)
-         */
-        public Token add(final Token child) {
-            if (child != null) {
-                children.add(child);
-                child.setParent(this);
-            }
-            return this;
-        }
-
-        /**
-         * Remove a child from a token
-         * @param child the child to remove
-         * @return true if successful
-         */
-        public boolean remove(final Token child) {
-            return children.remove(child);
-        }
-
-        /**
-         * Remove the last child from a token
-         * @return the removed child
-         */
-        public Object removeLast() {
-            return children.remove(children.size() - 1);
-        }
-
-        /**
-         * Flag this token as dead code
-         * @param isDead is it dead or not
-         */
-        private void setIsDead(final boolean isDead) {
-            this.isDead = isDead;
-        }
-
-        /**
-         * Is this token dead code
-         * @return boolean
-         */
-        private boolean getIsDead() {
-            return isDead;
-        }
-
-        /**
-         * Get the parent of this token
-         * @return parent token
-         */
-        public Token getParent() {
-            return parent;
-        }
-
-        public boolean hasParentOfType(final Token.Type parentType) {
-            for (Token p = getParent(); p != null; p = p.getParent()) {
-                if (p.getType() == parentType) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public boolean hasChildOfType(final Token.Type childType) {
-            for (final Iterator<Token> iter = iterator() ; iter.hasNext() ; ) {
-                if (iter.next().getType() == childType) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        /**
-         * Set the parent of this token
-         * @param parent
-         */
-        private void setParent(final Token parent) {
-            this.parent = parent;
-        }
-
-        /**
-         * Get the children of this token
-         * @return an array of children, never null
-         */
-        public Object[] getChildren() {
-            return children.toArray();
-        }
-
-        /**
-         * Reset this token, remove all children
-         */
-        public void reset() {
-            children.clear();
-        }
-
-        /**
-         * Get a preorder token iterator with this token as root
-         * @return an iterator
-         */
-        public Iterator<Token> iterator() {
-            return new TokenIterator(this);
-        }
-
-        /**
-         * Get the type of this token
-         * @return type
-         */
-        public Type getType() {
-            return type;
-        }
-
-        /**
-         * Turn this token into Java regexp compatible text
-         * @return part of a java regexp
-         */
-        @Override
-        public String toString() {
-            ToString t = toStringMap.get(getType());
-            if (t == null) {
-                t = DEFAULT_TOSTRING;
-            }
-            return t.toString(this);
-        }
     }
 
     /**
@@ -437,13 +101,11 @@
             return;
         }
 
-        for (final Map.Entry<Integer, Token> fwdRef : forwardReferences.entrySet()) {
-            if (fwdRef.getKey().intValue() > caps.size()) {
+        for (final Integer ref : forwardReferences) {
+            if (ref.intValue() > caps.size()) {
                 neverMatches = true;
                 break;
             }
-
-            fwdRef.getValue().setIsDead(true);
         }
 
         forwardReferences.clear();
@@ -459,12 +121,10 @@
     public static RegExpScanner scan(final String string) {
         final RegExpScanner scanner = new RegExpScanner(string);
 
-        Token pattern;
-
         try {
-            pattern = scanner.pattern();
+            scanner.disjunction();
         } catch (final Exception e) {
-            throw new PatternSyntaxException(e.getMessage(), string, scanner.sb.length());
+            throw new PatternSyntaxException(e.getMessage(), string, scanner.position);
         }
 
         scanner.processForwardReferences();
@@ -472,24 +132,12 @@
             return null; // never matches
         }
 
-        // go over the code and remove dead code
-        final Iterator<Token> iter = pattern.iterator();
-        while (iter.hasNext()) {
-            final Token next = iter.next();
-            if (next.getIsDead()) {
-                next.getParent().remove(next);
-            }
-        }
-
-        // turn the pattern into a string, p, the java equivalent string for our js regexp
-        final String p = pattern.toString();
-        // if builder contains all tokens that were sent in, we know
-        // we correctly parsed the entire JavaScript regexp without syntax errors
-        if (!string.equals(scanner.getStringBuilder().toString())) {
+        // Throw syntax error unless we parsed the entire JavaScript regexp without syntax errors
+        if (scanner.position != string.length()) {
+            final String p = scanner.getStringBuilder().toString();
             throw new PatternSyntaxException(string, p, p.length() + 1);
         }
 
-        scanner.javaPattern = p;
         return scanner;
      }
 
@@ -508,7 +156,7 @@
     }
 
     String getJavaPattern() {
-        return javaPattern;
+        return sb.toString();
     }
 
     BitVector getGroupsInNegativeLookahead() {
@@ -527,11 +175,10 @@
 
     /**
      * Commit n characters to the builder and to a given token
-     * @param token Uncommitted token.
      * @param n     Number of characters.
      * @return Committed token
      */
-    private Token commit(final Token token, final int n) {
+    private boolean commit(final int n) {
         final int startIn = position;
 
         switch (n) {
@@ -554,11 +201,7 @@
             assert false : "Should not reach here";
         }
 
-        if (token == null) {
-            return null;
-        }
-
-        return token.add(sb.substring(startIn, sb.length()));
+        return true;
     }
 
     /**
@@ -587,35 +230,20 @@
      */
 
     /*
-     * Pattern ::
-     *      Disjunction
-     */
-    private Token pattern() {
-        final Token token = new Token(Token.Type.PATTERN);
-
-        final Token child = disjunction();
-        return token.add(child);
-    }
-
-    /*
      * Disjunction ::
      *      Alternative
      *      Alternative | Disjunction
      */
-    private Token disjunction() {
-        final Token token = new Token(Token.Type.DISJUNCTION);
-
+    private void disjunction() {
         while (true) {
-            token.add(alternative());
+            alternative();
 
             if (ch0 == '|') {
-                commit(token, 1);
+                commit(1);
             } else {
                 break;
             }
         }
-
-        return token;
     }
 
     /*
@@ -623,15 +251,10 @@
      *      [empty]
      *      Alternative Term
      */
-    private Token alternative() {
-        final Token token = new Token(Token.Type.ALTERNATIVE);
-
-        Token child;
-        while ((child = term()) != null) {
-            token.add(child);
+    private void alternative() {
+        while (term()) {
+            // do nothing
         }
-
-        return token;
     }
 
     /*
@@ -640,48 +263,37 @@
      *      Atom
      *      Atom Quantifier
      */
-    private Token term() {
+    private boolean term() {
         final int startIn  = position;
         final int startOut = sb.length();
-        final Token token  = new Token(Token.Type.TERM);
-        Token child;
 
-        child = assertion();
-        if (child != null) {
-            return token.add(child);
+        if (assertion()) {
+            return true;
         }
 
-        child = atom();
-        if (child != null) {
+        if (atom()) {
             boolean emptyCharacterClass = false;
-            if ("[]".equals(child.toString())) {
+            if (sb.toString().endsWith("[]")) {
                 emptyCharacterClass = true;
+            } else if (sb.toString().endsWith("[^]")) {
+                sb.setLength(sb.length() - 2);
+                sb.append("\\s\\S]");
             }
 
-            token.add(child);
-
-            final Token quantifier = quantifier();
-            if (quantifier != null) {
-                token.add(quantifier);
-            }
+            boolean quantifier = quantifier();
 
             if (emptyCharacterClass) {
-                if (quantifier == null) {
+                if (!quantifier) {
                     neverMatches = true; //never matches ever.
-                } else {
-                    //if we can get away with max zero, remove this entire token
-                    final String qs = quantifier.toString();
-                    if ("+".equals(qs) || "*".equals(qs) || qs.startsWith("{0,")) {
-                        token.setIsDead(true);
-                    }
                 }
+                // Note: we could check if quantifier has min zero to mark empty character class as dead.
             }
 
-            return token;
+            return true;
         }
 
         restart(startIn, startOut);
-        return null;
+        return false;
     }
 
     /*
@@ -693,19 +305,18 @@
      *      ( ? = Disjunction )
      *      ( ? ! Disjunction )
      */
-    private Token assertion() {
+    private boolean assertion() {
         final int startIn  = position;
         final int startOut = sb.length();
-        final Token token  = new Token(Token.Type.ASSERTION);
 
         switch (ch0) {
         case '^':
         case '$':
-            return commit(token, 1);
+            return commit(1);
 
         case '\\':
             if (ch1 == 'b' || ch1 == 'B') {
-                return commit(token, 2);
+                return commit(2);
             }
             break;
 
@@ -717,24 +328,18 @@
                 break;
             }
             final boolean isNegativeLookahead = (ch2 == '!');
-            commit(token, 3);
+            commit(3);
 
             if (isNegativeLookahead) {
                 negativeLookaheadLevel++;
             }
-            final Token disjunction = disjunction();
+            disjunction();
             if (isNegativeLookahead) {
-                for (final Capture cap : caps) {
-                    if (cap.getNegativeLookaheadLevel() >= negativeLookaheadLevel) {
-                        cap.setDead();
-                    }
-                }
                 negativeLookaheadLevel--;
             }
 
-            if (disjunction != null && ch0 == ')') {
-                token.add(disjunction);
-                return commit(token, 1);
+            if (ch0 == ')') {
+                return commit(1);
             }
             break;
 
@@ -743,8 +348,7 @@
         }
 
         restart(startIn, startOut);
-
-        return null;
+        return false;
     }
 
     /*
@@ -752,17 +356,14 @@
      *      QuantifierPrefix
      *      QuantifierPrefix ?
      */
-    private Token quantifier() {
-        final Token token = new Token(Token.Type.QUANTIFIER);
-        final Token child = quantifierPrefix();
-        if (child != null) {
-            token.add(child);
+    private boolean quantifier() {
+        if (quantifierPrefix()) {
             if (ch0 == '?') {
-                commit(token, 1);
+                commit(1);
             }
-            return token;
+            return true;
         }
-        return null;
+        return false;
     }
 
     /*
@@ -774,45 +375,42 @@
      *      { DecimalDigits , }
      *      { DecimalDigits , DecimalDigits }
      */
-    private Token quantifierPrefix() {
+    private boolean quantifierPrefix() {
         final int startIn  = position;
         final int startOut = sb.length();
-        final Token token  = new Token(Token.Type.QUANTIFIER_PREFIX);
 
         switch (ch0) {
         case '*':
         case '+':
         case '?':
-            return commit(token, 1);
+            return commit(1);
 
         case '{':
-            commit(token, 1);
+            commit(1);
 
-            final Token child = decimalDigits();
-            if (child == null) {
+            if (!decimalDigits()) {
                 break; // not a quantifier - back out
             }
             push('}');
-            token.add(child);
 
             if (ch0 == ',') {
-                commit(token, 1);
-                token.add(decimalDigits());
+                commit(1);
+                decimalDigits();
             }
 
             if (ch0 == '}') {
                 pop('}');
-                commit(token, 1);
+                commit(1);
             }
 
-            return token;
+            return true;
 
         default:
             break;
         }
 
         restart(startIn, startOut);
-        return null;
+        return false;
     }
 
     /*
@@ -825,81 +423,51 @@
      *      ( ? : Disjunction )
      *
      */
-    private Token atom() {
+    private boolean atom() {
         final int startIn  = position;
         final int startOut = sb.length();
-        final Token token  = new Token(Token.Type.ATOM);
-        Token child;
 
-        child = patternCharacter();
-        if (child != null) {
-            return token.add(child);
+        if (patternCharacter()) {
+            return true;
         }
 
         if (ch0 == '.') {
-            return commit(token, 1);
+            return commit(1);
         }
 
         if (ch0 == '\\') {
-            commit(token, 1);
-            child = atomEscape();
-
-            if (child != null) {
-                if (child.hasChildOfType(Token.Type.IDENTITY_ESCAPE)) {
-                    final char idEscape = child.toString().charAt(0);
-                    if (NON_IDENT_ESCAPES.indexOf(idEscape) == -1) {
-                        token.reset();
-                    }
-                }
-
-                token.add(child);
+            commit(1);
 
-                // forward backreferences always match empty. JavaScript != Java
-                if (child.hasChildOfType(Token.Type.DECIMAL_ESCAPE) && !"\u0000".equals(child.toString())) {
-                    final int refNum = Integer.parseInt(child.toString());
-
-                    if (refNum - 1 < caps.size() && caps.get(refNum - 1).isDead()) {
-                        // reference to dead in-negative-lookahead capture
-                        token.setIsDead(true);
-                    } else if (caps.size() < refNum) {
-                        // forward reference: always matches against empty string (dead token).
-                        // invalid reference (non-existant capture): pattern never matches.
-                        forwardReferences.put(refNum, token);
-                    }
-                }
-
-                return token;
+            if (atomEscape()) {
+                return true;
             }
         }
 
-        child = characterClass();
-        if (child != null) {
-            return token.add(child);
+        if (characterClass()) {
+            return true;
         }
 
         if (ch0 == '(') {
             boolean capturingParens = true;
-            commit(token, 1);
+            commit(1);
             if (ch0 == '?' && ch1 == ':') {
                 capturingParens = false;
-                commit(token, 2);
+                commit(2);
             }
 
-            child = disjunction();
-            if (child != null) {
-                token.add(child);
-                if (ch0 == ')') {
-                    final Token atom = commit(token, 1);
-                    if (capturingParens) {
-                        caps.add(new Capture(negativeLookaheadLevel));
-                    }
-                    return atom;
+            disjunction();
+
+            if (ch0 == ')') {
+                commit(1);
+                if (capturingParens) {
+                    caps.add(new Capture(negativeLookaheadLevel));
                 }
+                return true;
             }
         }
 
         restart(startIn, startOut);
-        return null;
+        return false;
     }
 
     /*
@@ -907,9 +475,9 @@
      *      SourceCharacter but not any of: ^$\.*+?()[]{}|
      */
     @SuppressWarnings("fallthrough")
-    private Token patternCharacter() {
+    private boolean patternCharacter() {
         if (atEOF()) {
-            return null;
+            return false;
         }
 
         switch (ch0) {
@@ -924,23 +492,26 @@
         case ')':
         case '[':
         case '|':
-            return null;
+            return false;
 
         case '}':
         case ']':
             final int n = expected.get(ch0);
             if (n != 0) {
-                return null;
+                return false;
             }
 
        case '{':
            // if not a valid quantifier escape curly brace to match itself
            // this ensures compatibility with other JS implementations
-           final Token quant = quantifierPrefix();
-           return (quant == null) ? commit(new Token(Token.Type.PATTERN_CHARACTER).add("\\"), 1) : null;
+           if (!quantifierPrefix()) {
+               sb.append('\\');
+               return commit(1);
+           }
+           return false;
 
         default:
-            return commit(new Token(Token.Type.PATTERN_CHARACTER), 1); // SOURCECHARACTER
+            return commit(1); // SOURCECHARACTER
         }
     }
 
@@ -950,27 +521,9 @@
      *      CharacterEscape
      *      CharacterClassEscape
      */
-    private Token atomEscape() {
-        final Token token = new Token(Token.Type.ATOM_ESCAPE);
-        Token child;
-
-        child = decimalEscape();
-        if (child != null) {
-            return token.add(child);
-        }
-
-        child = characterClassEscape();
-        if (child != null) {
-            return token.add(child);
-        }
-
-        child = characterEscape();
-        if (child != null) {
-            return token.add(child);
-        }
-
-
-        return null;
+    private boolean atomEscape() {
+        // Note that contrary to ES 5.1 spec we put identityEscape() last because it acts as a catch-all
+        return decimalEscape() || characterClassEscape() || characterEscape() || identityEscape();
     }
 
     /*
@@ -981,48 +534,31 @@
      *      UnicodeEscapeSequence
      *      IdentityEscape
      */
-    private Token characterEscape() {
+    private boolean characterEscape() {
         final int startIn  = position;
         final int startOut = sb.length();
 
-        final Token token = new Token(Token.Type.CHARACTER_ESCAPE);
-        Token child;
-
-        child = controlEscape();
-        if (child != null) {
-            return token.add(child);
+        if (controlEscape()) {
+            return true;
         }
 
         if (ch0 == 'c') {
-            commit(token, 1);
-            child = controlLetter();
-            if (child != null) {
-                return token.add(child);
+            commit(1);
+            if (controlLetter()) {
+                return true;
             }
             restart(startIn, startOut);
         }
 
-        child = hexEscapeSequence();
-        if (child != null) {
-            return token.add(child);
-        }
-
-        child = unicodeEscapeSequence();
-        if (child != null) {
-            return token.add(child);
-        }
-
-        child = identityEscape();
-        if (child != null) {
-            return token.add(child);
+        if (hexEscapeSequence() || unicodeEscapeSequence()) {
+            return true;
         }
 
         restart(startIn, startOut);
-
-        return null;
+        return false;
     }
 
-    private boolean scanEscapeSequence(final char leader, final int length, final Token token) {
+    private boolean scanEscapeSequence(final char leader, final int length) {
         final int startIn  = position;
         final int startOut = sb.length();
 
@@ -1030,11 +566,11 @@
             return false;
         }
 
-        commit(token, 1);
+        commit(1);
         for (int i = 0; i < length; i++) {
             final char ch0l = Character.toLowerCase(ch0);
             if ((ch0l >= 'a' && ch0l <= 'f') || isDecimalDigit(ch0)) {
-                commit(token, 1);
+                commit(1);
             } else {
                 restart(startIn, startOut);
                 return false;
@@ -1044,37 +580,29 @@
         return true;
     }
 
-    private Token hexEscapeSequence() {
-        final Token token = new Token(Token.Type.HEX_ESCAPESEQUENCE);
-        if (scanEscapeSequence('x', 2, token)) {
-            return token;
-        }
-        return null;
+    private boolean hexEscapeSequence() {
+        return scanEscapeSequence('x', 2);
     }
 
-    private Token unicodeEscapeSequence() {
-        final Token token = new Token(Token.Type.UNICODE_ESCAPESEQUENCE);
-        if (scanEscapeSequence('u', 4, token)) {
-            return token;
-        }
-        return null;
+    private boolean unicodeEscapeSequence() {
+        return scanEscapeSequence('u', 4);
     }
 
     /*
      * ControlEscape ::
      *      one of fnrtv
      */
-    private Token controlEscape() {
+    private boolean controlEscape() {
         switch (ch0) {
         case 'f':
         case 'n':
         case 'r':
         case 't':
         case 'v':
-            return commit(new Token(Token.Type.CONTROL_ESCAPE), 1);
+            return commit(1);
 
         default:
-            return null;
+            return false;
         }
     }
 
@@ -1083,19 +611,18 @@
      *      one of abcdefghijklmnopqrstuvwxyz
      *      ABCDEFGHIJKLMNOPQRSTUVWXYZ
      */
-    private Token controlLetter() {
+    private boolean controlLetter() {
         final char c = Character.toUpperCase(ch0);
         if (c >= 'A' && c <= 'Z') {
-            final Token token = new Token(Token.Type.CONTROL_LETTER);
-            commit(token, 1);
-            return token;
+            // for some reason java regexps don't like control characters on the
+            // form "\\ca".match([string with ascii 1 at char0]). Translating
+            // them to unicode does it though.
+            sb.setLength(sb.length() - 1);
+            unicode(c - 'A' + 1);
+            skip(1);
+            return true;
         }
-        return null;
-        /*
-        Token token = new Token(Token.Type.CONTROL_LETTER);
-        commit(null, 1);//add original char to builder not to token
-        this.neverMatches = c < 'A' || c > 'Z';
-        return token.add(""+c);*/
+        return false;
     }
 
     /*
@@ -1104,56 +631,115 @@
      *      <ZWJ>  (200c)
      *      <ZWNJ> (200d)
      */
-    private Token identityEscape() {
-        final Token token = new Token(Token.Type.IDENTITY_ESCAPE);
-        commit(token, 1);
-        return token;
+    private boolean identityEscape() {
+        if (atEOF()) {
+            throw new RuntimeException("\\ at end of pattern"); // will be converted to PatternSyntaxException
+        }
+        // ES 5.1 A.7 requires "not IdentifierPart" here but all major engines accept any character here.
+        if (NON_IDENT_ESCAPES.indexOf(ch0) == -1) {
+            sb.setLength(sb.length() - 1);
+        }
+        return commit(1);
     }
 
     /*
      * DecimalEscape ::
      *      DecimalIntegerLiteral [lookahead DecimalDigit]
      */
-    private Token decimalEscape() {
-        final Token token = new Token(Token.Type.DECIMAL_ESCAPE);
+    private boolean decimalEscape() {
         final int startIn  = position;
         final int startOut = sb.length();
 
         if (ch0 == '0' && !isDecimalDigit(ch1)) {
-            commit(token, 1);
-            token.removeLast();
+            skip(1);
             //  DecimalEscape :: 0. If i is zero, return the EscapeValue consisting of a <NUL> character (Unicodevalue0000);
-            return token.add("\u0000");
+            sb.append("\u0000");
+            return true;
         }
 
         if (isDecimalDigit(ch0)) {
-            while (isDecimalDigit(ch0)) {
-                commit(token, 1);
+            final int num = ch0 - '0';
+
+            // Single digit escape, treat as backreference.
+            if (!isDecimalDigit(ch1)) {
+                if (num <= caps.size() && caps.get(num - 1).getNegativeLookaheadLevel() > 0) {
+                    //  Captures that live inside a negative lookahead are dead after the
+                    //  lookahead and will be undefined if referenced from outside.
+                    if (caps.get(num - 1).getNegativeLookaheadLevel() > negativeLookaheadLevel) {
+                        sb.setLength(sb.length() - 1);
+                    } else {
+                        sb.append(ch0);
+                    }
+                    skip(1);
+                    return true;
+                } else if (num > caps.size()) {
+                    // Forward reference to a capture group. Forward references are always undefined so we
+                    // can omit it from the output buffer. Additionally, if the capture group does not exist
+                    // the whole regexp becomes invalid, so register the reference for later processing.
+                    forwardReferences.add(num);
+                    sb.setLength(sb.length() - 1);
+                    skip(1);
+                    return true;
+                }
             }
-            return token;
+
+            if (inCharClass) {
+                // Convert octal escape to unicode escape if inside character class.
+                StringBuilder digit = new StringBuilder(4);
+                while (isDecimalDigit(ch0)) {
+                    digit.append(ch0);
+                    skip(1);
+                }
+
+                int value = Integer.parseInt(digit.toString(), 8); //throws exception that leads to SyntaxError if not octal
+                if (value > 0xff) {
+                    throw new NumberFormatException(digit.toString());
+                }
+
+                unicode(value);
+
+            } else {
+                // Copy decimal escape as-is
+                decimalDigits();
+            }
+            return true;
         }
 
         restart(startIn, startOut);
-
-        return null;
+        return false;
     }
 
     /*
      * CharacterClassEscape ::
      *  one of dDsSwW
      */
-    private Token characterClassEscape() {
+    private boolean characterClassEscape() {
         switch (ch0) {
+        // java.util.regex requires translation of \s and \S to explicit character list
         case 's':
+            if (RegExpFactory.usesJavaUtilRegex()) {
+                sb.setLength(sb.length() - 1);
+                sb.append('[').append(Lexer.getWhitespaceRegExp()).append(']');
+                skip(1);
+                return true;
+            }
+            return commit(1);
         case 'S':
+            if (RegExpFactory.usesJavaUtilRegex()) {
+                sb.setLength(sb.length() - 1);
+                sb.append("[^").append(Lexer.getWhitespaceRegExp()).append(']');
+                skip(1);
+                return true;
+            }
+            return commit(1);
         case 'd':
         case 'D':
         case 'w':
         case 'W':
-            return commit(new Token(Token.Type.CHARACTERCLASS_ESCAPE), 1);
+            return commit(1);
 
         default:
-            return null;
+            return false;
         }
     }
 
@@ -1162,29 +748,31 @@
      *      [ [lookahead {^}] ClassRanges ]
      *      [ ^ ClassRanges ]
      */
-    private Token characterClass() {
+    private boolean characterClass() {
         final int startIn  = position;
         final int startOut = sb.length();
-        final Token token  = new Token(Token.Type.CHARACTERCLASS);
 
         if (ch0 == '[') {
-            push(']');
-            commit(token, 1);
+            try {
+                inCharClass = true;
+                push(']');
+                commit(1);
 
-            if (ch0 == '^') {
-                commit(token, 1);
-            }
+                if (ch0 == '^') {
+                    commit(1);
+                }
 
-            final Token child = classRanges();
-            if (child != null && ch0 == ']') {
-                pop(']');
-                token.add(child);
-                return commit(token, 1);
+                if (classRanges() && ch0 == ']') {
+                    pop(']');
+                    return commit(1);
+                }
+            } finally {
+                inCharClass = false;  // no nested character classes in JavaScript
             }
         }
 
         restart(startIn, startOut);
-        return null;
+        return false;
     }
 
     /*
@@ -1192,8 +780,9 @@
      *      [empty]
      *      NonemptyClassRanges
      */
-    private Token classRanges() {
-        return new Token(Token.Type.CLASSRANGES).add(nonemptyClassRanges());
+    private boolean classRanges() {
+        nonemptyClassRanges();
+        return true;
     }
 
     /*
@@ -1202,40 +791,27 @@
      *      ClassAtom NonemptyClassRangesNoDash
      *      ClassAtom - ClassAtom ClassRanges
      */
-    private Token nonemptyClassRanges() {
+    private boolean nonemptyClassRanges() {
         final int startIn  = position;
         final int startOut = sb.length();
-        final Token token  = new Token(Token.Type.NON_EMPTY_CLASSRANGES);
-        Token child;
 
-        child = classAtom();
-        if (child != null) {
-            token.add(child);
+        if (classAtom()) {
 
             if (ch0 == '-') {
-                commit(token, 1);
+                commit(1);
 
-                final Token child1 = classAtom();
-                final Token child2 = classRanges();
-                if (child1 != null && child2 != null) {
-                    token.add(child1);
-                    token.add(child2);
-
-                    return token;
+                if (classAtom() && classRanges()) {
+                    return true;
                 }
             }
 
-            child = nonemptyClassRangesNoDash();
-            if (child != null) {
-                token.add(child);
-                return token;
-            }
+            nonemptyClassRangesNoDash();
 
-            return token;
+            return true;
         }
 
         restart(startIn, startOut);
-        return null;
+        return false;
     }
 
     /*
@@ -1244,61 +820,44 @@
      *      ClassAtomNoDash NonemptyClassRangesNoDash
      *      ClassAtomNoDash - ClassAtom ClassRanges
      */
-    private Token nonemptyClassRangesNoDash() {
+    private boolean nonemptyClassRangesNoDash() {
         final int startIn  = position;
         final int startOut = sb.length();
-        final Token token  = new Token(Token.Type.NON_EMPTY_CLASSRANGES_NODASH);
-        Token child;
 
-        child = classAtomNoDash();
-        if (child != null) {
-            token.add(child);
+        if (classAtomNoDash()) {
 
             // need to check dash first, as for e.g. [a-b|c-d] will otherwise parse - as an atom
             if (ch0 == '-') {
-               commit(token, 1);
+               commit(1);
 
-               final Token child1 = classAtom();
-               final Token child2 = classRanges();
-               if (child1 != null && child2 != null) {
-                   token.add(child1);
-                   return token.add(child2);
+               if (classAtom() && classRanges()) {
+                   return true;
                }
                //fallthru
            }
 
-            child = nonemptyClassRangesNoDash();
-            if (child != null) {
-                token.add(child);
-            }
-            return token; // still a class atom
+            nonemptyClassRangesNoDash();
+            return true; // still a class atom
         }
 
-        child = classAtom();
-        if (child != null) {
-            return token.add(child);
+        if (classAtom()) {
+            return true;
         }
 
         restart(startIn, startOut);
-        return null;
+        return false;
     }
 
     /*
      * ClassAtom : - ClassAtomNoDash
      */
-    private Token classAtom() {
-        final Token token = new Token(Token.Type.CLASSATOM);
+    private boolean classAtom() {
 
         if (ch0 == '-') {
-            return commit(token, 1);
+            return commit(1);
         }
 
-        final Token child = classAtomNoDash();
-        if (child != null) {
-            return token.add(child);
-        }
-
-        return null;
+        return classAtomNoDash();
     }
 
     /*
@@ -1306,33 +865,32 @@
      *      SourceCharacter but not one of \ or ] or -
      *      \ ClassEscape
      */
-    private Token classAtomNoDash() {
+    private boolean classAtomNoDash() {
         final int startIn  = position;
         final int startOut = sb.length();
-        final Token token  = new Token(Token.Type.CLASSATOM_NODASH);
 
         switch (ch0) {
         case ']':
         case '-':
         case '\0':
-            return null;
+            return false;
 
         case '[':
             // unescaped left square bracket - add escape
-            return commit(token.add("\\"), 1);
+            sb.append('\\');
+            return commit(1);
 
         case '\\':
-            commit(token, 1);
-            final Token child = classEscape();
-            if (child != null) {
-                return token.add(child);
+            commit(1);
+            if (classEscape()) {
+                return true;
             }
 
             restart(startIn, startOut);
-            return null;
+            return false;
 
         default:
-            return commit(token, 1);
+            return commit(1);
         }
     }
 
@@ -1343,46 +901,45 @@
      *      CharacterEscape
      *      CharacterClassEscape
      */
-    private Token classEscape() {
-        final Token token = new Token(Token.Type.CLASS_ESCAPE);
-        Token child;
+    private boolean classEscape() {
 
-        child = decimalEscape();
-        if (child != null) {
-            return token.add(child);
+        if (decimalEscape()) {
+            return true;
         }
 
         if (ch0 == 'b') {
-            return commit(token, 1);
+            sb.setLength(sb.length() - 1);
+            sb.append('\b');
+            skip(1);
+            return true;
         }
 
-        child = characterEscape();
-        if (child != null) {
-            return token.add(child);
-        }
-
-        child = characterClassEscape();
-        if (child != null) {
-            return token.add(child);
-        }
-
-        return null;
+        // Note that contrary to ES 5.1 spec we put identityEscape() last because it acts as a catch-all
+        return characterEscape() || characterClassEscape() || identityEscape();
     }
 
     /*
      * DecimalDigits
      */
-    private Token decimalDigits() {
+    private boolean decimalDigits() {
         if (!isDecimalDigit(ch0)) {
-            return null;
+            return false;
+        }
+
+        while (isDecimalDigit(ch0)) {
+            commit(1);
         }
 
-        final Token token = new Token(Token.Type.DECIMALDIGITS);
-        while (isDecimalDigit(ch0)) {
-            commit(token, 1);
+        return true;
+    }
+
+    private void unicode(final int value) {
+        final String hex = Integer.toHexString(value);
+        sb.append('u');
+        for (int i = 0; i < 4 - hex.length(); i++) {
+            sb.append('0');
         }
-
-        return token;
+        sb.append(hex);
     }
 
     private static boolean isDecimalDigit(final char ch) {
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java	Wed Feb 27 14:12:45 2013 +0000
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java	Sat Mar 02 11:26:47 2013 -0400
@@ -219,7 +219,7 @@
     }
 
     /**
-     * @see [http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt]
+     * @see <a href="http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt">http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt</a>
      */
     public static boolean isCodeCType(int code, int ctype) {
         int type;