Fwd: Javascript and other languages support (and Clone Digger performance)

60 views
Skip to first unread message

Haoyu Bai

unread,
Mar 4, 2009, 9:36:03 AM3/4/09
to clonedigg...@googlegroups.com
Hi,

Turn to AST representation then the problem solved! I was never aware
of the difference of AST and parse tree. Thank you Peter!

Now, Clone Digger can parse JavaScript. :-)

-- Haoyu Bai


---------- Forwarded message ----------
From: Peter Bulychev <peter.b...@gmail.com>
Date: Wed, Mar 4, 2009 at 7:19 PM
Subject: Re: Javascript and other languages support (and Clone Digger
performance)
To: Haoyu Bai <divi...@gmail.com>


Hello, Haoyu.

The quick answer is that you are using the parse tree, and it contains
a lot of extra nodes, which will not be used by Clone Digger.
You shall use an AST representation instead of that. That will speed
up the tool and improve the quality of clone detection.
The javascript grammar you referenced is able to do that.
Take a look, how it is done in the Java target (not Lua, because Lua
is using parse tree instead of AST also).

The second point is that you shall mark some AST nodes as statement
nodes. Again, take a look on how it is done for the Java target.

And the third point is that Clone Digger is offline tool for large
projects. For instance, it could be run nightly and it will require 2
hours to run on large projects on my PC.
If you want to do it much faster, you can find only exact copies, for
instance, on use another threshold parameters.

If there are no reasons for you not to use google groups, please
resend you letter there, so other people will be able to read this
(I've already answered your previous question there).
I'll try to answer in more details in google groups this evening.

2009/3/4 Haoyu Bai <divi...@gmail.com>
- Show quoted text -
>
> Hello Peter,
>
> I'm working on extending Clone Digger to support various other
> languages like Javascript, Haskell, etc. I do so because I'm working
> on a study of code clone in various languages, and Clone Digger is the
> only one clone detector I found that is Open Source and expendable.
>
> Based on your Lua parser and a Javascript ANTLR grammer file
> (http://research.xebic.com/es3/),  now the JS parser can work with CD.
> But the problem is - (again) it is slow. For example I have run it on
> jQuery library, it is 4376 lines of code and comments, and FYI here's
> the output of CD:
>
> Parsing  tests/jquery-1.3.2.js ... done
> 550 sequences
> average sequence length: 1.503636
> maximum sequence length: 8
> Number of statements:  827
> Calculating size for each statement... done
> Building statement hash... done
> Number of different hash values:  487
> Building patterns... 681 patterns were discovered
> Choosing pattern for each statement...
>
> Then it hanged on the "Choosing pattern for each statement...", more
> than 10 minutes passed, there's still no more progress.
>
> I tried to investigate this, and found that the JS parser generates
> very huge parse tree which has many nodes that not really meaningful,
> for example, a sequence of nodes that only has one son, like A -> B ->
> C -> D -> ... -> Leaf. This caused some operation of class
> AbstractSyntaxTree very slow, for example __eq__() and storeSize(). I
> have attached a AST XML generated by a much smaller JS code, for you
> to know what I exactly means.
>
> Do you have any suggestion on how to improve this? Or the grammer file
> I picked is now suitable for Clone Digger?
>
> Thanks!
>
> -- Haoyu Bai

--
Best regards,
  Peter Bulychev.

Peter Bulychev

unread,
Mar 4, 2009, 9:54:40 AM3/4/09
to clonedigg...@googlegroups.com
My congratulations!

If you want, we can put your changes to the repository.

2009/3/4 Haoyu Bai <divi...@gmail.com>

Haoyu Bai

unread,
Mar 4, 2009, 10:38:31 AM3/4/09
to clonedigg...@googlegroups.com
On Wed, Mar 4, 2009 at 10:54 PM, Peter Bulychev
<peter.b...@gmail.com> wrote:
> My congratulations!
>
> If you want, we can put your changes to the repository.

Hi,

Patch attached. However you may rerun build_jar.sh because I'm using
ANTLR 3.1.1 to generate the parser and the .jar file is not included
in this patch.

Thanks!

-- Haoyu Bai

cdjs.diff

Peter Bulychev

unread,
Mar 5, 2009, 3:12:22 AM3/5/09
to clonedigg...@googlegroups.com
I tried to parse jquery-1.3.2.min.js with the grammar you provided but it failed.

Please read the log attached

I guess there can be other ANTLR libs in your CLASSPATH or something like that.
Can you rerun my experiment? (I specified exactly which jars I was using using)
If it works fine for you, can you send me yours antlr-3.1.1.jar and antlr-3.1.1-runtime.jar?
I'll compare them with my jars.


2009/3/4 Haoyu Bai <divi...@gmail.com>
Index: ast_suppliers.py
===================================================================
--- ast_suppliers.py    (revision 201)
+++ ast_suppliers.py    (working copy)
@@ -28,3 +28,6 @@

 import lua_antlr
 abstract_syntax_tree_suppliers['lua'] = lua_antlr.LuaANTLRSourceFile
+
+import js_antlr
+abstract_syntax_tree_suppliers['js'] = js_antlr.JsANTLRSourceFile
Index: js_antlr.py
===================================================================
--- js_antlr.py (revision 0)
+++ js_antlr.py (revision 0)
@@ -0,0 +1,72 @@
+#    Copyright 2008 Peter Bulychev
+#    http://clonedigger.sourceforge.net
+#
+#    This file is part of Clone Digger.
+#
+#    Clone Digger is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    Clone Digger is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with Clone Digger.  If not, see <http://www.gnu.org/licenses/>.
+
+import pdb
+import os
+import xml.parsers.expat
+
+from abstract_syntax_tree import *
+
+class JsANTLRSourceFile (SourceFile):
+    extension = 'js'
+    size_threshold = 5
+    distance_threshold = 5
+    def __init__(self, file_name):
+        SourceFile.__init__(self, file_name)
+        class ExpatHandler:
+            def __init__(self, start_node, parent):
+                self.parent = parent
+                self.stack = [start_node]
+            def start_element(expat_self, xml_node_name, attrs):
+                line_number = int(attrs["line_number"])-1
+                line_numbers = [line_number]
+                if line_numbers == [-1]:
+                    line_numbers = []
+                name = attrs["name"]
+                r = AbstractSyntaxTree(name, line_numbers, self)
+                if xml_node_name == "statement_node":
+                #if name in ["CALL", "BLOCK"]:
+                    r.markAsStatement()
+                else:
+                    assert(xml_node_name == "node")
+                expat_self.stack[-1].addChild(r)
+                expat_self.stack.append(r)
+            def end_element(self, name):
+                self.stack.pop()
+
+        tree_file_name  = 'temporary_ast.xml'
+        if os.system('java -classpath ./js_antlr/TreeProducer.jar:./antlr_runtime/antlr-3.1.1-runtime.jar TreeProducer %s %s 2>err.log'%(file_name, tree_file_name)):
+            f = open('err.log')
+            s = f.read()
+            f.close()
+            raise Exception(s)
+        f = open('err.log')
+        s = f.read()
+        f.close()
+        if s:
+            print s
+
+        self._tree = AbstractSyntaxTree('program')
+        handler = ExpatHandler(self._tree, self)
+        p = xml.parsers.expat.ParserCreate()
+        p.StartElementHandler = handler.start_element
+        p.EndElementHandler = handler.end_element
+        f = open(tree_file_name)
+        p.ParseFile(f)
+        f.close()
+#       os.remove(tree_file_name)
Index: clonedigger.py
===================================================================
--- clonedigger.py      (revision 201)
+++ clonedigger.py      (working copy)
@@ -46,7 +46,7 @@
 The semantics of threshold options is discussed in the paper "Duplicate code detection using anti-unification", which can be downloaded from the site http://clonedigger.sourceforge.net . All arguments are optional. Supported options are:
 """)
    cmdline.add_option('-l', '--language', dest='language',
-                       type='choice', choices=['python', 'java', 'lua'],
+                       type='choice', choices=['python', 'java', 'lua', 'js'],
                       help='the programming language')
    cmdline.add_option('--no-recursion', dest='no_recursion',
                       action='store_true',
Index: js_antlr/JavaScriptParser.java
===================================================================
--- js_antlr/JavaScriptParser.java      (revision 0)
+++ js_antlr/JavaScriptParser.java      (revision 0)
@@ -0,0 +1,10124 @@
+// $ANTLR 3.1.1 JavaScript.g 2009-03-04 23:29:37
+
+import org.antlr.runtime.*;
+import java.util.Stack;
+import java.util.List;
+import java.util.ArrayList;
+
+
+import org.antlr.runtime.tree.*;
+
+public class JavaScriptParser extends Parser {
+    public static final String[] tokenNames = new String[] {
+        "<invalid>", "<EOR>", "<DOWN>", "<UP>", "NULL", "TRUE", "FALSE", "BREAK", "CASE", "CATCH", "CONTINUE", "DEFAULT", "DELETE", "DO", "ELSE", "FINALLY", "FOR", "FUNCTION", "IF", "IN", "INSTANCEOF", "NEW", "RETURN", "SWITCH", "THIS", "THROW", "TRY", "TYPEOF", "VAR", "VOID", "WHILE", "WITH", "ABSTRACT", "BOOLEAN", "BYTE", "CHAR", "CLASS", "CONST", "DEBUGGER", "DOUBLE", "ENUM", "EXPORT", "EXTENDS", "FINAL", "FLOAT", "GOTO", "IMPLEMENTS", "IMPORT", "INT", "INTERFACE", "LONG", "NATIVE", "PACKAGE", "PRIVATE", "PROTECTED", "PUBLIC", "SHORT", "STATIC", "SUPER", "SYNCHRONIZED", "THROWS", "TRANSIENT", "VOLATILE", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACK", "RBRACK", "DOT", "SEMIC", "COMMA", "LT", "GT", "LTE", "GTE", "EQ", "NEQ", "SAME", "NSAME", "ADD", "SUB", "MUL", "MOD", "INC", "DEC", "SHL", "SHR", "SHU", "AND", "OR", "XOR", "NOT", "INV", "LAND", "LOR", "QUE", "COLON", "ASSIGN", "ADDASS", "SUBASS", "MULASS", "MODASS", "SHLASS", "SHRASS", "SHUASS", "ANDASS", "ORASS", "XORASS", "DIV", "DIVASS", "ARGS", "ARRAY", "BLOCK", "BYFIELD", "BYINDEX", "CALL", "CEXPR", "EXPR", "FORITER", "FORSTEP", "ITEM", "LABELLED", "NAMEDVALUE", "NEG", "OBJECT", "PAREXPR", "PDEC", "PINC", "POS", "BSLASH", "DQUOTE", "SQUOTE", "TAB", "VT", "FF", "SP", "NBSP", "USP", "WhiteSpace", "LF", "CR", "LS", "PS", "LineTerminator", "EOL", "MultiLineComment", "SingleLineComment", "Identifier", "StringLiteral", "HexDigit", "IdentifierStartASCII", "DecimalDigit", "IdentifierPart", "IdentifierNameASCIIStart", "RegularExpressionLiteral", "OctalDigit", "ExponentPart", "DecimalIntegerLiteral", "DecimalLiteral", "OctalIntegerLiteral", "HexIntegerLiteral", "CharacterEscapeSequence", "ZeroToThree", "OctalEscapeSequence", "HexEscapeSequence", "UnicodeEscapeSequence", "EscapeSequence", "BackslashSequence", "RegularExpressionFirstChar", "RegularExpressionChar"
+    };
+    public static final int VT=134;
+    public static final int LOR=95;
+    public static final int FUNCTION=17;
+    public static final int PACKAGE=52;
+    public static final int SHR=87;
+    public static final int RegularExpressionChar=170;
+    public static final int LT=72;
+    public static final int WHILE=30;
+    public static final int MOD=83;
+    public static final int SHL=86;
+    public static final int CONST=37;
+    public static final int BackslashSequence=168;
+    public static final int LS=142;
+    public static final int CASE=8;
+    public static final int CHAR=35;
+    public static final int NEW=21;
+    public static final int DQUOTE=131;
+    public static final int DO=13;
+    public static final int NOT=92;
+    public static final int DecimalDigit=152;
+    public static final int BYFIELD=114;
+    public static final int EOF=-1;
+    public static final int CEXPR=117;
+    public static final int BREAK=7;
+    public static final int Identifier=148;
+    public static final int DIVASS=110;
+    public static final int BYINDEX=115;
+    public static final int FORSTEP=120;
+    public static final int FINAL=43;
+    public static final int RPAREN=66;
+    public static final int INC=84;
+    public static final int IMPORT=47;
+    public static final int EOL=145;
+    public static final int POS=129;
+    public static final int OctalDigit=156;
+    public static final int THIS=24;
+    public static final int RETURN=22;
+    public static final int ExponentPart=157;
+    public static final int ARGS=111;
+    public static final int DOUBLE=39;
+    public static final int WhiteSpace=139;
+    public static final int VAR=28;
+    public static final int EXPORT=41;
+    public static final int VOID=29;
+    public static final int LABELLED=122;
+    public static final int SUPER=58;
+    public static final int GOTO=45;
+    public static final int EQ=76;
+    public static final int XORASS=108;
+    public static final int ADDASS=99;
+    public static final int ARRAY=112;
+    public static final int SHU=88;
+    public static final int RBRACK=68;
+    public static final int RBRACE=64;
+    public static final int PRIVATE=53;
+    public static final int STATIC=57;
+    public static final int INV=93;
+    public static final int SWITCH=23;
+    public static final int NULL=4;
+    public static final int ELSE=14;
+    public static final int NATIVE=51;
+    public static final int THROWS=60;
+    public static final int INT=48;
+    public static final int DELETE=12;
+    public static final int MUL=82;
+    public static final int IdentifierStartASCII=151;
+    public static final int TRY=26;
+    public static final int FF=135;
+    public static final int SHLASS=103;
+    public static final int OctalEscapeSequence=164;
+    public static final int USP=138;
+    public static final int RegularExpressionFirstChar=169;
+    public static final int ANDASS=106;
+    public static final int TYPEOF=27;
+    public static final int IdentifierNameASCIIStart=154;
+    public static final int QUE=96;
+    public static final int OR=90;
+    public static final int DEBUGGER=38;
+    public static final int GT=73;
+    public static final int PDEC=127;
+    public static final int CALL=116;
+    public static final int CharacterEscapeSequence=162;
+    public static final int CATCH=9;
+    public static final int FALSE=6;
+    public static final int EscapeSequence=167;
+    public static final int LAND=94;
+    public static final int MULASS=101;
+    public static final int THROW=25;
+    public static final int PINC=128;
+    public static final int OctalIntegerLiteral=160;
+    public static final int PROTECTED=54;
+    public static final int DEC=85;
+    public static final int CLASS=36;
+    public static final int LBRACK=67;
+    public static final int HexEscapeSequence=165;
+    public static final int ORASS=107;
+    public static final int SingleLineComment=147;
+    public static final int NAMEDVALUE=123;
+    public static final int LBRACE=63;
+    public static final int GTE=75;
+    public static final int FOR=16;
+    public static final int RegularExpressionLiteral=155;
+    public static final int SUB=81;
+    public static final int FLOAT=44;
+    public static final int ABSTRACT=32;
+    public static final int AND=89;
+    public static final int DecimalIntegerLiteral=158;
+    public static final int HexDigit=150;
+    public static final int LTE=74;
+    public static final int LPAREN=65;
+    public static final int IF=18;
+    public static final int SUBASS=100;
+    public static final int EXPR=118;
+    public static final int BOOLEAN=33;
+    public static final int SYNCHRONIZED=59;
+    public static final int IN=19;
+    public static final int IMPLEMENTS=46;
+    public static final int OBJECT=125;
+    public static final int CONTINUE=10;
+    public static final int COMMA=71;
+    public static final int FORITER=119;
+    public static final int TRANSIENT=61;
+    public static final int SHRASS=104;
+    public static final int MODASS=102;
+    public static final int PS=143;
+    public static final int DOT=69;
+    public static final int IdentifierPart=153;
+    public static final int MultiLineComment=146;
+    public static final int WITH=31;
+    public static final int ADD=80;
+    public static final int BYTE=34;
+    public static final int XOR=91;
+    public static final int ZeroToThree=163;
+    public static final int ITEM=121;
+    public static final int VOLATILE=62;
+    public static final int UnicodeEscapeSequence=166;
+    public static final int SHUASS=105;
+    public static final int DEFAULT=11;
+    public static final int NSAME=79;
+    public static final int TAB=133;
+    public static final int SHORT=56;
+    public static final int INSTANCEOF=20;
+    public static final int SQUOTE=132;
+    public static final int DecimalLiteral=159;
+    public static final int TRUE=5;
+    public static final int SAME=78;
+    public static final int StringLiteral=149;
+    public static final int COLON=97;
+    public static final int PAREXPR=126;
+    public static final int NEQ=77;
+    public static final int ENUM=40;
+    public static final int FINALLY=15;
+    public static final int HexIntegerLiteral=161;
+    public static final int NBSP=137;
+    public static final int SP=136;
+    public static final int BLOCK=113;
+    public static final int LineTerminator=144;
+    public static final int NEG=124;
+    public static final int ASSIGN=98;
+    public static final int INTERFACE=49;
+    public static final int DIV=109;
+    public static final int SEMIC=70;
+    public static final int CR=141;
+    public static final int LONG=50;
+    public static final int EXTENDS=42;
+    public static final int PUBLIC=55;
+    public static final int BSLASH=130;
+    public static final int LF=140;
+
+    // delegates
+    // delegators
+
+
+        public JavaScriptParser(TokenStream input) {
+            this(input, new RecognizerSharedState());
+        }
+        public JavaScriptParser(TokenStream input, RecognizerSharedState state) {
+            super(input, state);
+
+        }
+
+    protected TreeAdaptor adaptor = new CommonTreeAdaptor();
+
+    public void setTreeAdaptor(TreeAdaptor adaptor) {
+        this.adaptor = adaptor;
+    }
+    public TreeAdaptor getTreeAdaptor() {
+        return adaptor;
+    }
+
+    public String[] getTokenNames() { return JavaScriptParser.tokenNames; }
+    public String getGrammarFileName() { return "JavaScript.g"; }
+
+
+    private final boolean isLeftHandSideAssign(RuleReturnScope lhs, Object[] cached)
+    {
+       if (cached[0] != null)
+       {
+               return ((Boolean)cached[0]).booleanValue();
+       }
+
+       boolean result;
+       if (isLeftHandSideExpression(lhs))
+       {
+               switch (input.LA(1))
+               {
+                       case ASSIGN:
+                       case MULASS:
+                       case DIVASS:
+                       case MODASS:
+                       case ADDASS:
+                       case SUBASS:
+                       case SHLASS:
+                       case SHRASS:
+                       case SHUASS:
+                       case ANDASS:
+                       case XORASS:
+                       case ORASS:
+                               result = true;
+                               break;
+                       default:
+                               result = false;
+                               break;
+               }
+       }
+       else
+       {
+               result = false;
+       }
+
+       cached[0] = new Boolean(result);
+       return result;
+    }
+
+    private final static boolean isLeftHandSideExpression(RuleReturnScope lhs)
+    {
+       if (lhs.getTree() == null) // e.g. during backtracking
+       {
+               return true;
+       }
+       else
+       {
+               switch (((Tree)lhs.getTree()).getType())
+               {
+               // primaryExpression
+                       case THIS:
+                       case Identifier:
+                       case NULL:
+                       case TRUE:
+                       case FALSE:
+                       case DecimalLiteral:
+                       case OctalIntegerLiteral:
+                       case HexIntegerLiteral:
+                       case StringLiteral:
+                       case RegularExpressionLiteral:
+                       case ARRAY:
+                       case OBJECT:
+                       case PAREXPR:
+               // functionExpression
+                       case FUNCTION:
+               // newExpression
+                       case NEW:
+               // leftHandSideExpression
+                       case CALL:
+                       case BYFIELD:
+                       case BYINDEX:
+                               return true;
+
+                       default:
+                               return false;
+               }
+       }
+    }
+
+    private final boolean isLeftHandSideIn(RuleReturnScope lhs, Object[] cached)
+    {
+       if (cached[0] != null)
+       {
+               return ((Boolean)cached[0]).booleanValue();
+       }
+
+       boolean result = isLeftHandSideExpression(lhs) && (input.LA(1) == IN);
+       cached[0] = new Boolean(result);
+       return result;
+    }
+
+    private final void promoteEOL(ParserRuleReturnScope rule)
+    {
+       // Get current token and its type (the possibly offending token).
+       Token lt = input.LT(1);
+       int la = lt.getType();
+
+       // We only need to promote an EOL when the current token is offending (not a SEMIC, EOF, RBRACE, EOL or MultiLineComment).
+       // EOL and MultiLineComment are not offending as they're already promoted in a previous call to this method.
+       // Promoting an EOL means switching it from off channel to on channel.
+       // A MultiLineComment gets promoted when it contains an EOL.
+       if (!(la == SEMIC || la == EOF || la == RBRACE || la == EOL || la == MultiLineComment))
+       {
+               // Start on the possition before the current token and scan backwards off channel tokens until the previous on channel token.
+               for (int ix = lt.getTokenIndex() - 1; ix > 0; ix--)
+               {
+                       lt = input.get(ix);
+                       if (lt.getChannel() == Token.DEFAULT_CHANNEL)
+                       {
+                               // On channel token found: stop scanning.
+                               break;
+                       }
+                       else if (lt.getType() == EOL || (lt.getType() == MultiLineComment && lt.getText().matches("/.*\r\n|\r|\n")))
+                       {
+                               // We found our EOL: promote the token to on channel, position the input on it and reset the rule start.
+                               lt.setChannel(Token.DEFAULT_CHANNEL);
+                               input.seek(lt.getTokenIndex());
+                               if (rule != null)
+                               {
+                                       rule.start = lt;
+                               }
+                               break;
+                       }
+               }
+       }
+    }
+
+
+    public static class token_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "token"
+    // JavaScript.g:508:1: token : ( reservedWord | Identifier | punctuator | numericLiteral | StringLiteral );
+    public final JavaScriptParser.token_return token() throws RecognitionException {
+        JavaScriptParser.token_return retval = new JavaScriptParser.token_return();
+        retval.start = input.LT(1);
+        int token_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token Identifier2=null;
+        Token StringLiteral5=null;
+        JavaScriptParser.reservedWord_return reservedWord1 = null;
+
+        JavaScriptParser.punctuator_return punctuator3 = null;
+
+        JavaScriptParser.numericLiteral_return numericLiteral4 = null;
+
+
+        MyAstNode Identifier2_tree=null;
+        MyAstNode StringLiteral5_tree=null;
+
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 1) ) { return retval; }
+            // JavaScript.g:509:2: ( reservedWord | Identifier | punctuator | numericLiteral | StringLiteral )
+            int alt1=5;
+            switch ( input.LA(1) ) {
+            case NULL:
+            case TRUE:
+            case FALSE:
+            case BREAK:
+            case CASE:
+            case CATCH:
+            case CONTINUE:
+            case DEFAULT:
+            case DELETE:
+            case DO:
+            case ELSE:
+            case FINALLY:
+            case FOR:
+            case FUNCTION:
+            case IF:
+            case IN:
+            case INSTANCEOF:
+            case NEW:
+            case RETURN:
+            case SWITCH:
+            case THIS:
+            case THROW:
+            case TRY:
+            case TYPEOF:
+            case VAR:
+            case VOID:
+            case WHILE:
+            case WITH:
+            case ABSTRACT:
+            case BOOLEAN:
+            case BYTE:
+            case CHAR:
+            case CLASS:
+            case CONST:
+            case DEBUGGER:
+            case DOUBLE:
+            case ENUM:
+            case EXPORT:
+            case EXTENDS:
+            case FINAL:
+            case FLOAT:
+            case GOTO:
+            case IMPLEMENTS:
+            case IMPORT:
+            case INT:
+            case INTERFACE:
+            case LONG:
+            case NATIVE:
+            case PACKAGE:
+            case PRIVATE:
+            case PROTECTED:
+            case PUBLIC:
+            case SHORT:
+            case STATIC:
+            case SUPER:
+            case SYNCHRONIZED:
+            case THROWS:
+            case TRANSIENT:
+            case VOLATILE:
+                {
+                alt1=1;
+                }
+                break;
+            case Identifier:
+                {
+                alt1=2;
+                }
+                break;
+            case LBRACE:
+            case RBRACE:
+            case LPAREN:
+            case RPAREN:
+            case LBRACK:
+            case RBRACK:
+            case DOT:
+            case SEMIC:
+            case COMMA:
+            case LT:
+            case GT:
+            case LTE:
+            case GTE:
+            case EQ:
+            case NEQ:
+            case SAME:
+            case NSAME:
+            case ADD:
+            case SUB:
+            case MUL:
+            case MOD:
+            case INC:
+            case DEC:
+            case SHL:
+            case SHR:
+            case SHU:
+            case AND:
+            case OR:
+            case XOR:
+            case NOT:
+            case INV:
+            case LAND:
+            case LOR:
+            case QUE:
+            case COLON:
+            case ASSIGN:
+            case ADDASS:
+            case SUBASS:
+            case MULASS:
+            case MODASS:
+            case SHLASS:
+            case SHRASS:
+            case SHUASS:
+            case ANDASS:
+            case ORASS:
+            case XORASS:
+            case DIV:
+            case DIVASS:
+                {
+                alt1=3;
+                }
+                break;
+            case DecimalLiteral:
+            case OctalIntegerLiteral:
+            case HexIntegerLiteral:
+                {
+                alt1=4;
+                }
+                break;
+            case StringLiteral:
+                {
+                alt1=5;
+                }
+                break;
+            default:
+                NoViableAltException nvae =
+                    new NoViableAltException("", 1, 0, input);
+
+                throw nvae;
+            }
+
+            switch (alt1) {
+                case 1 :
+                    // JavaScript.g:509:4: reservedWord
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_reservedWord_in_token1756);
+                    reservedWord1=reservedWord();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, reservedWord1.getTree());
+
+                    }
+                    break;
+                case 2 :
+                    // JavaScript.g:510:4: Identifier
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    Identifier2=(Token)match(input,Identifier,FOLLOW_Identifier_in_token1761);
+                    Identifier2_tree = (MyAstNode)adaptor.create(Identifier2);
+                    adaptor.addChild(root_0, Identifier2_tree);
+
+
+                    }
+                    break;
+                case 3 :
+                    // JavaScript.g:511:4: punctuator
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_punctuator_in_token1766);
+                    punctuator3=punctuator();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, punctuator3.getTree());
+
+                    }
+                    break;
+                case 4 :
+                    // JavaScript.g:512:4: numericLiteral
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_numericLiteral_in_token1771);
+                    numericLiteral4=numericLiteral();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, numericLiteral4.getTree());
+
+                    }
+                    break;
+                case 5 :
+                    // JavaScript.g:513:4: StringLiteral
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    StringLiteral5=(Token)match(input,StringLiteral,FOLLOW_StringLiteral_in_token1776);
+                    StringLiteral5_tree = (MyAstNode)adaptor.create(StringLiteral5);
+                    adaptor.addChild(root_0, StringLiteral5_tree);
+
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "token"
+
+    public static class reservedWord_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "reservedWord"
+    // JavaScript.g:518:1: reservedWord : ( keyword | futureReservedWord | NULL | booleanLiteral );
+    public final JavaScriptParser.reservedWord_return reservedWord() throws RecognitionException {
+        JavaScriptParser.reservedWord_return retval = new JavaScriptParser.reservedWord_return();
+        retval.start = input.LT(1);
+        int reservedWord_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token NULL8=null;
+        JavaScriptParser.keyword_return keyword6 = null;
+
+        JavaScriptParser.futureReservedWord_return futureReservedWord7 = null;
+
+        JavaScriptParser.booleanLiteral_return booleanLiteral9 = null;
+
+
+        MyAstNode NULL8_tree=null;
+
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 2) ) { return retval; }
+            // JavaScript.g:519:2: ( keyword | futureReservedWord | NULL | booleanLiteral )
+            int alt2=4;
+            switch ( input.LA(1) ) {
+            case BREAK:
+            case CASE:
+            case CATCH:
+            case CONTINUE:
+            case DEFAULT:
+            case DELETE:
+            case DO:
+            case ELSE:
+            case FINALLY:
+            case FOR:
+            case FUNCTION:
+            case IF:
+            case IN:
+            case INSTANCEOF:
+            case NEW:
+            case RETURN:
+            case SWITCH:
+            case THIS:
+            case THROW:
+            case TRY:
+            case TYPEOF:
+            case VAR:
+            case VOID:
+            case WHILE:
+            case WITH:
+                {
+                alt2=1;
+                }
+                break;
+            case ABSTRACT:
+            case BOOLEAN:
+            case BYTE:
+            case CHAR:
+            case CLASS:
+            case CONST:
+            case DEBUGGER:
+            case DOUBLE:
+            case ENUM:
+            case EXPORT:
+            case EXTENDS:
+            case FINAL:
+            case FLOAT:
+            case GOTO:
+            case IMPLEMENTS:
+            case IMPORT:
+            case INT:
+            case INTERFACE:
+            case LONG:
+            case NATIVE:
+            case PACKAGE:
+            case PRIVATE:
+            case PROTECTED:
+            case PUBLIC:
+            case SHORT:
+            case STATIC:
+            case SUPER:
+            case SYNCHRONIZED:
+            case THROWS:
+            case TRANSIENT:
+            case VOLATILE:
+                {
+                alt2=2;
+                }
+                break;
+            case NULL:
+                {
+                alt2=3;
+                }
+                break;
+            case TRUE:
+            case FALSE:
+                {
+                alt2=4;
+                }
+                break;
+            default:
+                NoViableAltException nvae =
+                    new NoViableAltException("", 2, 0, input);
+
+                throw nvae;
+            }
+
+            switch (alt2) {
+                case 1 :
+                    // JavaScript.g:519:4: keyword
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_keyword_in_reservedWord1789);
+                    keyword6=keyword();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, keyword6.getTree());
+
+                    }
+                    break;
+                case 2 :
+                    // JavaScript.g:520:4: futureReservedWord
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_futureReservedWord_in_reservedWord1794);
+                    futureReservedWord7=futureReservedWord();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, futureReservedWord7.getTree());
+
+                    }
+                    break;
+                case 3 :
+                    // JavaScript.g:521:4: NULL
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    NULL8=(Token)match(input,NULL,FOLLOW_NULL_in_reservedWord1799);
+                    NULL8_tree = (MyAstNode)adaptor.create(NULL8);
+                    adaptor.addChild(root_0, NULL8_tree);
+
+
+                    }
+                    break;
+                case 4 :
+                    // JavaScript.g:522:4: booleanLiteral
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_booleanLiteral_in_reservedWord1804);
+                    booleanLiteral9=booleanLiteral();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, booleanLiteral9.getTree());
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "reservedWord"
+
+    public static class keyword_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "keyword"
+    // JavaScript.g:529:1: keyword : ( BREAK | CASE | CATCH | CONTINUE | DEFAULT | DELETE | DO | ELSE | FINALLY | FOR | FUNCTION | IF | IN | INSTANCEOF | NEW | RETURN | SWITCH | THIS | THROW | TRY | TYPEOF | VAR | VOID | WHILE | WITH );
+    public final JavaScriptParser.keyword_return keyword() throws RecognitionException {
+        JavaScriptParser.keyword_return retval = new JavaScriptParser.keyword_return();
+        retval.start = input.LT(1);
+        int keyword_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token set10=null;
+
+        MyAstNode set10_tree=null;
+
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 3) ) { return retval; }
+            // JavaScript.g:530:2: ( BREAK | CASE | CATCH | CONTINUE | DEFAULT | DELETE | DO | ELSE | FINALLY | FOR | FUNCTION | IF | IN | INSTANCEOF | NEW | RETURN | SWITCH | THIS | THROW | TRY | TYPEOF | VAR | VOID | WHILE | WITH )
+            // JavaScript.g:
+            {
+            root_0 = (MyAstNode)adaptor.nil();
+
+            set10=(Token)input.LT(1);
+            if ( (input.LA(1)>=BREAK && input.LA(1)<=WITH) ) {
+                input.consume();
+                adaptor.addChild(root_0, (MyAstNode)adaptor.create(set10));
+                state.errorRecovery=false;
+            }
+            else {
+                MismatchedSetException mse = new MismatchedSetException(null,input);
+                throw mse;
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "keyword"
+
+    public static class futureReservedWord_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "futureReservedWord"
+    // JavaScript.g:561:1: futureReservedWord : ( ABSTRACT | BOOLEAN | BYTE | CHAR | CLASS | CONST | DEBUGGER | DOUBLE | ENUM | EXPORT | EXTENDS | FINAL | FLOAT | GOTO | IMPLEMENTS | IMPORT | INT | INTERFACE | LONG | NATIVE | PACKAGE | PRIVATE | PROTECTED | PUBLIC | SHORT | STATIC | SUPER | SYNCHRONIZED | THROWS | TRANSIENT | VOLATILE );
+    public final JavaScriptParser.futureReservedWord_return futureReservedWord() throws RecognitionException {
+        JavaScriptParser.futureReservedWord_return retval = new JavaScriptParser.futureReservedWord_return();
+        retval.start = input.LT(1);
+        int futureReservedWord_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token set11=null;
+
+        MyAstNode set11_tree=null;
+
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 4) ) { return retval; }
+            // JavaScript.g:562:2: ( ABSTRACT | BOOLEAN | BYTE | CHAR | CLASS | CONST | DEBUGGER | DOUBLE | ENUM | EXPORT | EXTENDS | FINAL | FLOAT | GOTO | IMPLEMENTS | IMPORT | INT | INTERFACE | LONG | NATIVE | PACKAGE | PRIVATE | PROTECTED | PUBLIC | SHORT | STATIC | SUPER | SYNCHRONIZED | THROWS | TRANSIENT | VOLATILE )
+            // JavaScript.g:
+            {
+            root_0 = (MyAstNode)adaptor.nil();
+
+            set11=(Token)input.LT(1);
+            if ( (input.LA(1)>=ABSTRACT && input.LA(1)<=VOLATILE) ) {
+                input.consume();
+                adaptor.addChild(root_0, (MyAstNode)adaptor.create(set11));
+                state.errorRecovery=false;
+            }
+            else {
+                MismatchedSetException mse = new MismatchedSetException(null,input);
+                throw mse;
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "futureReservedWord"
+
+    public static class punctuator_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "punctuator"
+    // JavaScript.g:639:1: punctuator : ( LBRACE | RBRACE | LPAREN | RPAREN | LBRACK | RBRACK | DOT | SEMIC | COMMA | LT | GT | LTE | GTE | EQ | NEQ | SAME | NSAME | ADD | SUB | MUL | MOD | INC | DEC | SHL | SHR | SHU | AND | OR | XOR | NOT | INV | LAND | LOR | QUE | COLON | ASSIGN | ADDASS | SUBASS | MULASS | MODASS | SHLASS | SHRASS | SHUASS | ANDASS | ORASS | XORASS | DIV | DIVASS );
+    public final JavaScriptParser.punctuator_return punctuator() throws RecognitionException {
+        JavaScriptParser.punctuator_return retval = new JavaScriptParser.punctuator_return();
+        retval.start = input.LT(1);
+        int punctuator_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token set12=null;
+
+        MyAstNode set12_tree=null;
+
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 5) ) { return retval; }
+            // JavaScript.g:640:2: ( LBRACE | RBRACE | LPAREN | RPAREN | LBRACK | RBRACK | DOT | SEMIC | COMMA | LT | GT | LTE | GTE | EQ | NEQ | SAME | NSAME | ADD | SUB | MUL | MOD | INC | DEC | SHL | SHR | SHU | AND | OR | XOR | NOT | INV | LAND | LOR | QUE | COLON | ASSIGN | ADDASS | SUBASS | MULASS | MODASS | SHLASS | SHRASS | SHUASS | ANDASS | ORASS | XORASS | DIV | DIVASS )
+            // JavaScript.g:
+            {
+            root_0 = (MyAstNode)adaptor.nil();
+
+            set12=(Token)input.LT(1);
+            if ( (input.LA(1)>=LBRACE && input.LA(1)<=DIVASS) ) {
+                input.consume();
+                adaptor.addChild(root_0, (MyAstNode)adaptor.create(set12));
+                state.errorRecovery=false;
+            }
+            else {
+                MismatchedSetException mse = new MismatchedSetException(null,input);
+                throw mse;
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "punctuator"
+
+    public static class literal_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "literal"
+    // JavaScript.g:694:1: literal : ( NULL | booleanLiteral | numericLiteral | StringLiteral | RegularExpressionLiteral );
+    public final JavaScriptParser.literal_return literal() throws RecognitionException {
+        JavaScriptParser.literal_return retval = new JavaScriptParser.literal_return();
+        retval.start = input.LT(1);
+        int literal_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token NULL13=null;
+        Token StringLiteral16=null;
+        Token RegularExpressionLiteral17=null;
+        JavaScriptParser.booleanLiteral_return booleanLiteral14 = null;
+
+        JavaScriptParser.numericLiteral_return numericLiteral15 = null;
+
+
+        MyAstNode NULL13_tree=null;
+        MyAstNode StringLiteral16_tree=null;
+        MyAstNode RegularExpressionLiteral17_tree=null;
+
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 6) ) { return retval; }
+            // JavaScript.g:695:2: ( NULL | booleanLiteral | numericLiteral | StringLiteral | RegularExpressionLiteral )
+            int alt3=5;
+            switch ( input.LA(1) ) {
+            case NULL:
+                {
+                alt3=1;
+                }
+                break;
+            case TRUE:
+            case FALSE:
+                {
+                alt3=2;
+                }
+                break;
+            case DecimalLiteral:
+            case OctalIntegerLiteral:
+            case HexIntegerLiteral:
+                {
+                alt3=3;
+                }
+                break;
+            case StringLiteral:
+                {
+                alt3=4;
+                }
+                break;
+            case RegularExpressionLiteral:
+                {
+                alt3=5;
+                }
+                break;
+            default:
+                NoViableAltException nvae =
+                    new NoViableAltException("", 3, 0, input);
+
+                throw nvae;
+            }
+
+            switch (alt3) {
+                case 1 :
+                    // JavaScript.g:695:4: NULL
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    NULL13=(Token)match(input,NULL,FOLLOW_NULL_in_literal2485);
+                    NULL13_tree = (MyAstNode)adaptor.create(NULL13);
+                    adaptor.addChild(root_0, NULL13_tree);
+
+
+                    }
+                    break;
+                case 2 :
+                    // JavaScript.g:696:4: booleanLiteral
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_booleanLiteral_in_literal2490);
+                    booleanLiteral14=booleanLiteral();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, booleanLiteral14.getTree());
+
+                    }
+                    break;
+                case 3 :
+                    // JavaScript.g:697:4: numericLiteral
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_numericLiteral_in_literal2495);
+                    numericLiteral15=numericLiteral();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, numericLiteral15.getTree());
+
+                    }
+                    break;
+                case 4 :
+                    // JavaScript.g:698:4: StringLiteral
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    StringLiteral16=(Token)match(input,StringLiteral,FOLLOW_StringLiteral_in_literal2500);
+                    StringLiteral16_tree = (MyAstNode)adaptor.create(StringLiteral16);
+                    adaptor.addChild(root_0, StringLiteral16_tree);
+
+
+                    }
+                    break;
+                case 5 :
+                    // JavaScript.g:699:4: RegularExpressionLiteral
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    RegularExpressionLiteral17=(Token)match(input,RegularExpressionLiteral,FOLLOW_RegularExpressionLiteral_in_literal2505);
+                    RegularExpressionLiteral17_tree = (MyAstNode)adaptor.create(RegularExpressionLiteral17);
+                    adaptor.addChild(root_0, RegularExpressionLiteral17_tree);
+
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "literal"
+
+    public static class booleanLiteral_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "booleanLiteral"
+    // JavaScript.g:702:1: booleanLiteral : ( TRUE | FALSE );
+    public final JavaScriptParser.booleanLiteral_return booleanLiteral() throws RecognitionException {
+        JavaScriptParser.booleanLiteral_return retval = new JavaScriptParser.booleanLiteral_return();
+        retval.start = input.LT(1);
+        int booleanLiteral_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token set18=null;
+
+        MyAstNode set18_tree=null;
+
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 7) ) { return retval; }
+            // JavaScript.g:703:2: ( TRUE | FALSE )
+            // JavaScript.g:
+            {
+            root_0 = (MyAstNode)adaptor.nil();
+
+            set18=(Token)input.LT(1);
+            if ( (input.LA(1)>=TRUE && input.LA(1)<=FALSE) ) {
+                input.consume();
+                adaptor.addChild(root_0, (MyAstNode)adaptor.create(set18));
+                state.errorRecovery=false;
+            }
+            else {
+                MismatchedSetException mse = new MismatchedSetException(null,input);
+                throw mse;
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "booleanLiteral"
+
+    public static class numericLiteral_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "numericLiteral"
+    // JavaScript.g:749:1: numericLiteral : ( DecimalLiteral | OctalIntegerLiteral | HexIntegerLiteral );
+    public final JavaScriptParser.numericLiteral_return numericLiteral() throws RecognitionException {
+        JavaScriptParser.numericLiteral_return retval = new JavaScriptParser.numericLiteral_return();
+        retval.start = input.LT(1);
+        int numericLiteral_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token set19=null;
+
+        MyAstNode set19_tree=null;
+
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 8) ) { return retval; }
+            // JavaScript.g:750:2: ( DecimalLiteral | OctalIntegerLiteral | HexIntegerLiteral )
+            // JavaScript.g:
+            {
+            root_0 = (MyAstNode)adaptor.nil();
+
+            set19=(Token)input.LT(1);
+            if ( (input.LA(1)>=DecimalLiteral && input.LA(1)<=HexIntegerLiteral) ) {
+                input.consume();
+                adaptor.addChild(root_0, (MyAstNode)adaptor.create(set19));
+                state.errorRecovery=false;
+            }
+            else {
+                MismatchedSetException mse = new MismatchedSetException(null,input);
+                throw mse;
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "numericLiteral"
+
+    public static class primaryExpression_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "primaryExpression"
+    // JavaScript.g:837:1: primaryExpression : ( THIS | Identifier | literal | arrayLiteral | objectLiteral | lpar= LPAREN expression RPAREN -> ^( PAREXPR[$lpar, \"PAREXPR\"] expression ) );
+    public final JavaScriptParser.primaryExpression_return primaryExpression() throws RecognitionException {
+        JavaScriptParser.primaryExpression_return retval = new JavaScriptParser.primaryExpression_return();
+        retval.start = input.LT(1);
+        int primaryExpression_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token lpar=null;
+        Token THIS20=null;
+        Token Identifier21=null;
+        Token RPAREN26=null;
+        JavaScriptParser.literal_return literal22 = null;
+
+        JavaScriptParser.arrayLiteral_return arrayLiteral23 = null;
+
+        JavaScriptParser.objectLiteral_return objectLiteral24 = null;
+
+        JavaScriptParser.expression_return expression25 = null;
+
+
+        MyAstNode lpar_tree=null;
+        MyAstNode THIS20_tree=null;
+        MyAstNode Identifier21_tree=null;
+        MyAstNode RPAREN26_tree=null;
+        RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN");
+        RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN");
+        RewriteRuleSubtreeStream stream_expression=new RewriteRuleSubtreeStream(adaptor,"rule expression");
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 9) ) { return retval; }
+            // JavaScript.g:838:2: ( THIS | Identifier | literal | arrayLiteral | objectLiteral | lpar= LPAREN expression RPAREN -> ^( PAREXPR[$lpar, \"PAREXPR\"] expression ) )
+            int alt4=6;
+            switch ( input.LA(1) ) {
+            case THIS:
+                {
+                alt4=1;
+                }
+                break;
+            case Identifier:
+                {
+                alt4=2;
+                }
+                break;
+            case NULL:
+            case TRUE:
+            case FALSE:
+            case StringLiteral:
+            case RegularExpressionLiteral:
+            case DecimalLiteral:
+            case OctalIntegerLiteral:
+            case HexIntegerLiteral:
+                {
+                alt4=3;
+                }
+                break;
+            case LBRACK:
+                {
+                alt4=4;
+                }
+                break;
+            case LBRACE:
+                {
+                alt4=5;
+                }
+                break;
+            case LPAREN:
+                {
+                alt4=6;
+                }
+                break;
+            default:
+                NoViableAltException nvae =
+                    new NoViableAltException("", 4, 0, input);
+
+                throw nvae;
+            }
+
+            switch (alt4) {
+                case 1 :
+                    // JavaScript.g:838:4: THIS
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    THIS20=(Token)match(input,THIS,FOLLOW_THIS_in_primaryExpression3118);
+                    THIS20_tree = (MyAstNode)adaptor.create(THIS20);
+                    adaptor.addChild(root_0, THIS20_tree);
+
+
+                    }
+                    break;
+                case 2 :
+                    // JavaScript.g:839:4: Identifier
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    Identifier21=(Token)match(input,Identifier,FOLLOW_Identifier_in_primaryExpression3123);
+                    Identifier21_tree = (MyAstNode)adaptor.create(Identifier21);
+                    adaptor.addChild(root_0, Identifier21_tree);
+
+
+                    }
+                    break;
+                case 3 :
+                    // JavaScript.g:840:4: literal
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_literal_in_primaryExpression3128);
+                    literal22=literal();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, literal22.getTree());
+
+                    }
+                    break;
+                case 4 :
+                    // JavaScript.g:841:4: arrayLiteral
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_arrayLiteral_in_primaryExpression3133);
+                    arrayLiteral23=arrayLiteral();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, arrayLiteral23.getTree());
+
+                    }
+                    break;
+                case 5 :
+                    // JavaScript.g:842:4: objectLiteral
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_objectLiteral_in_primaryExpression3138);
+                    objectLiteral24=objectLiteral();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, objectLiteral24.getTree());
+
+                    }
+                    break;
+                case 6 :
+                    // JavaScript.g:843:4: lpar= LPAREN expression RPAREN
+                    {
+                    lpar=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_primaryExpression3145);
+                    stream_LPAREN.add(lpar);
+
+                    pushFollow(FOLLOW_expression_in_primaryExpression3147);
+                    expression25=expression();
+
+                    state._fsp--;
+
+                    stream_expression.add(expression25.getTree());
+                    RPAREN26=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_primaryExpression3149);
+                    stream_RPAREN.add(RPAREN26);
+
+
+
+                    // AST REWRITE
+                    // elements: expression
+                    // token labels:
+                    // rule labels: retval
+                    // token list labels:
+                    // rule list labels:
+                    retval.tree = root_0;
+                    RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"token retval",retval!=null?retval.tree:null);
+
+                    root_0 = (MyAstNode)adaptor.nil();
+                    // 843:34: -> ^( PAREXPR[$lpar, \"PAREXPR\"] expression )
+                    {
+                        // JavaScript.g:843:37: ^( PAREXPR[$lpar, \"PAREXPR\"] expression )
+                        {
+                        MyAstNode root_1 = (MyAstNode)adaptor.nil();
+                        root_1 = (MyAstNode)adaptor.becomeRoot((MyAstNode)adaptor.create(PAREXPR, lpar, "PAREXPR"), root_1);
+
+                        adaptor.addChild(root_1, stream_expression.nextTree());
+
+                        adaptor.addChild(root_0, root_1);
+                        }
+
+                    }
+
+                    retval.tree = root_0;
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "primaryExpression"
+
+    public static class arrayLiteral_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "arrayLiteral"
+    // JavaScript.g:846:1: arrayLiteral : lb= LBRACK ( arrayItem ( COMMA arrayItem )* )? RBRACK -> ^( ARRAY[$lb, \"ARRAY\"] ( arrayItem )* ) ;
+    public final JavaScriptParser.arrayLiteral_return arrayLiteral() throws RecognitionException {
+        JavaScriptParser.arrayLiteral_return retval = new JavaScriptParser.arrayLiteral_return();
+        retval.start = input.LT(1);
+        int arrayLiteral_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token lb=null;
+        Token COMMA28=null;
+        Token RBRACK30=null;
+        JavaScriptParser.arrayItem_return arrayItem27 = null;
+
+        JavaScriptParser.arrayItem_return arrayItem29 = null;
+
+
+        MyAstNode lb_tree=null;
+        MyAstNode COMMA28_tree=null;
+        MyAstNode RBRACK30_tree=null;
+        RewriteRuleTokenStream stream_RBRACK=new RewriteRuleTokenStream(adaptor,"token RBRACK");
+        RewriteRuleTokenStream stream_LBRACK=new RewriteRuleTokenStream(adaptor,"token LBRACK");
+        RewriteRuleTokenStream stream_COMMA=new RewriteRuleTokenStream(adaptor,"token COMMA");
+        RewriteRuleSubtreeStream stream_arrayItem=new RewriteRuleSubtreeStream(adaptor,"rule arrayItem");
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 10) ) { return retval; }
+            // JavaScript.g:847:2: (lb= LBRACK ( arrayItem ( COMMA arrayItem )* )? RBRACK -> ^( ARRAY[$lb, \"ARRAY\"] ( arrayItem )* ) )
+            // JavaScript.g:847:4: lb= LBRACK ( arrayItem ( COMMA arrayItem )* )? RBRACK
+            {
+            lb=(Token)match(input,LBRACK,FOLLOW_LBRACK_in_arrayLiteral3173);
+            stream_LBRACK.add(lb);
+
+            // JavaScript.g:847:14: ( arrayItem ( COMMA arrayItem )* )?
+            int alt6=2;
+            int LA6_0 = input.LA(1);
+
+            if ( ((LA6_0>=NULL && LA6_0<=FALSE)||LA6_0==DELETE||LA6_0==FUNCTION||LA6_0==NEW||LA6_0==THIS||LA6_0==TYPEOF||LA6_0==VOID||LA6_0==LBRACE||LA6_0==LPAREN||LA6_0==LBRACK||LA6_0==COMMA||(LA6_0>=ADD && LA6_0<=SUB)||(LA6_0>=INC && LA6_0<=DEC)||(LA6_0>=NOT && LA6_0<=INV)||(LA6_0>=Identifier && LA6_0<=StringLiteral)||LA6_0==RegularExpressionLiteral||(LA6_0>=DecimalLiteral && LA6_0<=HexIntegerLiteral)) ) {
+                alt6=1;
+            }
+            else if ( (LA6_0==RBRACK) ) {
+                int LA6_2 = input.LA(2);
+
+                if ( (( input.LA(1) == COMMA )) ) {
+                    alt6=1;
+                }
+            }
+            switch (alt6) {
+                case 1 :
+                    // JavaScript.g:847:16: arrayItem ( COMMA arrayItem )*
+                    {
+                    pushFollow(FOLLOW_arrayItem_in_arrayLiteral3177);
+                    arrayItem27=arrayItem();
+
+                    state._fsp--;
+
+                    stream_arrayItem.add(arrayItem27.getTree());
+                    // JavaScript.g:847:26: ( COMMA arrayItem )*
+                    loop5:
+                    do {
+                        int alt5=2;
+                        int LA5_0 = input.LA(1);
+
+                        if ( (LA5_0==COMMA) ) {
+                            alt5=1;
+                        }
+
+
+                        switch (alt5) {
+                       case 1 :
+                           // JavaScript.g:847:28: COMMA arrayItem
+                           {
+                           COMMA28=(Token)match(input,COMMA,FOLLOW_COMMA_in_arrayLiteral3181);
+                           stream_COMMA.add(COMMA28);
+
+                           pushFollow(FOLLOW_arrayItem_in_arrayLiteral3183);
+                           arrayItem29=arrayItem();
+
+                           state._fsp--;
+
+                           stream_arrayItem.add(arrayItem29.getTree());
+
+                           }
+                           break;
+
+                       default :
+                           break loop5;
+                        }
+                    } while (true);
+
+
+                    }
+                    break;
+
+            }
+
+            RBRACK30=(Token)match(input,RBRACK,FOLLOW_RBRACK_in_arrayLiteral3191);
+            stream_RBRACK.add(RBRACK30);
+
+
+
+            // AST REWRITE
+            // elements: arrayItem
+            // token labels:
+            // rule labels: retval
+            // token list labels:
+            // rule list labels:
+            retval.tree = root_0;
+            RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"token retval",retval!=null?retval.tree:null);
+
+            root_0 = (MyAstNode)adaptor.nil();
+            // 848:2: -> ^( ARRAY[$lb, \"ARRAY\"] ( arrayItem )* )
+            {
+                // JavaScript.g:848:5: ^( ARRAY[$lb, \"ARRAY\"] ( arrayItem )* )
+                {
+                MyAstNode root_1 = (MyAstNode)adaptor.nil();
+                root_1 = (MyAstNode)adaptor.becomeRoot((MyAstNode)adaptor.create(ARRAY, lb, "ARRAY"), root_1);
+
+                // JavaScript.g:848:28: ( arrayItem )*
+                while ( stream_arrayItem.hasNext() ) {
+                    adaptor.addChild(root_1, stream_arrayItem.nextTree());
+
+                }
+                stream_arrayItem.reset();
+
+                adaptor.addChild(root_0, root_1);
+                }
+
+            }
+
+            retval.tree = root_0;
+            }
+
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "arrayLiteral"
+
+    public static class arrayItem_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "arrayItem"
+    // JavaScript.g:851:1: arrayItem : (expr= assignmentExpression | {...}?) -> ^( ITEM ( $expr)? ) ;
+    public final JavaScriptParser.arrayItem_return arrayItem() throws RecognitionException {
+        JavaScriptParser.arrayItem_return retval = new JavaScriptParser.arrayItem_return();
+        retval.start = input.LT(1);
+        int arrayItem_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        JavaScriptParser.assignmentExpression_return expr = null;
+
+
+        RewriteRuleSubtreeStream stream_assignmentExpression=new RewriteRuleSubtreeStream(adaptor,"rule assignmentExpression");
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 11) ) { return retval; }
+            // JavaScript.g:852:2: ( (expr= assignmentExpression | {...}?) -> ^( ITEM ( $expr)? ) )
+            // JavaScript.g:852:4: (expr= assignmentExpression | {...}?)
+            {
+            // JavaScript.g:852:4: (expr= assignmentExpression | {...}?)
+            int alt7=2;
+            int LA7_0 = input.LA(1);
+
+            if ( ((LA7_0>=NULL && LA7_0<=FALSE)||LA7_0==DELETE||LA7_0==FUNCTION||LA7_0==NEW||LA7_0==THIS||LA7_0==TYPEOF||LA7_0==VOID||LA7_0==LBRACE||LA7_0==LPAREN||LA7_0==LBRACK||(LA7_0>=ADD && LA7_0<=SUB)||(LA7_0>=INC && LA7_0<=DEC)||(LA7_0>=NOT && LA7_0<=INV)||(LA7_0>=Identifier && LA7_0<=StringLiteral)||LA7_0==RegularExpressionLiteral||(LA7_0>=DecimalLiteral && LA7_0<=HexIntegerLiteral)) ) {
+                alt7=1;
+            }
+            else if ( (LA7_0==RBRACK||LA7_0==COMMA) ) {
+                alt7=2;
+            }
+            else {
+                NoViableAltException nvae =
+                    new NoViableAltException("", 7, 0, input);
+
+                throw nvae;
+            }
+            switch (alt7) {
+                case 1 :
+                    // JavaScript.g:852:6: expr= assignmentExpression
+                    {
+                    pushFollow(FOLLOW_assignmentExpression_in_arrayItem3219);
+                    expr=assignmentExpression();
+
+                    state._fsp--;
+
+                    stream_assignmentExpression.add(expr.getTree());
+
+                    }
+                    break;
+                case 2 :
+                    // JavaScript.g:852:34: {...}?
+                    {
+                    if ( !(( input.LA(1) == COMMA )) ) {
+                        throw new FailedPredicateException(input, "arrayItem", " input.LA(1) == COMMA ");
+                    }
+
+                    }
+                    break;
+
+            }
+
+
+
+            // AST REWRITE
+            // elements: expr
+            // token labels:
+            // rule labels: retval, expr
+            // token list labels:
+            // rule list labels:
+            retval.tree = root_0;
+            RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"token retval",retval!=null?retval.tree:null);
+            RewriteRuleSubtreeStream stream_expr=new RewriteRuleSubtreeStream(adaptor,"token expr",expr!=null?expr.tree:null);
+
+            root_0 = (MyAstNode)adaptor.nil();
+            // 853:2: -> ^( ITEM ( $expr)? )
+            {
+                // JavaScript.g:853:5: ^( ITEM ( $expr)? )
+                {
+                MyAstNode root_1 = (MyAstNode)adaptor.nil();
+                root_1 = (MyAstNode)adaptor.becomeRoot((MyAstNode)adaptor.create(ITEM, "ITEM"), root_1);
+
+                // JavaScript.g:853:13: ( $expr)?
+                if ( stream_expr.hasNext() ) {
+                    adaptor.addChild(root_1, stream_expr.nextTree());
+
+                }
+                stream_expr.reset();
+
+                adaptor.addChild(root_0, root_1);
+                }
+
+            }
+
+            retval.tree = root_0;
+            }
+
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "arrayItem"
+
+    public static class objectLiteral_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "objectLiteral"
+    // JavaScript.g:856:1: objectLiteral : lb= LBRACE ( nameValuePair ( COMMA nameValuePair )* )? RBRACE -> ^( OBJECT[$lb, \"OBJECT\"] ( nameValuePair )* ) ;
+    public final JavaScriptParser.objectLiteral_return objectLiteral() throws RecognitionException {
+        JavaScriptParser.objectLiteral_return retval = new JavaScriptParser.objectLiteral_return();
+        retval.start = input.LT(1);
+        int objectLiteral_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token lb=null;
+        Token COMMA32=null;
+        Token RBRACE34=null;
+        JavaScriptParser.nameValuePair_return nameValuePair31 = null;
+
+        JavaScriptParser.nameValuePair_return nameValuePair33 = null;
+
+
+        MyAstNode lb_tree=null;
+        MyAstNode COMMA32_tree=null;
+        MyAstNode RBRACE34_tree=null;
+        RewriteRuleTokenStream stream_RBRACE=new RewriteRuleTokenStream(adaptor,"token RBRACE");
+        RewriteRuleTokenStream stream_COMMA=new RewriteRuleTokenStream(adaptor,"token COMMA");
+        RewriteRuleTokenStream stream_LBRACE=new RewriteRuleTokenStream(adaptor,"token LBRACE");
+        RewriteRuleSubtreeStream stream_nameValuePair=new RewriteRuleSubtreeStream(adaptor,"rule nameValuePair");
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 12) ) { return retval; }
+            // JavaScript.g:857:2: (lb= LBRACE ( nameValuePair ( COMMA nameValuePair )* )? RBRACE -> ^( OBJECT[$lb, \"OBJECT\"] ( nameValuePair )* ) )
+            // JavaScript.g:857:4: lb= LBRACE ( nameValuePair ( COMMA nameValuePair )* )? RBRACE
+            {
+            lb=(Token)match(input,LBRACE,FOLLOW_LBRACE_in_objectLiteral3251);
+            stream_LBRACE.add(lb);
+
+            // JavaScript.g:857:14: ( nameValuePair ( COMMA nameValuePair )* )?
+            int alt9=2;
+            int LA9_0 = input.LA(1);
+
+            if ( ((LA9_0>=Identifier && LA9_0<=StringLiteral)||(LA9_0>=DecimalLiteral && LA9_0<=HexIntegerLiteral)) ) {
+                alt9=1;
+            }
+            switch (alt9) {
+                case 1 :
+                    // JavaScript.g:857:16: nameValuePair ( COMMA nameValuePair )*
+                    {
+                    pushFollow(FOLLOW_nameValuePair_in_objectLiteral3255);
+                    nameValuePair31=nameValuePair();
+
+                    state._fsp--;
+
+                    stream_nameValuePair.add(nameValuePair31.getTree());
+                    // JavaScript.g:857:30: ( COMMA nameValuePair )*
+                    loop8:
+                    do {
+                        int alt8=2;
+                        int LA8_0 = input.LA(1);
+
+                        if ( (LA8_0==COMMA) ) {
+                            alt8=1;
+                        }
+
+
+                        switch (alt8) {
+                       case 1 :
+                           // JavaScript.g:857:32: COMMA nameValuePair
+                           {
+                           COMMA32=(Token)match(input,COMMA,FOLLOW_COMMA_in_objectLiteral3259);
+                           stream_COMMA.add(COMMA32);
+
+                           pushFollow(FOLLOW_nameValuePair_in_objectLiteral3261);
+                           nameValuePair33=nameValuePair();
+
+                           state._fsp--;
+
+                           stream_nameValuePair.add(nameValuePair33.getTree());
+
+                           }
+                           break;
+
+                       default :
+                           break loop8;
+                        }
+                    } while (true);
+
+
+                    }
+                    break;
+
+            }
+
+            RBRACE34=(Token)match(input,RBRACE,FOLLOW_RBRACE_in_objectLiteral3269);
+            stream_RBRACE.add(RBRACE34);
+
+
+
+            // AST REWRITE
+            // elements: nameValuePair
+            // token labels:
+            // rule labels: retval
+            // token list labels:
+            // rule list labels:
+            retval.tree = root_0;
+            RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"token retval",retval!=null?retval.tree:null);
+
+            root_0 = (MyAstNode)adaptor.nil();
+            // 858:2: -> ^( OBJECT[$lb, \"OBJECT\"] ( nameValuePair )* )
+            {
+                // JavaScript.g:858:5: ^( OBJECT[$lb, \"OBJECT\"] ( nameValuePair )* )
+                {
+                MyAstNode root_1 = (MyAstNode)adaptor.nil();
+                root_1 = (MyAstNode)adaptor.becomeRoot((MyAstNode)adaptor.create(OBJECT, lb, "OBJECT"), root_1);
+
+                // JavaScript.g:858:30: ( nameValuePair )*
+                while ( stream_nameValuePair.hasNext() ) {
+                    adaptor.addChild(root_1, stream_nameValuePair.nextTree());
+
+                }
+                stream_nameValuePair.reset();
+
+                adaptor.addChild(root_0, root_1);
+                }
+
+            }
+
+            retval.tree = root_0;
+            }
+
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "objectLiteral"
+
+    public static class nameValuePair_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "nameValuePair"
+    // JavaScript.g:861:1: nameValuePair : propertyName COLON assignmentExpression -> ^( NAMEDVALUE propertyName assignmentExpression ) ;
+    public final JavaScriptParser.nameValuePair_return nameValuePair() throws RecognitionException {
+        JavaScriptParser.nameValuePair_return retval = new JavaScriptParser.nameValuePair_return();
+        retval.start = input.LT(1);
+        int nameValuePair_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token COLON36=null;
+        JavaScriptParser.propertyName_return propertyName35 = null;
+
+        JavaScriptParser.assignmentExpression_return assignmentExpression37 = null;
+
+
+        MyAstNode COLON36_tree=null;
+        RewriteRuleTokenStream stream_COLON=new RewriteRuleTokenStream(adaptor,"token COLON");
+        RewriteRuleSubtreeStream stream_propertyName=new RewriteRuleSubtreeStream(adaptor,"rule propertyName");
+        RewriteRuleSubtreeStream stream_assignmentExpression=new RewriteRuleSubtreeStream(adaptor,"rule assignmentExpression");
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 13) ) { return retval; }
+            // JavaScript.g:862:2: ( propertyName COLON assignmentExpression -> ^( NAMEDVALUE propertyName assignmentExpression ) )
+            // JavaScript.g:862:4: propertyName COLON assignmentExpression
+            {
+            pushFollow(FOLLOW_propertyName_in_nameValuePair3294);
+            propertyName35=propertyName();
+
+            state._fsp--;
+
+            stream_propertyName.add(propertyName35.getTree());
+            COLON36=(Token)match(input,COLON,FOLLOW_COLON_in_nameValuePair3296);
+            stream_COLON.add(COLON36);
+
+            pushFollow(FOLLOW_assignmentExpression_in_nameValuePair3298);
+            assignmentExpression37=assignmentExpression();
+
+            state._fsp--;
+
+            stream_assignmentExpression.add(assignmentExpression37.getTree());
+
+
+            // AST REWRITE
+            // elements: assignmentExpression, propertyName
+            // token labels:
+            // rule labels: retval
+            // token list labels:
+            // rule list labels:
+            retval.tree = root_0;
+            RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"token retval",retval!=null?retval.tree:null);
+
+            root_0 = (MyAstNode)adaptor.nil();
+            // 863:2: -> ^( NAMEDVALUE propertyName assignmentExpression )
+            {
+                // JavaScript.g:863:5: ^( NAMEDVALUE propertyName assignmentExpression )
+                {
+                MyAstNode root_1 = (MyAstNode)adaptor.nil();
+                root_1 = (MyAstNode)adaptor.becomeRoot((MyAstNode)adaptor.create(NAMEDVALUE, "NAMEDVALUE"), root_1);
+
+                adaptor.addChild(root_1, stream_propertyName.nextTree());
+                adaptor.addChild(root_1, stream_assignmentExpression.nextTree());
+
+                adaptor.addChild(root_0, root_1);
+                }
+
+            }
+
+            retval.tree = root_0;
+            }
+
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "nameValuePair"
+
+    public static class propertyName_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "propertyName"
+    // JavaScript.g:866:1: propertyName : ( Identifier | StringLiteral | numericLiteral );
+    public final JavaScriptParser.propertyName_return propertyName() throws RecognitionException {
+        JavaScriptParser.propertyName_return retval = new JavaScriptParser.propertyName_return();
+        retval.start = input.LT(1);
+        int propertyName_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token Identifier38=null;
+        Token StringLiteral39=null;
+        JavaScriptParser.numericLiteral_return numericLiteral40 = null;
+
+
+        MyAstNode Identifier38_tree=null;
+        MyAstNode StringLiteral39_tree=null;
+
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 14) ) { return retval; }
+            // JavaScript.g:867:2: ( Identifier | StringLiteral | numericLiteral )
+            int alt10=3;
+            switch ( input.LA(1) ) {
+            case Identifier:
+                {
+                alt10=1;
+                }
+                break;
+            case StringLiteral:
+                {
+                alt10=2;
+                }
+                break;
+            case DecimalLiteral:
+            case OctalIntegerLiteral:
+            case HexIntegerLiteral:
+                {
+                alt10=3;
+                }
+                break;
+            default:
+                NoViableAltException nvae =
+                    new NoViableAltException("", 10, 0, input);
+
+                throw nvae;
+            }
+
+            switch (alt10) {
+                case 1 :
+                    // JavaScript.g:867:4: Identifier
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    Identifier38=(Token)match(input,Identifier,FOLLOW_Identifier_in_propertyName3322);
+                    Identifier38_tree = (MyAstNode)adaptor.create(Identifier38);
+                    adaptor.addChild(root_0, Identifier38_tree);
+
+
+                    }
+                    break;
+                case 2 :
+                    // JavaScript.g:868:4: StringLiteral
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    StringLiteral39=(Token)match(input,StringLiteral,FOLLOW_StringLiteral_in_propertyName3327);
+                    StringLiteral39_tree = (MyAstNode)adaptor.create(StringLiteral39);
+                    adaptor.addChild(root_0, StringLiteral39_tree);
+
+
+                    }
+                    break;
+                case 3 :
+                    // JavaScript.g:869:4: numericLiteral
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_numericLiteral_in_propertyName3332);
+                    numericLiteral40=numericLiteral();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, numericLiteral40.getTree());
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "propertyName"
+
+    public static class memberExpression_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "memberExpression"
+    // JavaScript.g:881:1: memberExpression : ( primaryExpression | functionExpression | newExpression );
+    public final JavaScriptParser.memberExpression_return memberExpression() throws RecognitionException {
+        JavaScriptParser.memberExpression_return retval = new JavaScriptParser.memberExpression_return();
+        retval.start = input.LT(1);
+        int memberExpression_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        JavaScriptParser.primaryExpression_return primaryExpression41 = null;
+
+        JavaScriptParser.functionExpression_return functionExpression42 = null;
+
+        JavaScriptParser.newExpression_return newExpression43 = null;
+
+
+
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 15) ) { return retval; }
+            // JavaScript.g:882:2: ( primaryExpression | functionExpression | newExpression )
+            int alt11=3;
+            switch ( input.LA(1) ) {
+            case NULL:
+            case TRUE:
+            case FALSE:
+            case THIS:
+            case LBRACE:
+            case LPAREN:
+            case LBRACK:
+            case Identifier:
+            case StringLiteral:
+            case RegularExpressionLiteral:
+            case DecimalLiteral:
+            case OctalIntegerLiteral:
+            case HexIntegerLiteral:
+                {
+                alt11=1;
+                }
+                break;
+            case FUNCTION:
+                {
+                alt11=2;
+                }
+                break;
+            case NEW:
+                {
+                alt11=3;
+                }
+                break;
+            default:
+                NoViableAltException nvae =
+                    new NoViableAltException("", 11, 0, input);
+
+                throw nvae;
+            }
+
+            switch (alt11) {
+                case 1 :
+                    // JavaScript.g:882:4: primaryExpression
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_primaryExpression_in_memberExpression3350);
+                    primaryExpression41=primaryExpression();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, primaryExpression41.getTree());
+
+                    }
+                    break;
+                case 2 :
+                    // JavaScript.g:883:4: functionExpression
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_functionExpression_in_memberExpression3355);
+                    functionExpression42=functionExpression();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, functionExpression42.getTree());
+
+                    }
+                    break;
+                case 3 :
+                    // JavaScript.g:884:4: newExpression
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    pushFollow(FOLLOW_newExpression_in_memberExpression3360);
+                    newExpression43=newExpression();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, newExpression43.getTree());
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "memberExpression"
+
+    public static class newExpression_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "newExpression"
+    // JavaScript.g:887:1: newExpression : ( NEW primaryExpression | NEW functionExpression );
+    public final JavaScriptParser.newExpression_return newExpression() throws RecognitionException {
+        JavaScriptParser.newExpression_return retval = new JavaScriptParser.newExpression_return();
+        retval.start = input.LT(1);
+        int newExpression_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token NEW44=null;
+        Token NEW46=null;
+        JavaScriptParser.primaryExpression_return primaryExpression45 = null;
+
+        JavaScriptParser.functionExpression_return functionExpression47 = null;
+
+
+        MyAstNode NEW44_tree=null;
+        MyAstNode NEW46_tree=null;
+
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 16) ) { return retval; }
+            // JavaScript.g:888:2: ( NEW primaryExpression | NEW functionExpression )
+            int alt12=2;
+            int LA12_0 = input.LA(1);
+
+            if ( (LA12_0==NEW) ) {
+                int LA12_1 = input.LA(2);
+
+                if ( ((LA12_1>=NULL && LA12_1<=FALSE)||LA12_1==THIS||LA12_1==LBRACE||LA12_1==LPAREN||LA12_1==LBRACK||(LA12_1>=Identifier && LA12_1<=StringLiteral)||LA12_1==RegularExpressionLiteral||(LA12_1>=DecimalLiteral && LA12_1<=HexIntegerLiteral)) ) {
+                    alt12=1;
+                }
+                else if ( (LA12_1==FUNCTION) ) {
+                    alt12=2;
+                }
+                else {
+                    NoViableAltException nvae =
+                        new NoViableAltException("", 12, 1, input);
+
+                    throw nvae;
+                }
+            }
+            else {
+                NoViableAltException nvae =
+                    new NoViableAltException("", 12, 0, input);
+
+                throw nvae;
+            }
+            switch (alt12) {
+                case 1 :
+                    // JavaScript.g:888:4: NEW primaryExpression
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    NEW44=(Token)match(input,NEW,FOLLOW_NEW_in_newExpression3371);
+                    NEW44_tree = (MyAstNode)adaptor.create(NEW44);
+                    root_0 = (MyAstNode)adaptor.becomeRoot(NEW44_tree, root_0);
+
+                    pushFollow(FOLLOW_primaryExpression_in_newExpression3374);
+                    primaryExpression45=primaryExpression();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, primaryExpression45.getTree());
+
+                    }
+                    break;
+                case 2 :
+                    // JavaScript.g:889:7: NEW functionExpression
+                    {
+                    root_0 = (MyAstNode)adaptor.nil();
+
+                    NEW46=(Token)match(input,NEW,FOLLOW_NEW_in_newExpression3382);
+                    NEW46_tree = (MyAstNode)adaptor.create(NEW46);
+                    root_0 = (MyAstNode)adaptor.becomeRoot(NEW46_tree, root_0);
+
+                    pushFollow(FOLLOW_functionExpression_in_newExpression3385);
+                    functionExpression47=functionExpression();
+
+                    state._fsp--;
+
+                    adaptor.addChild(root_0, functionExpression47.getTree());
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "newExpression"
+
+    public static class arguments_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "arguments"
+    // JavaScript.g:893:1: arguments : LPAREN ( assignmentExpression ( COMMA assignmentExpression )* )? RPAREN -> ^( ARGS ( assignmentExpression )* ) ;
+    public final JavaScriptParser.arguments_return arguments() throws RecognitionException {
+        JavaScriptParser.arguments_return retval = new JavaScriptParser.arguments_return();
+        retval.start = input.LT(1);
+        int arguments_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token LPAREN48=null;
+        Token COMMA50=null;
+        Token RPAREN52=null;
+        JavaScriptParser.assignmentExpression_return assignmentExpression49 = null;
+
+        JavaScriptParser.assignmentExpression_return assignmentExpression51 = null;
+
+
+        MyAstNode LPAREN48_tree=null;
+        MyAstNode COMMA50_tree=null;
+        MyAstNode RPAREN52_tree=null;
+        RewriteRuleTokenStream stream_RPAREN=new RewriteRuleTokenStream(adaptor,"token RPAREN");
+        RewriteRuleTokenStream stream_COMMA=new RewriteRuleTokenStream(adaptor,"token COMMA");
+        RewriteRuleTokenStream stream_LPAREN=new RewriteRuleTokenStream(adaptor,"token LPAREN");
+        RewriteRuleSubtreeStream stream_assignmentExpression=new RewriteRuleSubtreeStream(adaptor,"rule assignmentExpression");
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 17) ) { return retval; }
+            // JavaScript.g:894:2: ( LPAREN ( assignmentExpression ( COMMA assignmentExpression )* )? RPAREN -> ^( ARGS ( assignmentExpression )* ) )
+            // JavaScript.g:894:4: LPAREN ( assignmentExpression ( COMMA assignmentExpression )* )? RPAREN
+            {
+            LPAREN48=(Token)match(input,LPAREN,FOLLOW_LPAREN_in_arguments3398);
+            stream_LPAREN.add(LPAREN48);
+
+            // JavaScript.g:894:11: ( assignmentExpression ( COMMA assignmentExpression )* )?
+            int alt14=2;
+            int LA14_0 = input.LA(1);
+
+            if ( ((LA14_0>=NULL && LA14_0<=FALSE)||LA14_0==DELETE||LA14_0==FUNCTION||LA14_0==NEW||LA14_0==THIS||LA14_0==TYPEOF||LA14_0==VOID||LA14_0==LBRACE||LA14_0==LPAREN||LA14_0==LBRACK||(LA14_0>=ADD && LA14_0<=SUB)||(LA14_0>=INC && LA14_0<=DEC)||(LA14_0>=NOT && LA14_0<=INV)||(LA14_0>=Identifier && LA14_0<=StringLiteral)||LA14_0==RegularExpressionLiteral||(LA14_0>=DecimalLiteral && LA14_0<=HexIntegerLiteral)) ) {
+                alt14=1;
+            }
+            switch (alt14) {
+                case 1 :
+                    // JavaScript.g:894:13: assignmentExpression ( COMMA assignmentExpression )*
+                    {
+                    pushFollow(FOLLOW_assignmentExpression_in_arguments3402);
+                    assignmentExpression49=assignmentExpression();
+
+                    state._fsp--;
+
+                    stream_assignmentExpression.add(assignmentExpression49.getTree());
+                    // JavaScript.g:894:34: ( COMMA assignmentExpression )*
+                    loop13:
+                    do {
+                        int alt13=2;
+                        int LA13_0 = input.LA(1);
+
+                        if ( (LA13_0==COMMA) ) {
+                            alt13=1;
+                        }
+
+
+                        switch (alt13) {
+                       case 1 :
+                           // JavaScript.g:894:36: COMMA assignmentExpression
+                           {
+                           COMMA50=(Token)match(input,COMMA,FOLLOW_COMMA_in_arguments3406);
+                           stream_COMMA.add(COMMA50);
+
+                           pushFollow(FOLLOW_assignmentExpression_in_arguments3408);
+                           assignmentExpression51=assignmentExpression();
+
+                           state._fsp--;
+
+                           stream_assignmentExpression.add(assignmentExpression51.getTree());
+
+                           }
+                           break;
+
+                       default :
+                           break loop13;
+                        }
+                    } while (true);
+
+
+                    }
+                    break;
+
+            }
+
+            RPAREN52=(Token)match(input,RPAREN,FOLLOW_RPAREN_in_arguments3416);
+            stream_RPAREN.add(RPAREN52);
+
+
+
+            // AST REWRITE
+            // elements: assignmentExpression
+            // token labels:
+            // rule labels: retval
+            // token list labels:
+            // rule list labels:
+            retval.tree = root_0;
+            RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"token retval",retval!=null?retval.tree:null);
+
+            root_0 = (MyAstNode)adaptor.nil();
+            // 895:2: -> ^( ARGS ( assignmentExpression )* )
+            {
+                // JavaScript.g:895:5: ^( ARGS ( assignmentExpression )* )
+                {
+                MyAstNode root_1 = (MyAstNode)adaptor.nil();
+                root_1 = (MyAstNode)adaptor.becomeRoot((MyAstNode)adaptor.create(ARGS, "ARGS"), root_1);
+
+                // JavaScript.g:895:13: ( assignmentExpression )*
+                while ( stream_assignmentExpression.hasNext() ) {
+                    adaptor.addChild(root_1, stream_assignmentExpression.nextTree());
+
+                }
+                stream_assignmentExpression.reset();
+
+                adaptor.addChild(root_0, root_1);
+                }
+
+            }
+
+            retval.tree = root_0;
+            }
+
+            retval.stop = input.LT(-1);
+
+            retval.tree = (MyAstNode)adaptor.rulePostProcessing(root_0);
+            adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+       retval.tree = (MyAstNode)adaptor.errorNode(input, retval.start, input.LT(-1), re);
+
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end "arguments"
+
+    public static class leftHandSideExpression_return extends ParserRuleReturnScope {
+        MyAstNode tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start "leftHandSideExpression"
+    // JavaScript.g:898:1: leftHandSideExpression : ( memberExpression -> memberExpression ) ( arguments -> ^( CALL $leftHandSideExpression arguments ) | LBRACK expression RBRACK -> ^( BYINDEX $leftHandSideExpression expression ) | DOT Identifier -> ^( BYFIELD $leftHandSideExpression Identifier ) )* ;
+    public final JavaScriptParser.leftHandSideExpression_return leftHandSideExpression() throws RecognitionException {
+        JavaScriptParser.leftHandSideExpression_return retval = new JavaScriptParser.leftHandSideExpression_return();
+        retval.start = input.LT(1);
+        int leftHandSideExpression_StartIndex = input.index();
+        MyAstNode root_0 = null;
+
+        Token LBRACK55=null;
+        Token RBRACK57=null;
+        Token DOT58=null;
+        Token Identifier59=null;
+        JavaScriptParser.memberExpression_return memberExpression53 = null;
+
+        JavaScriptParser.arguments_return arguments54 = null;
+
+        JavaScriptParser.expression_return expression56 = null;
+
+
+        MyAstNode LBRACK55_tree=null;
+        MyAstNode RBRACK57_tree=null;
+        MyAstNode DOT58_tree=null;
+        MyAstNode Identifier59_tree=null;
+        RewriteRuleTokenStream stream_RBRACK=new RewriteRuleTokenStream(adaptor,"token RBRACK");
+        RewriteRuleTokenStream stream_LBRACK=new RewriteRuleTokenStream(adaptor,"token LBRACK");
+        RewriteRuleTokenStream stream_DOT=new RewriteRuleTokenStream(adaptor,"token DOT");
+        RewriteRuleTokenStream stream_Identifier=new RewriteRuleTokenStream(adaptor,"token Identifier");
+        RewriteRuleSubtreeStream stream_memberExpression=new RewriteRuleSubtreeStream(adaptor,"rule memberExpression");
+        RewriteRuleSubtreeStream stream_expression=new RewriteRuleSubtreeStream(adaptor,"rule expression");
+        RewriteRuleSubtreeStream stream_arguments=new RewriteRuleSubtreeStream(adaptor,"rule arguments");
+        try {
+            if ( state.backtracking>0 && alreadyParsedRule(input, 18) ) { return retval; }
+            // JavaScript.g:899:2: ( ( memberExpression -> memberExpression ) ( arguments -> ^( CALL $leftHandSideExpression arguments ) | LBRACK expression RBRACK -> ^( BYINDEX $leftHandSideExpression expression ) | DOT Identifier -> ^( BYFIELD $leftHandSideExpression Identifier ) )* )
+            // JavaScript.g:900:2: ( memberExpression -> memberExpression ) ( arguments -> ^( CALL $leftHandSideExpression arguments ) | LBRACK expression RBRACK -> ^( BYINDEX $leftHandSideExpression expression ) | DOT Identifier -> ^( BYFIELD $leftHandSideExpression Identifier ) )*
+            {
+            // JavaScript.g:900:2: ( memberExpression -> memberExpression )
+            // JavaScript.g:901:3: memberExpression
+            {
+            pushFollow(FOLLOW_memberExpression_in_leftHandSideExpression3445);
+            memberExpression53=memberExpression();
+
+            state._fsp--;
+
+            stream_memberExpression.add(memberExpression53.getTree());
+
+
+            // AST REWRITE
+            // elements: memberExpression
+            // token labels:
+            // rule labels: retval
+            // token list labels:
+            // rule list labels:
+            retval.tree = root_0;
+            RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"token retval",retval!=null?retval.tree:null);
+
+            root_0 = (MyAstNode)adaptor.nil();
+            // 901:22: -> memberExpression
+            {
+                adaptor.addChild(root_0, stream_memberExpression.nextTree());
+
+            }
+
+            retval.tree = root_0;
+            }
+
+            // JavaScript.g:903:2: ( arguments -> ^( CALL $leftHandSideExpression arguments ) | LBRACK expression RBRACK -> ^( BYINDEX $leftHandSideExpression expression ) | DOT Identifier -> ^( BYFIELD $leftHandSideExpression Identifier ) )*
+            loop15:
+            do {
+                int alt15=4;
+                switch ( input.LA(1) ) {
+                case LPAREN:
+                    {
+                    alt15=1;
+                    }
+                    break;
+                case LBRACK:
+                    {
+                    alt15=2;
+                    }
+                    break;
+                case DOT:
+                    {
+                    alt15=3;
+                    }
+                    break;
+
+                }
+
+                switch (alt15) {
+               case 1 :
+                   // JavaScript.g:904:3: arguments
+                   {
+                   pushFollow(FOLLOW_arguments_in_leftHandSideExpression3461);
+                   arguments54=arguments();
+
+                   state._fsp--;
+
+                   stream_arguments.add(arguments54.getTree());
+
+
+                   // AST REWRITE
+                   // elements: arguments, leftHandSideExpression
+                   // token labels:
+                   // rule labels: retval
+                   // token list labels:
+                   // rule list labels:
+                   retval.tree = root_0;
+                   RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"token retval",retval!=null?retval.tree:null);
+
+                   root_0 = (MyAstNode)adaptor.nil();
+                   // 904:15: -> ^( CALL $leftHandSideExpression arguments )
+                   {
+                       // JavaScript.g:904:18: ^( CALL $leftHandSideExpression arguments )
+                       {
+                       MyAstNode root_1 = (MyAstNode)adaptor.nil();
+                       root_1 = (MyAstNode)adaptor.becomeRoot((MyAstNode)adaptor.create(CALL, "CALL"), root_1);
+
+                       adaptor.addChild(root_1, stream_retval.nextTree());
+                       adaptor.addChild(root_1, stream_arguments.nextTree());
+
+                       adaptor.addChild(root_0, root_1);
+                       }
+
+                   }
+
+                   retval.tree = root_0;
+                   }
+                   break;
+               case 2 :
+                   // JavaScript.g:905:5: LBRACK expression RBRACK
+                   {
+                   LBRACK55=(Token)match(input,LBRACK,FOLLOW_LBRACK_in_leftHandSideExpression3482);
+                   stream_LBRACK.add(LBRACK55);
+
+                   pushFollow(FOLLOW_expression_in_leftHandSideExpression3484);
+                   expression56=expression();
+
+                   state._fsp--;
+
+                   stream_expression.add(expression56.getTree());
+                   RBRACK57=(Token)match(input,RBRACK,FOLLOW_RBRACK_in_leftHandSideExpression3486);
+                   stream_RBRACK.add(RBRACK57);
+
+
+
+                   // AST REWRITE
+                   // elements: expression, leftHandSideExpression
+                   // token labels:
+                   // rule labels: retval
+                   // token list labels:
+                   // rule list labels:
+                   retval.tree = root_0;
+                   RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"token retval",retval!=null?retval.tree:null);
+
+                   root_0 = (MyAstNode)adaptor.nil();
+                   // 905:30: -> ^( BYINDEX $leftHandSideExpression expression )
+                   {
+                       // JavaScript.g:905:33: ^( BYINDEX $leftHandSideExpression expression )
+                       {
+                       MyAstNode root_1 = (MyAstNode)adaptor.nil();
+                       root_1 = (MyAstNode)adaptor.becomeRoot((MyAstNode)adaptor.create(BYINDEX, "BYINDEX"), root_1);
+
+                       adaptor.addChild(root_1, stream_retval.nextTree());
+                       adaptor.addChild(root_1, stream_expression.nextTree());
+
+                       adaptor.addChild(root_0, root_1);
+                       }
+
+                   }
+
+                   retval.tree = root_0;
+                   }
+                   break;
+               case 3 :
+                   // JavaScript.g:906:5: DOT Identifier
+                   {
+                   DOT58=(Token)match(input,DOT,FOLLOW_DOT_in_leftHandSideExpression3505);
+                   stream_DOT.add(DOT58);
+
+                   Identifier59=(Token)match(input,Identifier,FOLLOW_Identifier_in_leftHandSideExpression3507);
+                   stream_Identifier.add(Identifier59);
+
+
+
+                   // AST REWRITE
+                   // elements: Identifier, leftHandSideExpression
+                   // token labels:
+                   // rule labels: retval
+                   // token list labels:
+                   // rule list labels:
+                   retval.tree = root_0;
+                   RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"token retval",retval!=null?retval.tree:null);
+
+                   root_0 = (MyAstNode)adaptor.nil();
+                   // 906:21: -> ^( BYFIELD $leftHandSideExpression Identifier )
+                   {
+                       // JavaScript.g:906:24: ^( BYFIELD $leftHandSideExpression Identifier )
+                       {
+                       MyAstNode root_1 = (MyAstNode)adaptor.nil();
+                       root_1 = (MyAstNode)adaptor.becomeRoot((MyAstNode)adaptor.create(BYFIELD, "BYFIELD"), root_1);
+
+                       adaptor.addChild(root_1, stream_retval.nextTree());
+                       adaptor.addChild(root_1, stream_Identifier.nextNode());
+
+                       adaptor.addChild(root_0, root_1);
+                       }
+
+                   }
+
+                   retval.tree = root_0;
+                   }
+                   break;
+

log.txt

Olle Jonsson

unread,
Mar 5, 2009, 3:24:08 AM3/5/09
to clonedigg...@googlegroups.com
Excited: CloneDigger for JavaScript sounds wonderful. Great job, all.

On that note: Is there a CloneDigger + ANTLR 3 hacker's guide? (Being
a complete beginner, I do have the ANTLR book by Parr. Perhaps that's
all I need.) It could be a good blog article with which to fish for
contributors.

Olle, Sweden

PS: Hm, "clonedigger" matched nothing on GitHub, perhaps you, Peter,
want to add a canonical repo there?
http://github.com/search?q=clonedigger

Haoyu Bai

unread,
Mar 5, 2009, 3:26:06 AM3/5/09
to clonedigg...@googlegroups.com

Hi,

Yes there's some problem with this kind of compressed javascript. I
think this is because ANTLR failed on this super long line?

-- Haoyu Bai

Peter Bulychev

unread,
Mar 5, 2009, 3:42:03 AM3/5/09
to clonedigg...@googlegroups.com
Yes, maybe the problem is in the length of that line.
But I guess that the problem can also be in the grammar.
I also tried to parse this project (http://script.aculo.us/dist/scriptaculous-js-1.8.2.zip) but failed again.
Can you try this and also send me the link to the sources you were able to parse?

I have to go now, will answer you and Olle later.

2009/3/5 Haoyu Bai <divi...@gmail.com>

Haoyu Bai

unread,
Mar 5, 2009, 7:13:12 AM3/5/09
to clonedigg...@googlegroups.com

There's bug in the grammar ( or it is JavaScript not obey the ECMA
standard, I'm not sure ), and there's also something wrong when ANTLR
dealing with long line. I updated the grammar file and TreeProducer to
fix the two things. See the attached files.


-- Haoyu Bai

JavaScript.g
TreeProducer.java

Peter Bulychev

unread,
Mar 6, 2009, 2:08:18 PM3/6/09
to clonedigg...@googlegroups.com
Great!

Thank you, Haoyu!

I placed your code to the repository (also added license.txt file).

There are still several things to do:
  • adjust default threshold values. Different coding style is used for different languages. CD should be tested on several js projects with different threshold values, and the optimal set shall be found
  • test the grammar. it's possible to forget to mark some nodes in the AST as statement nodes, and thus to miss some clones. For instance we can run DuDe tool (http://loose.upt.ro/iplasma/dude.html) and Clone Digger on the same large js project and to check that the clones which were found by DuDe are also found by Clone DIgger
I plan to do that but not right now. If you are interested in js support, you can also do it by yourself.

Peter Bulychev

unread,
Mar 6, 2009, 2:53:06 PM3/6/09
to clonedigg...@googlegroups.com
Hello, Olle.

Haoyu, if you are reading this text, can you check it?

On that note: Is there a CloneDigger + ANTLR 3 hacker's guide? (Being
a complete beginner, I do have the ANTLR book by Parr. Perhaps that's
all I need.) It could be a good blog article with which to fish for
contributors.
Well, I think that it is not so complicated, so I can write a quick instruction here.

You will need an ANTLR grammar with Java target. It's better to have a grammar which produces abstract syntax trees (if your grammar has a substring "-> ^", then it is able to do that). But if your grammar is only able to produce parse trees, it will be still possible to use it with Clone Digger, but you will have performance problems. The problem is that parse trees contain a lot of unnecessary nodes, which are not presented in the abstract syntax trees. I'll provide the instruction for the case of abstract syntax trees. If you need to work with parse trees, take a look on how it is done for the Lua target.

Add "ASTLabelType=MyAstNode;" to the options of the grammar
You'll need to mark some rules in your grammar as statement rules. You can do that by putting the following code to the appropriate rules:
@after {
        if(retval.tree != null)
            retval.tree.is_statement = true;
    }
Don't forget that class and function definitions are also (compound) statements.

Than create a directory [your_language]_antlr, copy your grammar there as well as TreeProducer.java, MyAstNode.java and build_jar.sh (take them from java_antlr directory). Change "java" to [your language] in these files. Also copy java_antlr.py to [your_language]_antlr.py and modify it. Grep all the Python source files int the clonedigger directory for the string "javascript" and add the analogous commands for your language near found source lines.

Try to adjust distance and size thresholds. Search several large projects for clones and find the appropriate ones.

Than run the text-based tool DuDe  (http://loose.upt.ro/iplasma/dude.html) and Clone Digger on the same project and check that Clone Digger doesn't miss real clones (it can happen if you forgot to mark some statement rules).

That's all :)


PS: Hm, "clonedigger" matched nothing on GitHub, perhaps you, Peter,
want to add a canonical repo there?
http://github.com/search?q=clonedigger
What are the benefits of having a canonical repo on GitHub?

Haoyu Bai

unread,
Mar 8, 2009, 10:33:12 AM3/8/09
to clonedigg...@googlegroups.com
2009/3/7 Peter Bulychev <peter.b...@gmail.com>:

Hi,

I don't know there's whether a hacking guide.

Also, I think ANTLR is not the only way - I have added Erlang support
without ATNLR. Instead of ANTLR, I reused the epp_dodger Erlang
module. It is a Erlang source code parser and AST generator written in
Erlang. The AST is serialized and parsed at the Python side, and then
feed to Clone Digger.

It is almost as easy as the ANTLR way. Since almost all advanced
languages have its own source code parser as part of its standard
library, I think go along this way we can easily extend Clone Digger
to many many languages. Cheers! :-)

-- Haoyu Bai

Haoyu Bai

unread,
Mar 11, 2009, 12:16:10 PM3/11/09
to clonedigg...@googlegroups.com
On Sun, Mar 8, 2009 at 10:33 PM, Haoyu Bai <divi...@gmail.com> wrote:
>
> Hi,
>
> I don't know there's whether a hacking guide.
>
> Also, I think ANTLR is not the only way - I have added Erlang support
> without ATNLR. Instead of ANTLR, I reused the epp_dodger Erlang
> module. It is a Erlang source code parser and AST generator written in
> Erlang. The AST is serialized and parsed at the Python side, and then
> feed to Clone Digger.
>
> It is almost as easy as the ANTLR way. Since almost all advanced
> languages have its own source code parser as part of its standard
> library, I think go along this way we can easily extend Clone Digger
> to many many languages. Cheers! :-)
>
> -- Haoyu Bai
>

Hi,

By using the similar method I added Haskell support to Clone Digger.
The Haskell module Language.Haskell.Exts [1] is used for parsing. I
have successfully run CD with several Haskell project yet, but due to
the limit of the parsing module, some source code is failed to parse.
However, it has the functionality now! :-)

[1] http://hackage.haskell.org/cgi-bin/hackage-scripts/package/haskell-src-exts

-- Haoyu Bai

Peter Bulychev

unread,
Mar 17, 2009, 11:33:15 AM3/17/09
to clonedigg...@googlegroups.com
My congratulations!

Again, if you want, we can put your code to the repository.

Is your code cross-platform (etc can be run on both Linux and Windows)?
I guess it needs Haskell interpreter to run.
Is there something else which is required in order to run your code?

I'll be thankful if you attach some clones found in Haskell programs.

2009/3/11 Haoyu Bai <divi...@gmail.com>

Haoyu Bai

unread,
Mar 17, 2009, 2:46:58 PM3/17/09
to clonedigg...@googlegroups.com
On Tue, Mar 17, 2009 at 11:33 PM, Peter Bulychev
<peter.b...@gmail.com> wrote:
> My congratulations!
>
> Again, if you want, we can put your code to the repository.
>
> Is your code cross-platform (etc can be run on both Linux and Windows)?
> I guess it needs Haskell interpreter to run.
> Is there something else which is required in order to run your code?
>
> I'll be thankful if you attach some clones found in Haskell programs.
>

Hi,

Ok I'l supply a proper patch to you later. It needs Haskell compiler
GHC to compile and run, which is available on both Linux and Windows.
And a haskell library haskell-src-exts
(http://hackage.haskell.org/cgi-bin/hackage-scripts/package/haskell-src-exts)
should be explicitly installed for this. If you feel that's
inconvinient, I can try to put the library into Clone Digger's source
code tree.

However I think we need a proper build system such as SCons to deal
with more and more buildings. Any ideas?

Thanks!

-- Haoyu Bai

Reply all
Reply to author
Forward
0 new messages