You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2014/07/22 15:36:13 UTC

[47/51] [partial] - Migrated the directory structure to a more Maven style structure. - Started migrating the Parser from Antlr2+3 and JFlex to Antlr4.

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/59f6373b/compiler/src/main/antlr4/org/apache/flex/compiler/internal/parsing/as/AS.g4
----------------------------------------------------------------------
diff --git a/compiler/src/main/antlr4/org/apache/flex/compiler/internal/parsing/as/AS.g4 b/compiler/src/main/antlr4/org/apache/flex/compiler/internal/parsing/as/AS.g4
new file mode 100644
index 0000000..1967aff
--- /dev/null
+++ b/compiler/src/main/antlr4/org/apache/flex/compiler/internal/parsing/as/AS.g4
@@ -0,0 +1,3207 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+/**
+ * This is a grammar for ActionScript.
+ */
+grammar AS;
+
+options
+{
+    language = Java;
+}
+
+tokens
+{
+	// These hidden tokens are matched by the raw tokenizer but are not sent to the parser.
+	HIDDEN_TOKEN_COMMENT,
+	HIDDEN_TOKEN_SINGLE_LINE_COMMENT,
+	HIDDEN_TOKEN_STAR_ASSIGNMENT,
+	HIDDEN_TOKEN_BUILTIN_NS,
+	HIDDEN_TOKEN_MULTI_LINE_COMMENT,
+
+	// These two tokens are used by code model's ASDoc tokenizer.
+	TOKEN_ASDOC_TAG,
+	TOKEN_ASDOC_TEXT,
+
+	// These tokens are transformed from reserved words by StreamingASTokenizer.
+	TOKEN_RESERVED_WORD_EACH,
+	TOKEN_RESERVED_WORD_CONFIG,
+	TOKEN_KEYWORD_INCLUDE,
+	TOKEN_RESERVED_WORD_GOTO
+}
+
+@header
+{
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+
+/*
+ * This file is generated from ASTreeAssembler.g
+ * DO NOT MAKE EDITS DIRECTLY TO THIS FILE.  THEY WILL BE LOST WHEN THE FILE IS GENERATED AGAIN!!!
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.flex.compiler.tree.as.*;
+import org.apache.flex.compiler.workspaces.IWorkspace;
+import org.apache.flex.compiler.parsing.IASToken;
+import org.apache.flex.compiler.parsing.IASToken.ASTokenKind;
+import org.apache.flex.compiler.tree.as.IContainerNode.ContainerType;
+import org.apache.flex.compiler.tree.as.ILiteralNode.LiteralType;
+import org.apache.flex.compiler.internal.tree.as.*;
+import org.apache.flex.compiler.internal.tree.as.metadata.*;
+import org.apache.flex.compiler.asdoc.IASParserASDocDelegate;
+import org.apache.flex.compiler.constants.IASLanguageConstants;
+import org.apache.flex.compiler.problems.ICompilerProblem;
+import org.apache.flex.compiler.problems.*;
+
+import org.antlr.v4.runtime.tree.TerminalNode;
+
+}
+
+/**
+ * ActionScript3 parser grammar. It consumes ASTokens and produces IASNode AST.
+ * The number of tokens in a single syntactic predicate can not be greater than
+ * StreamingTokenBuffer.REWIND_BUFFER_SIZE.
+ *
+ * @see <a href="https://zerowing.corp.adobe.com/display/FlashPlayer/ActionScript+Language+Specification">ActionScript Language Syntax Specification</a>
+ */
+/*class ASParser extends Parser("org.apache.flex.compiler.internal.parsing.as.BaseASParser");
+ 
+options
+{ 
+	exportVocab = AS;
+	defaultErrorHandler = false;
+}
+
+{
+
+     * Construct an AS3 parser from a token buffer.
+    public ASParser(IWorkspace workspace, IRepairingTokenBuffer buffer)
+    {
+    	super(workspace, buffer);
+    	tokenNames = _tokenNames;
+    }
+
+     * Construct an AS3 parser for parsing command line config args
+	public ASParser(IWorkspace workspace, IRepairingTokenBuffer buffer, boolean parsingProjectConfigVariables)
+    {
+    	super(workspace, buffer, parsingProjectConfigVariables);
+    	tokenNames = _tokenNames;
+    }
+}*/
+
+
+/*
+ * Matches multiple directives. This layer is added to handle parsing error in directives.
+ */
+fileLevelDirectives[ContainerNode c]
+    :   (directive[c, -1])*
+    ;
+//    exception catch [RecognitionException parserError] { handleParsingError(parserError);  }
+
+/*
+ * Matches a "directive" level input.
+ * The first couple of alternatives gated with semantic predicates are used to
+ * either disambiguate inputs, or to trap erroneous syntax.
+ */
+directive[ContainerNode c, int endToken]
+/*{
+    final ASToken lt1 = LT(1);
+    final ASToken lt2 = LT(2);
+    final int la1 = LA(1);
+    final int la2 = LA(2);
+    final int la3 = LA(3);
+    final int la4 = LA(4);
+}*/
+    :   { _input.LA(1) == TOKEN_BLOCK_OPEN }? groupDirective[c, endToken]
+    |   { _input.LA(1) == TOKEN_RESERVED_WORD_NAMESPACE && _input.LA(2) == TOKEN_PAREN_OPEN }? statement[c, endToken]
+    |   { _input.LA(1) == TOKEN_IDENTIFIER && _input.LA(2) == TOKEN_NAMESPACE_ANNOTATION && _input.LT(1).getLine() == _input.LT(2).getLine() }?
+        // Skip over the user-defined namespace name and continue.
+        /*nsT:*/TOKEN_IDENTIFIER attributedDefinition[c] /*{ trapInvalidNamespaceAttribute((ASToken)nsT); }*/
+    |   asDocComment
+    |   importDirective[c]
+    |   useNamespaceDirective[c] 
+    |   { _input.LA(1) == TOKEN_NAMESPACE_NAME &&
+    	  _input.LA(2) == TOKEN_OPERATOR_NS_QUALIFIER &&
+    	  _input.LA(3) == TOKEN_IDENTIFIER &&
+    	  _input.LA(4) == TOKEN_BLOCK_OPEN}?
+        // ns::var { ... }
+        groupDirectiveWithConfigVariable[c, endToken]
+    |   { _input.LA(1) == TOKEN_NAMESPACE_NAME &&
+    	  _input.LA(2) == TOKEN_OPERATOR_NS_QUALIFIER &&
+    	  _input.LA(3) == TOKEN_NAMESPACE_ANNOTATION }?
+        // ns::var private var foo:int;
+        attributedDefinition[c]  
+    |   { _input.LA(1) == TOKEN_NAMESPACE_NAME &&
+    	  _input.LA(2) == TOKEN_OPERATOR_NS_QUALIFIER }?
+        // "ns::var" or "ns::[x, y]"
+        statement[c,endToken]
+    |   { !isFunctionClosure() }? 
+        attributedDefinition[c]  
+    |   packageDirective[c]
+    |   statement[c,endToken]
+    |   configNamespace[c]  
+    |   includeDirective
+    // The following alternatives are error traps
+    |   /*fT:*/TOKEN_KEYWORD_FINALLY   /*{ reportUnexpectedTokenProblem((ASToken)fT); }*/
+    |   /*cT:*/TOKEN_KEYWORD_CATCH     /*{ reportUnexpectedTokenProblem((ASToken)cT); }*/
+    ;
+    /*exception catch [RecognitionException ex]
+    { 
+    	handleParsingError(ex, endToken);  
+    	consumeUntilKeywordOrIdentifier(endToken); 
+    }*/
+	
+/**
+ * Include processing is usually done in the lexer. However, this rule is added
+ * in order to support code model partitioner whose tokenizer is set to not
+ * "follow includes". In a normal AS3 compilation, the parser would never see
+ * the "include" token. 
+ */
+includeDirective
+    :   TOKEN_KEYWORD_INCLUDE TOKEN_LITERAL_STRING 
+    ;
+    
+/**
+ * Matches an attributed definition. An "attribute" can be a namespace or a 
+ * modifier.
+ */
+attributedDefinition[ContainerNode c]	
+/*{
+    List<INamespaceDecorationNode> namespaceAttributes = new ArrayList<INamespaceDecorationNode>();
+    List<ModifierNode> modifiers = new ArrayList<ModifierNode>(); 
+    INamespaceDecorationNode namespaceAttr = null;
+    
+    boolean enabled = isDefinitionEnabled(c);
+    boolean eval = true;
+}*/
+    :   (eval=configConditionOfDefinition)?
+        /*{
+        	// A configuration condition variable can either be matched by
+        	// the above rule or be transformed into a LiteralNode of boolean
+        	// type. If either is evaluated to false, the definition is disabled.
+        	enabled &= eval;
+            if (!enabled)
+			    c = new ContainerNode(); 
+        }*/
+        (attribute[modifiers, namespaceAttributes])* 
+        /*{
+            // Verify that at most one namespace attribute is matched.
+            verifyNamespaceAttributes(namespaceAttributes);
+            
+            if (!namespaceAttributes.isEmpty())
+               namespaceAttr = namespaceAttributes.get(0);
+        }*/
+        definition[c, namespaceAttr, modifiers]
+/*    	exception catch [RecognitionException ex]
+    	{ 
+    		handleParsingError(ex);  
+    	}*/
+    ;
+
+/**
+ * Matches an attribute such as:
+ * - Modifiers: dynamic, final, native, override, static, virtual.
+ * - Namespace names.
+ * - Reserved namespace names: internal, private, public, protected.
+ *
+ * A definition can have at most one "namespace attribute".
+ * The matched attribute is added to the lists passed in as arguments.
+ */
+attribute [List<ModifierNode> modifiers, List<INamespaceDecorationNode> namespaceAttributes] 
+/*{
+    ExpressionNodeBase namespaceNode = null; 
+    ModifierNode modifierNode = null;
+}*/
+    :   modifierNode=modifierAttribute
+        /*{
+            if (modifierNode != null)
+                modifiers.add(modifierNode);
+        }*/
+    |   namespaceNode=namespaceModifier 
+        /*{
+            if (namespaceNode instanceof INamespaceDecorationNode)
+                namespaceAttributes.add((INamespaceDecorationNode) namespaceNode); 
+        }*/
+    ;
+	
+	
+/**
+ * Matches a definition of variable, function, namespace, class or interface.
+ */
+definition[ContainerNode c, INamespaceDecorationNode ns, List<ModifierNode> modList]
+    :   variableDefinition[c, ns, modList]
+    |   functionDefinition[c, ns, modList]
+    |   namespaceDefinition[c, ns, modList]
+    |   classDefinition[c, ns, modList]
+    |   interfaceDefinition[c, ns, modList]
+    ;
+	
+/**
+ * Matches a "group" in a "group directive". 
+ * Entering a "Block" leaves the global context, but entering a "Group" doesn't.
+ */
+groupDirective[ContainerNode c, int endToken]
+/*{
+    BlockNode b = new BlockNode(); 
+    enterGroup();
+}*/
+    :   /*openT:*/TOKEN_BLOCK_OPEN      /*{ b.startAfter(openT); }*/
+        (directive[c, endToken])*
+    	{ if(b.getChildCount() > 0) c.addItem(b); }
+    	/*closeT:*/TOKEN_BLOCK_CLOSE    /*{ b.endBefore(closeT); leaveGroup(); }*/
+    ;
+
+/**
+ * Matches a config condition such as "CONFIG::debug". This rule only applies 
+ * to blocks gated with configuration variable.
+ *
+ * @return Evaluated result of the configuration variable.
+ */
+configCondition returns [boolean result]
+/*{
+	result = false;
+}*/
+    :   /*ns:*/TOKEN_NAMESPACE_NAME /*op:*/TOKEN_OPERATOR_NS_QUALIFIER /*id:*/TOKEN_IDENTIFIER
+        /*{
+            result = evaluateConfigurationVariable(ns.getText(), (ASToken) op, id.getText());
+        }*/
+    ;
+    
+/**
+ * Similar to "configCondition", only that the token type after "::" is 
+ * "TOKEN_NAMESPACE_ANNOTATION". This rule only applies to "attributed 
+ * definitions".
+ */
+configConditionOfDefinition returns [boolean result]
+/*{
+	result = false;
+}*/
+    :   /*ns:*/TOKEN_NAMESPACE_NAME /*op:*/TOKEN_OPERATOR_NS_QUALIFIER /*id:*/TOKEN_NAMESPACE_ANNOTATION
+        /*{
+            result = evaluateConfigurationVariable(ns.getText(), (ASToken) op, id.getText());
+        }*/
+    ;
+    
+/**
+ * Matches a group of directives gated with configuration variable.
+ *
+ *     CONFIG::debug {
+ *         trace("debugging code");
+ *     }
+ *
+ * If the configuration variable evaluates to false, the following block will
+ * not be added to the resulting AST.
+ */
+groupDirectiveWithConfigVariable [ContainerNode c, int endToken]
+/*{
+    boolean b;
+    ConfigConditionBlockNode block;
+    final Token lt = LT(1);
+}*/
+    :   /*b=*/configCondition
+        /*{
+        	block = new ConfigConditionBlockNode(b);
+        	block.startBefore(lt);
+        	c.addItem(block);
+        }*/
+        groupDirective[block, endToken]
+    ;
+	
+/**
+ * Matches a statement.
+ *
+ * Note that the "SuperStatement" in ASL syntax spec is not explicitly defined.
+ * The "super" statements like <code>super(args);</code> are matched as regular
+ * "call" expressions.
+ */
+statement[ContainerNode c, int exitCondition]
+/*{
+    final int la1 = LA(1);
+    final int la2 = LA(2);
+}*/
+    :   breakOrContinueStatement[c]
+    |   defaultXMLNamespaceStatement[c]
+    |   gotoStatement[c]                 
+    |   emptyStatement
+    |   { _input.LA(1) == TOKEN_IDENTIFIER && _input.LA(2) == TOKEN_COLON }? labeledStatement[c, exitCondition]
+    |   { _input.LA(1) != TOKEN_SQUARE_OPEN &&
+    	  _input.LA(1) != TOKEN_OPERATOR_LESS_THAN &&
+    	  _input.LA(1) != TOKEN_BLOCK_OPEN }? expressionStatement[c]
+    |   forStatement[c]
+    |   ifStatement[c]
+    |   meta[c]
+    |   returnStatement[c]
+    |   switchStatement[c]
+    |   throwsStatement[c]
+    |   tryStatement[c]
+    |   whileStatement[c]
+    |   doStatement[c]
+    |   withStatement[c]
+    ;
+/*    exception catch [RecognitionException ex]
+    { 
+        handleParsingError(ex);  
+        consumeUntilKeywordOrIdentifier(exitCondition); 
+    }*/
+    
+/**
+ * Matches an "expression statement". The ASL syntax specification says the 
+ * lookahead can not be "[", "{" or "function". Legacy code requires that "<"
+ * be excluded as well.
+ */
+expressionStatement[ContainerNode c]
+/*{
+    ExpressionNodeBase e = null; 
+    
+    if (LA(1) == TOKEN_KEYWORD_FUNCTION)
+    {
+        // Recover: continue parsing function as an anonymous function.
+        logSyntaxError(LT(1));
+    }
+}*/
+    :   /*e=*/expression
+        /*{
+            c.addItem(e);
+            if (!matchOptionalSemicolon())
+            {
+                recoverFromExpressionStatementMissingSemicolon(e);
+            }
+        }*/
+    ;
+
+/**
+ * <h1>From ASL syntax spec:</h1>
+ * <quote>
+ * InnerSubstatement is defined in the grammar for the sole purpose of 
+ * specifying side conditions that disambiguate various syntactic ambiguities 
+ * in a context-sensitive manner specified in Section 5.
+ * </quote>
+ *
+ * It is only used in "do statement" and "if statement" to loosen the following
+ * two cases allowed by AS3 but not by ECMA5.
+ *
+ * <code>
+ * do x++ while (x < 10);     // ES5 would require a ; after x++
+ * if (x > 10) x++ else y++;  // ES5 would require a ; after x++
+ * <code>
+ */
+innerSubstatement[ContainerNode c]
+    :   substatement[c] /*{ afterInnerSubstatement(); }*/
+    ;
+    
+/**
+ * Matches a sub-statement. 
+ */
+substatement[ContainerNode c]
+    :   (   { _input.LA(1) != TOKEN_BLOCK_OPEN }? statement[c, -1]
+        |   block[c] 
+        |   variableDefinition[c, null, null]
+        )
+        {
+        	if (c.getContainerType() == ContainerType.SYNTHESIZED)
+            	c.setContainerType(ContainerType.IMPLICIT);
+        }
+    ;
+
+/**
+ * Matches a "labeled statement". For example:
+ *
+ *     innerLoop: x++;
+ *
+ */
+labeledStatement[ContainerNode c, int exitCondition]
+/*{
+	LabeledStatementNode statementNode = null;
+	ASToken offendingNSToken = null;
+}*/
+    :   /*labelT:*/TOKEN_IDENTIFIER TOKEN_COLON
+        /*{
+            final NonResolvingIdentifierNode labelNode = 
+            	new NonResolvingIdentifierNode(
+                    labelT != null ? labelT.getText() : "",
+                    labelT);	
+            statementNode = new LabeledStatementNode(labelNode);
+            c.addItem(statementNode);
+        }*/
+        (   { _input.LA(1) == TOKEN_RESERVED_WORD_NAMESPACE && _input.LA(2) == TOKEN_IDENTIFIER }?
+            /*{ offendingNSToken = LT(1); }*/
+            namespaceDefinition[c, null, null] 
+            /*{ trapInvalidSubstatement(offendingNSToken); }*/
+        |   substatement[statementNode.getLabeledStatement()]
+        )
+    ;
+		 	
+/**
+ * Matches a block.
+ */
+block[ContainerNode b]
+    :   /*openT:*/TOKEN_BLOCK_OPEN
+        /*{
+        	b.startAfter(openT); 
+            b.setContainerType(ContainerType.BRACES);
+        }*/
+        (directive[b, TOKEN_BLOCK_CLOSE])*
+        /*closeT:*/TOKEN_BLOCK_CLOSE    /*{ b.endBefore(closeT); }*/
+    ;
+/*    exception catch [RecognitionException ex]
+    { 
+        handleParsingError(ex);   
+        consumeUntilKeywordOrIdentifier(TOKEN_BLOCK_CLOSE); 
+        endContainerAtError(ex, b);
+    }*/
+
+/**
+ * Matches an import directive.
+ *
+ *     import flash.display.Sprite;
+ *     import flash.events.*;
+ */
+importDirective[ContainerNode c]
+/*{
+	ExpressionNodeBase n = null; 
+	ImportNode i = null; 
+}*/
+    :   /*importT:*/TOKEN_KEYWORD_IMPORT
+    	/*{
+    		i = new ImportNode((ExpressionNodeBase) null);
+    		i.startBefore(importT);
+    		i.endAfter(importT); 
+    		c.addItem(i);
+    	}*/
+    
+        n=importName
+    	/*{
+     		if(n != null) {
+     			i.setImportTarget(n);
+     			i.setEnd(n.getEnd());
+     			encounteredImport(i);
+     		} 
+     		else {
+     			i.setImportTarget(new IdentifierNode(""));
+     		}
+     		matchOptionalSemicolon();
+    	}*/
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches "use namespace ns" directive.
+ */
+useNamespaceDirective[ContainerNode c]
+/*{
+	ExpressionNodeBase n = null;
+	UseNamespaceNode u = null;
+}*/
+    :   /*useT:*/YeTOKEN_KEYWORD_USE /*{ u = new UseNamespaceNode(n); u.startBefore(useT); c.addItem(u); }*/
+        /*nsT:*/TOKEN_RESERVED_WORD_NAMESPACE /*{ u.endAfter(nsT); }*/ n=restrictedName
+    	/*{
+    		u.setTargetNamespace(n);
+    		u.setEnd(n.getEnd());
+    		matchOptionalSemicolon();
+    	}*/
+    ;
+/*    exception catch [RecognitionException ex]
+	{ 
+		if (u != null && u.getTargetNamespace() == null) 
+			u.setTargetNamespace(handleMissingIdentifier(ex));
+		else 
+			handleParsingError(ex);  
+	}*/
+
+/**
+ * Matches an ASDoc block.
+ */		 
+asDocComment 
+    :   /*asdocT:*/TOKEN_ASDOC_COMMENT
+		/*{
+			asDocDelegate.setCurrentASDocToken(asdocT);
+		}*/
+	;
+
+/**
+ * Matches a "modifier attribute" such as "final", "dynamic", "override", 
+ * "static" or "native".
+ */
+modifierAttribute returns [ModifierNode modifierNode]
+/*{
+    modifierNode = null;
+    final ASToken modifierT = LT(1); 
+}*/
+    :   (   TOKEN_MODIFIER_FINAL
+        |   TOKEN_MODIFIER_DYNAMIC
+        |   TOKEN_MODIFIER_OVERRIDE
+        |   TOKEN_MODIFIER_STATIC
+        |   TOKEN_MODIFIER_NATIVE
+        |   TOKEN_MODIFIER_VIRTUAL
+        )
+        /*{ modifierNode = new ModifierNode((ASToken) modifierT);	}*/
+	;
+	
+ 
+/**
+ * Matches a namespace modifier on an "attributed definition".
+ */
+namespaceModifier returns[ExpressionNodeBase n]
+/*{
+    n = null;
+}*/
+    :   /*nsPart1T:*/TOKEN_NAMESPACE_ANNOTATION
+    	/*{
+        	// If our text token is a member access, then build a normal 
+        	// identifier. Otherwise, build a NS specific one.
+        	
+        	if (LA(1) == TOKEN_OPERATOR_MEMBER_ACCESS) 
+        	{
+                n = new IdentifierNode((ASToken)nsPart1T) ;
+            }
+            else
+            {
+                final NamespaceIdentifierNode nsNode = new NamespaceIdentifierNode((ASToken)nsPart1T); 
+        		nsNode.setIsConfigNamespace(isConfigNamespace(nsNode));
+        		n = nsNode;
+        	}
+    	}*/
+    	(
+            /*dotT:*/TOKEN_OPERATOR_MEMBER_ACCESS
+            (
+                /*nsNameT:*/TOKEN_NAMESPACE_ANNOTATION
+        		/*{
+        			IdentifierNode id = new IdentifierNode((ASToken)nsNameT);
+        			n = new FullNameNode(n, (ASToken) dotT, id);
+        		}*/
+        	)
+    	)*
+    	/*{
+            if (n instanceof FullNameNode) 
+        	   n = new QualifiedNamespaceExpressionNode((FullNameNode)n);
+    	}*/
+    
+    ;
+
+/**
+ * Matches a "metadata statement".
+ *
+ *     [ExcludeClass()]
+ *     [Bindable]
+ */
+meta[ContainerNode c]
+/*{
+	ArrayLiteralNode al = new ArrayLiteralNode(); 
+	final ASToken lt = LT(1);
+}*/
+    :   /*attributeT:*/TOKEN_ATTRIBUTE
+        /*{
+        	// Note that a separate parser is invoked here for metadata.
+            parseMetadata(attributeT, errors); 
+            preCheckMetadata(attributeT, c);
+    	}*/
+	|   { isIncompleteMetadataTagOnDefinition() }?
+	    TOKEN_SQUARE_OPEN
+	    // Error trap for "[" before a definition item.
+	    { logSyntaxError(_input.LT(1)); }
+    |   arrayInitializer[al]  
+        // This is statement-level metadata.
+        /*{
+        	// Synthesize a MetaTagsNode to hold the metadata offsets.
+            currentAttributes = new MetaTagsNode();
+            currentAttributes.span(al, al);
+            preCheckMetadata(lt, c);
+        }*/
+    ;
+/* 	exception catch [RecognitionException ex]
+ 	{ 
+ 		recoverFromMetadataTag(c, al); 
+	}*/
+ 	
+/**
+ * Matches a "config namespace foo" directive.
+ */
+configNamespace[ContainerNode c]
+	:   TOKEN_RESERVED_WORD_CONFIG TOKEN_RESERVED_WORD_NAMESPACE /*configN:*/TOKEN_IDENTIFIER
+		/*{
+			NamespaceNode cNode = new ConfigNamespaceNode(new IdentifierNode((ASToken)configN));
+			addConditionalCompilationNamespace(cNode);
+            matchOptionalSemicolon();
+		}*/
+	    
+	;
+/*	exception catch [RecognitionException ex]
+	{ handleParsingError(ex); }*/
+
+/**
+ * Matches a "package" block.
+ *
+ *     package mx.controls { ... }
+ *
+ */
+packageDirective[ContainerNode c]
+/*{
+	PackageNode p = null; 
+	ExpressionNodeBase name = null; 
+	BlockNode b = null; 
+}*/
+    :   /*packageT:*/TOKEN_KEYWORD_PACKAGE /*{ enterPackage((ASToken)packageT); }*/
+        (name=packageName)?
+        /*{
+        	p = new PackageNode(name != null ? name : IdentifierNode.createEmptyIdentifierNodeAfterToken(packageT), (ASToken)packageT);
+        	p.startBefore(packageT);
+        	c.addItem(p);
+        	b = p.getScopedNode();
+        }*/
+        (   /*openT:*/TOKEN_BLOCK_OPEN /*{ b.startAfter(openT); }*/
+        	packageContents[b]
+        )
+        /*{ leavePackage(); }*/
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); leavePackage();  }
+	
+/**
+ * Matches a package name such as:
+ *     org.apache.flex
+ *
+ * A Whitespace or LineTerminator is allowed around a . in a PackageName. 
+ * For example, the following is a syntactically valid
+ * <pre>
+ * package a .
+ *         b
+ * { }
+ * </pre>
+ * The resulting PackageName value is equivalent to a PackageName without any intervening Whitespace and LineTerminators.
+ */	
+packageName returns [ExpressionNodeBase n]
+/*{
+	n = null; 
+	ExpressionNodeBase e = null; 
+}*/
+ 	:	/*n=*/identifier
+		(options{greedy=true;}: { _input.LA(2) != TOKEN_OPERATOR_STAR }?
+			/*dotT:*/TOKEN_OPERATOR_MEMBER_ACCESS
+			/*{
+				n = new FullNameNode(n, (ASToken) dotT, null); 
+			}*/
+			/*e=*/identifier
+			/*{
+				((FullNameNode)n).setRightOperandNode(e); 
+			}*/
+		)*
+	;
+//	exception catch [RecognitionException ex] { return handleMissingIdentifier(ex, n); }
+	
+/**
+ * Matches contents in a package block.
+ */
+packageContents[ContainerNode b]
+    :   (directive[b, TOKEN_BLOCK_CLOSE])* 
+    	/*closeT:*/TOKEN_BLOCK_CLOSE /*{ b.endBefore(closeT); }*/
+    ;
+/*    exception catch [RecognitionException ex]
+	{
+        if(handleParsingError(ex)) 
+        {
+        	//attempt to recover from the error so we can keep parsing within the block
+            packageContents(b); 
+        } 
+        else 
+        {
+            endContainerAtError(ex, b); 
+        } 
+    }*/
+
+/**
+ * Matches a namespace definition.
+ *
+ *     namespace ns1;
+ */
+namespaceDefinition[ContainerNode c, INamespaceDecorationNode namespace, List<ModifierNode> modList]
+/*{
+	NamespaceNode n = null; 
+	IdentifierNode id = null; 
+	ExpressionNodeBase v = null; 
+}*/
+	:   /*nsT:*/TOKEN_RESERVED_WORD_NAMESPACE id=identifier
+		/*{
+			n = new NamespaceNode(id);
+			n.startBefore(nsT);
+			storeDecorations(n, c, namespace, modList);
+            checkNamespaceDefinition(n);
+		}*/
+		(initializer[n])?
+    	/*{
+			c.addItem(n);
+    		matchOptionalSemicolon(); 
+    	}*/
+	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches an interface definition.
+ *
+ *     interface IFoo extends IBar {...}
+ */
+interfaceDefinition[ContainerNode c,  INamespaceDecorationNode namespace, List<ModifierNode> modList]
+/*{
+	InterfaceNode interfaceNode = null; 
+	IdentifierNode intName = null; 
+	ExpressionNodeBase baseInterfaceName = null; 
+	BlockNode b = null; 
+    enterInterfaceDefinition(LT(1));
+}*/
+    :   /*intT:*/TOKEN_KEYWORD_INTERFACE intName=identifier
+		/*{
+			interfaceNode = new InterfaceNode(intName);
+			interfaceNode.setInterfaceKeyword((IASToken)intT);
+			storeDecorations(interfaceNode, c, namespace, modList);
+			c.addItem(interfaceNode);
+			
+			// Recover from invalid interface name.
+			final int la1 = LA(1);
+			if (la1 != TOKEN_RESERVED_WORD_EXTENDS && la1 != TOKEN_BLOCK_OPEN)
+			{
+			    addProblem(new SyntaxProblem(LT(1)));
+			    consumeUntilKeywordOr(TOKEN_BLOCK_OPEN);
+			}
+		}*/
+		(	/*extendsT:*/TOKEN_RESERVED_WORD_EXTENDS
+			/*{ interfaceNode.setExtendsKeyword((ASToken)extendsT); }*/
+			(	baseInterfaceName=restrictedName
+				/*{
+					interfaceNode.addBaseInterface(baseInterfaceName);  
+					interfaceNode.setEnd(baseInterfaceName.getEnd()); 
+				}*/
+ 
+				(	/*commaT:*/TOKEN_COMMA
+					/*{ interfaceNode.endAfter(commaT); }*/
+					(	baseInterfaceName=restrictedName
+						/*{
+							interfaceNode.addBaseInterface(baseInterfaceName); 
+							interfaceNode.setEnd(baseInterfaceName.getEnd()); 
+						}*/
+					)
+				)*
+			)
+		)?
+ 
+		/*{
+ 		  	b = interfaceNode.getScopedNode();
+ 		}*/
+ 	
+ 		/*openT:*/TOKEN_BLOCK_OPEN
+			/*{ b.startAfter(openT); }*/
+		classOrInterfaceBlock[b]
+ 	;
+// 	exception catch [RecognitionException ex] { handleParsingError(ex);  }
+ 
+/**
+ * Matches a class definition. For example:
+ *
+ *     class Player extends my_ns::GameObject implements IPlayer { ... }
+ *
+ */
+classDefinition [ContainerNode c, INamespaceDecorationNode namespace, List<ModifierNode> modList]
+/*{
+    IdentifierNode className = null; 
+    ExpressionNodeBase superName = null; 
+    ExpressionNodeBase interfaceName = null;
+    ClassNode classNode = null;
+    disableSemicolonInsertion();
+    enterClassDefinition(LT(1));
+}*/
+    :   /*classT:*/TOKEN_KEYWORD_CLASS className=identifier
+        /*{
+            // When class name is empty, it is a synthesized IdentifierNode
+            // created by the error recovery logic in "identifier" rule.
+            // In such case, we fast-forward the token stream to the next
+            // keyword to recover.
+            if (className.getName().isEmpty())
+            {
+                // If the parser recover from "extends", "implements" or "{", 
+                // we are could continue parsing the class definition, because
+                // these tokens are the "follow set" of a class name token.
+                // Otherwise, the next keyword is still a good starting point.
+                consumeUntilKeywordOr(TOKEN_BLOCK_OPEN);
+            }
+            
+            insideClass = true;
+            classNode = new ClassNode(className);
+            classNode.setSourcePath(((IASToken)classT).getSourcePath());
+            classNode.setClassKeyword((IASToken)classT);
+            storeDecorations(classNode, c, namespace, modList);
+            c.addItem(classNode);
+        }*/
+         
+        (   /*extendsT:*/TOKEN_RESERVED_WORD_EXTENDS
+            /*{ classNode.setExtendsKeyword((ASToken)extendsT); }*/
+            // The rule for super type should be "restrictedName". However, in
+            // order to trap errors like "class Foo extends Vector.<T>", the
+            // parser has to allow parameterized type as super name. It's up to
+            // semantic analysis to report this problem.
+            superName=type 
+        	/*{
+        		classNode.setBaseClass(superName); 
+        		classNode.setEnd(superName.getEnd()); 
+        	}*/
+//            exception catch [RecognitionException ex] { handleParsingError(ex); }
+        )?
+ 
+        (   /*impT:*/ TOKEN_RESERVED_WORD_IMPLEMENTS
+            /*{ classNode.setImplementsKeyword((ASToken)impT); }*/
+            (   interfaceName=restrictedName
+                /*{
+                    classNode.addInterface(interfaceName);
+                    classNode.setEnd(interfaceName.getEnd());
+                }*/
+                (   /*commaT:*/TOKEN_COMMA
+                    /*{ classNode.endAfter(commaT); }*/
+                    interfaceName=restrictedName
+                    /*{
+                        classNode.addInterface(interfaceName); 
+                        classNode.setEnd(interfaceName.getEnd()); 
+                    }*/
+                )*
+//                exception catch [RecognitionException ex] { handleParsingError(ex); }
+            )
+//            exception catch [RecognitionException ex] { handleParsingError(ex);  }
+        )?
+		
+        /*openT:*/TOKEN_BLOCK_OPEN
+        /*{ classNode.getScopedNode().startAfter(openT); }*/
+        classOrInterfaceBlock[classNode.getScopedNode()]
+	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex);  }
+
+/**
+ * Matches the content block of a class definition or an interface definition.
+ */
+classOrInterfaceBlock[BlockNode b]
+// 	{ enableSemicolonInsertion(); }
+	
+	:   (directive[b, TOKEN_BLOCK_CLOSE])*
+		/*closeT:*/TOKEN_BLOCK_CLOSE
+		/*{ b.endBefore(closeT); }*/
+	;
+/*	exception catch [RecognitionException ex]
+	{ 
+		if(handleParsingError(ex))  {
+			classOrInterfaceBlock(b); //attempt to retry
+		} else {
+			endContainerAtError(ex, b); 
+		}
+	}*/
+	
+/**
+ * Matches an anonymous function (function closure).
+ */
+functionExpression returns [FunctionObjectNode n]
+/*{
+	n = null; 
+	BlockNode b = null; 
+	FunctionNode f = null; 
+	IdentifierNode name=null; 
+	ContainerNode p = null;
+}*/
+ 	:   /*functionT:*/TOKEN_KEYWORD_FUNCTION
+ 	
+ 		// optional function name
+ 		(name=identifier)?
+		/*{
+			if(name == null) 
+				name = IdentifierNode.createEmptyIdentifierNodeAfterToken(functionT);
+			f = new FunctionNode((ASToken)functionT, name);
+			n = new FunctionObjectNode(f);
+			f.startBefore(functionT);
+			n.startBefore(functionT);
+			b = f.getScopedNode();
+			disableSemicolonInsertion();
+		}*/
+ 
+        // function signature
+    	/*lpT:*/TOKEN_PAREN_OPEN
+		/*{
+			p = f.getParametersContainerNode();
+			p.startAfter(lpT);
+		}*/
+    	formalParameters[p]
+    	/*rpT:*/TOKEN_PAREN_CLOSE
+ 		/*{ p.endBefore(rpT); }*/
+    	(resultType[f])?
+     	/*{ enableSemicolonInsertion(); }*/
+
+		// non-optional function body     		
+     	/*lbT:*/TOKEN_BLOCK_OPEN
+		/*{ b.startAfter(lbT);}*/
+     	functionBlock[f, (ASToken)lbT]		
+ 	;
+// 	exception catch [RecognitionException ex] { handleParsingError(ex);  }
+
+/**
+ * Matches a function block, excluding the open "{" but including the closing "}".
+ */
+functionBlock[FunctionNode f, ASToken openT]
+/*{
+    final BlockNode b = f.getScopedNode();
+    b.setContainerType(IContainerNode.ContainerType.BRACES); 
+    skipFunctionBody(f, openT);
+}*/
+	:   (directive[b, TOKEN_BLOCK_CLOSE])*
+        /*rbT:*/TOKEN_BLOCK_CLOSE
+	  	/*{ b.endBefore(rbT); }*/
+	;
+/*  	exception catch [RecognitionException ex]
+	{ 
+		IASToken prev = buffer.previous();
+        if (prev.getType() != ASTokenTypes.EOF)
+            b.endAfter(prev);
+        else
+            b.setEnd(b.getStart());
+		if(handleParsingError(ex))  {
+			functionBlock(f, openT); //attempt to retry
+		} 
+	}*/
+
+/**
+ * Matches an optional function body. It can either be a "block" or a 
+ * "semicolon".
+ */
+optionalFunctionBody [FunctionNode f]
+/*{
+    BlockNode blockNode = f.getScopedNode();
+    enableSemicolonInsertion();
+}*/
+    :   { _input.LA(1) == TOKEN_BLOCK_OPEN }? /*lbT:*/TOKEN_BLOCK_OPEN
+        /*{ blockNode.startAfter(lbT); }*/
+        functionBlock[f, (ASToken)lbT]   
+    |   { buffer.matchOptionalSemicolon() }? // Matches a function without body.
+    |   /*{
+            final Token lt = LT(1);
+            blockNode.startBefore(lt);
+            blockNode.endBefore(lt);
+
+            // Report missing left-curly problem if there's no other syntax
+            // problems in the function definition.
+            reportFunctionBodyMissingLeftBraceProblem();
+        }*/
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a function definition. For example:
+ *
+ *     private function myFunction(name:String) : void
+ *     {
+ *         return;
+ *     }
+ *
+ */	
+functionDefinition[ContainerNode c, INamespaceDecorationNode namespace, List<ModifierNode> modList]
+/*{
+	IdentifierNode name=null; 
+    disableSemicolonInsertion();
+}*/
+	:   (   /*functionT:*/TOKEN_KEYWORD_FUNCTION
+	
+			// optional accessors:
+			// Although "get" and "set" can be identifiers as well, here
+			// they can only be the reserved words, unless it's a function
+			// called "get()" or "set()". As a result, the parser
+			// needs to match it in a "greedy" fashion.
+	        (options{greedy=true;}:
+	        	{ _input.LA(2) != TOKEN_PAREN_OPEN}? /*getT:*/TOKEN_RESERVED_WORD_GET
+        	|   { _input.LA(2) != TOKEN_PAREN_OPEN}? /*setT:*/TOKEN_RESERVED_WORD_SET
+        	)? 
+        	
+        	// non-optional function name:
+	        name=identifier
+			//we need to be able to keep going in case we are in the processing of typing a function name
+//			exception catch [RecognitionException ex] { name = handleMissingIdentifier(ex); }
+		)
+/*		{
+			final FunctionNode n ;
+			if (getT != null)
+				n = new GetterNode((ASToken)functionT, (ASToken)getT, name);
+			else if (setT != null)
+				n = new SetterNode((ASToken)functionT, (ASToken)setT, name);
+			else
+				n = new FunctionNode((ASToken)functionT, name);
+ 
+			storeDecorations(n, c, namespace, modList);
+			c.addItem(n);
+		}*/
+		
+		// function signature:
+		/*lpT:*/TOKEN_PAREN_OPEN
+		/*{
+			final ContainerNode parameters = n.getParametersContainerNode();
+			parameters.startAfter(lpT);
+ 		}*/
+     	formalParameters[parameters]
+     	(	/*rpT:*/TOKEN_PAREN_CLOSE
+     		/*{ parameters.endBefore(rpT); }*/
+     		// error recovery for typing in-progress function definitions
+//     		exception catch [RecognitionException ex] { handleParsingError(ex); }
+     	)
+     	(resultType[n])?
+     	
+     	optionalFunctionBody[n]
+ 	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches the parameters of a function definition signature (excluding the parenthesis).
+ * 
+ *     arg1:int, arg2:String
+ */
+formalParameters[ContainerNode c]
+	: (formal[c] (TOKEN_COMMA formal[c])*)?
+	;
+//	exception catch [RecognitionException ex] {handleParsingError(ex); }
+
+/**
+ * Matches a single parameter in a function definition.
+ */
+formal[ContainerNode c]
+/*	{ ParameterNode p = null; }*/
+	
+	:(/*p=*/restParameter | /*p=*/parameter)
+		/*{ if (p != null) c.addItem(p); }*/
+	;
+
+/**
+ * Matches the "rest parameters" in a function definition.
+ *
+ *     ...args
+ */
+restParameter returns [ParameterNode p]
+/*	{ p = null; }*/
+	
+	: /*e:*/TOKEN_ELLIPSIS /*p=*/parameter
+		/*{
+			if (p != null){
+				// ??? following is an override on default type-specification
+				// ??? and should be pulled soon as that gets resolved.
+				if (p.getTypeNode() == null){
+					p.span(e);
+				}
+				p.setIsRestParameter(true);
+			}
+		}*/
+	;
+	
+/**
+ * Matches a parameter in a function definition.
+ */
+parameter returns [ParameterNode p]
+/*{
+	p = null; 
+	ASToken t = null;
+	IdentifierNode name = null; 
+}*/
+	:   (   /*t=*/varOrConst
+    		/*{
+    			// const allowed here, var is not...log error, keep going
+    			if (t.getType() == TOKEN_KEYWORD_VAR) 
+    				handleParsingError(new RecognitionException()); 
+    		}*/
+        )? 
+	
+        /*name=*/identifier
+		/*{
+			p = new ParameterNode(name); 
+			if (t != null && t.getType() == TOKEN_KEYWORD_CONST)
+				p.setKeyword(t);
+		}*/
+		
+        (resultType[p])?
+        (initializer[p])?	 
+	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches keyword "var" or keyword "const".
+ */
+varOrConst returns[ASToken token]
+/*{
+	token = LT(1); 
+}*/
+	:   TOKEN_KEYWORD_VAR 
+	|   TOKEN_KEYWORD_CONST
+	;
+	
+/**
+ * Matches a result type: either a "void" keyword or a restricted name.
+ *
+ *     :void
+ *     :String
+ *     :int
+ *
+ */
+resultType [BaseTypedDefinitionNode result]
+/*{
+    ExpressionNodeBase t = null; 
+}*/
+    :   /*colon:*/TOKEN_COLON
+        (   ( t=voidLiteral | t=type )
+/*        	exception catch [RecognitionException ex]
+            { t = handleMissingIdentifier(ex); }*/
+        )    
+        /*{
+            if(t.getStart() == -1) 
+                t.startAfter(colon);
+            	
+            if (t.getEnd() == -1) 
+                t.endAfter(colon);
+            	
+            result.endAfter(colon);
+            result.setType((ASToken) colon, t); 
+        }*/
+    ;
+ 	
+/**
+ * Matches an initializer in a variable/constant definition.
+ */
+initializer [IInitializableDefinitionNode v]
+/*{
+	ExpressionNodeBase e = null; 
+}*/
+  	:   /*assignT:*/TOKEN_OPERATOR_ASSIGNMENT
+        e=assignmentRightValue
+ 		/*{ v.setAssignedValue((IASToken) assignT, e); }*/
+ 	;
+// 	exception catch [RecognitionException ex] {handleParsingError(ex);  }
+ 	
+/**
+ * Matches a variable/constant definition.
+ */
+variableDefinition[ContainerNode c, INamespaceDecorationNode namespace, List<ModifierNode> modList]
+/*{
+	VariableNode v = null;
+	ChainedVariableNode v2 = null;
+	ASToken tok = null;
+	asDocDelegate.beforeVariable();
+}*/
+	:   tok=varOrConst v=singleVariable[(ASToken)tok, namespace]
+		/*{
+			asDocDelegate.afterVariable();	
+			storeVariableDecorations(v, c, namespace, modList);
+			if(v instanceof ConfigConstNode) {
+				addConfigConstNode((ConfigConstNode)v);
+			} else {
+				c.addItem(v);
+			}
+		}*/
+    	// don't allow chain after a config
+    	(   {!(v instanceof ConfigConstNode)}? 
+    	    TOKEN_COMMA /*v2=*/chainedVariable[c]
+    		/*{
+    		 	if(v2 != null)
+                {
+                    v.addChainedVariableNode(v2);
+                    storeEmbedDecoration(v2, v.getMetaTags());
+                }
+    		}*/
+//    		exception catch [RecognitionException ex] { handleParsingError(ex); }
+    	)*
+    	/*{ matchOptionalSemicolon(); setAllowErrorsInContext(true); }*/
+	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex); setAllowErrorsInContext(true); }
+
+/**
+ * Matches a single variable/constant definition.
+ */
+singleVariable[IASToken keyword, INamespaceDecorationNode namespace] returns [VariableNode v]
+/*{
+	v = null; 
+	IdentifierNode name = null; 
+}*/
+	:   /*name=*/identifier
+		/*{
+			if(namespaceIsConfigNamespace(namespace)) {
+				v = new ConfigConstNode(name);
+			} else {
+				v = new VariableNode(name);
+			}
+			v.setKeyword(keyword);
+			v.setIsConst(keyword.getType() == TOKEN_KEYWORD_CONST);
+			if(name.getStart() == -1) {
+				name.startAfter(keyword);
+				name.endAfter(keyword);
+			}
+		}*/
+		
+		(resultType[v])? 
+		(initializer[v])?
+	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex); }
+	
+/**
+ * Matches a chained variable/constant definition.
+ */     
+chainedVariable[ContainerNode c] returns [ChainedVariableNode v]
+/*{
+	 v = null; 
+	 IdentifierNode name = null; 
+}*/
+	:   /*name=*/identifier
+		/*{ v = new ChainedVariableNode(name); }*/
+		
+		(resultType[v])?
+		(initializer[v])?
+	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex); }
+	
+/**
+ * Matches variable definitions in a for loop.
+ */
+variableDefExpression returns[NodeBase v]
+/*{
+	v = null; 
+	ContainerNode c = null; 
+	NodeBase v1 = null; 
+	ASToken varT = null;
+}*/
+	:   /*varT=*/varOrConst /*v=*/singleVariableDefExpression[varT, varT.getType() == TOKEN_KEYWORD_CONST]
+		(   TOKEN_COMMA /*v1=*/singleVariableDefExpression[null, varT.getType() == TOKEN_KEYWORD_CONST]
+			/*{
+				if (c == null) {
+					c = new ContainerNode();
+					c.setStart(v.getStart());
+					c.addItem(v);
+					v = c;
+				}
+				c.addItem(v1);
+				c.setEnd(v1.getEnd());
+			}*/
+		)*
+	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex);  }
+		
+/**
+ * Matches a single variable definition in a for loop.
+ */
+singleVariableDefExpression[ASToken varToken, boolean isConst] returns [ExpressionNodeBase n]
+/*{
+	n = null;
+	VariableNode variable = null;
+	IdentifierNode varName = null; 
+	ExpressionNodeBase value = null; 
+}*/
+	:   /*varName=*/identifier
+		/*{
+			variable = new VariableNode(varName);
+			if(varToken != null)
+				variable.setKeyword(varToken);
+			variable.setIsConst(isConst);
+			n = new VariableExpressionNode(variable);
+		}*/
+		
+    	(resultType[variable])?
+    		
+    	(initializer[variable])?
+	;
+
+/**
+ * Matches a default XML namespace statement. For example:
+ * 
+ *    default xml namespace = "domain";
+ *
+ */
+defaultXMLNamespaceStatement[ContainerNode c]
+/*	{ ExpressionNodeBase e = null; }*/
+	
+	: /*defT:*/TOKEN_DIRECTIVE_DEFAULT_XML TOKEN_OPERATOR_ASSIGNMENT e=assignmentExpression
+		/*{
+			DefaultXMLNamespaceNode n = new DefaultXMLNamespaceNode(new KeywordNode((IASToken)defT));
+			c.addItem(n);
+			n.setExpressionNode(e); 
+			matchOptionalSemicolon();
+		}*/
+	;
+
+/**
+ * Matches an expression in a pair of parenthesis. It's usually used as a
+ * condition expression in {@code if (...)}, {@code while (...)}, etc.
+ *
+ *     (....)
+ */
+statementParenExpression returns [ExpressionNodeBase e]
+/*{
+	e = null; 
+}*/
+	:   TOKEN_PAREN_OPEN     { disableSemicolonInsertion(); }
+		/*e=*/expression
+	    TOKEN_PAREN_CLOSE    { enableSemicolonInsertion(); }
+	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex); enableSemicolonInsertion(); }
+	
+		
+/**
+ * Matches an empty statement which is an explicit semicolon.
+ */
+emptyStatement
+ 	:   TOKEN_SEMICOLON
+ 	;
+
+/**
+ * Matches a "return" statement.
+ */
+returnStatement[ContainerNode c]
+/*{
+	ExpressionNodeBase n = null; 
+	ExpressionNodeBase e = null;
+}*/
+	:   /*returnT:*/TOKEN_KEYWORD_RETURN
+		/*{
+			n = new ReturnNode((ASToken)returnT);
+			c.addItem(n);
+			afterRestrictedToken((ASToken)returnT);
+		}*/
+		
+		/*e=*/optExpression
+		/*{
+			((ReturnNode)n).setStatementExpression(e);
+		}*/
+	   /*{ matchOptionalSemicolon(); }*/
+	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a "throw" statement.
+ */
+throwsStatement[ContainerNode c]
+/*{
+	ExpressionNodeBase n = null; 
+	ExpressionNodeBase e = null;
+}*/
+	:   /*throwT:*/TOKEN_KEYWORD_THROW
+		/*{
+			n = new ThrowNode((ASToken)throwT);
+			c.addItem(n);
+			afterRestrictedToken((ASToken)throwT);
+		}*/
+	
+		(   /*e=*/expression
+			/*{
+				((ThrowNode)n).setStatementExpression(e); 
+			}*/
+//			exception catch [RecognitionException ex] { handleParsingError(ex); }
+		)
+	   /*{ matchOptionalSemicolon(); }*/
+	;
+	
+/**
+ * Matches a "for loop" statement.
+ */
+forStatement[ContainerNode c]
+/*{
+    ForLoopNode node = null; 
+    ContainerNode forContainer = null; 
+    BlockNode b = null; 
+    NodeBase fi = null; 
+    ExpressionNodeBase e = null; 
+    BinaryOperatorNodeBase inNode = null;
+}*/
+    :   /*forKeyword:*/TOKEN_KEYWORD_FOR /*lparenT:*/TOKEN_PAREN_OPEN
+        /*{
+            node = new ForLoopNode((ASToken)forKeyword); 
+            c.addItem(node);
+            forContainer = node.getConditionalsContainerNode();
+            b = node.getContentsNode();
+            forContainer.startAfter(lparenT); 
+        }*/
+        
+        /*{
+            expressionMode = ExpressionMode.noIn;
+        }*/
+        /*fi=*/forInitializer
+        /*{
+            expressionMode = ExpressionMode.normal;
+        }*/
+        
+        (   TOKEN_SEMICOLON           /*{ forContainer.addItem(fi); }*/
+            forCondition[forContainer] 
+            TOKEN_SEMICOLON 
+            forStep[forContainer]
+        |   /*in:*/TOKEN_KEYWORD_IN
+            /*{
+                final ExpressionNodeBase leftOfIn;
+                if (fi instanceof ExpressionNodeBase)
+                {
+                    leftOfIn = (ExpressionNodeBase) fi;
+                }
+                else
+                {
+                    // for...in doesn't allow multiple variable definition in the initializer clause
+                    addProblem(new InvalidForInInitializerProblem(node));
+                    if (fi instanceof ContainerNode &&
+                        fi.getChildCount() > 0 &&
+                        ((ContainerNode)fi).getChild(0) instanceof ExpressionNodeBase)
+                    {
+                        // Recover by taking the first variable initializer and
+                        // drop the rest.
+                        leftOfIn = (ExpressionNodeBase)((ContainerNode)fi).getChild(0);
+                    }
+                    else
+                    {
+                        // No valid variable initializer found: recover by adding
+                        // an empty identifier node.
+                        leftOfIn = IdentifierNode.createEmptyIdentifierNodeAfterToken((ASToken)lparenT);
+                    }
+                }
+                inNode = BinaryOperatorNodeBase.create((ASToken)in, leftOfIn, null);
+                forContainer.addItem(inNode);
+            }*/
+            /*e=*/optExpression
+            /*{ inNode.setRightOperandNode(e); }*/
+        )?  // Make optional for error handling.
+        
+        /*{
+            if (forContainer.getChildCount() == 0 && fi != null)
+                forContainer.addItem(fi);
+        }*/
+        
+        (   /*rparenT:*/TOKEN_PAREN_CLOSE
+            /*{
+                forContainer.endBefore(rparenT); 
+            }*/
+//            exception catch [RecognitionException ex] { handleParsingError(ex); }
+        )
+        substatement[b] 
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches the "initializer" part in a for loop.
+ */    
+forInitializer returns [NodeBase n]
+/*{
+	n = null; 
+}*/
+    :   /*n=*/variableDefExpression
+    |   /*n=*/optExpression
+    ;
+//    exception catch [RecognitionException ex] {handleParsingError(ex);  }
+
+/**
+ * Matches the "condition" part in a for loop.
+ */
+forCondition[ContainerNode c]
+/*{
+	ExpressionNodeBase e = null; 
+}*/
+	:   /*e=*/optExpression
+		/*{if (e != null) c.addItem(e);}*/
+	;
+// 	exception catch [RecognitionException ex] {handleParsingError(ex);  }
+
+/**
+ * Matches the "step" part in a for loop.
+ */
+forStep[ContainerNode c]
+/*{
+	ExpressionNodeBase e = null; 
+}*/
+	:    /*e=*/optExpression
+		/*{if (e != null) c.addItem(e);}*/
+	;
+// 	exception catch [RecognitionException ex] {handleParsingError(ex);  }
+ 
+/**
+ * Matches a "do...while" statement.
+ */
+doStatement[ContainerNode c] 
+/*{
+	DoWhileLoopNode n = null; 
+    ExpressionNodeBase e = null; 
+    BlockNode b = null; 
+}*/
+ 	:   /*doT:*/TOKEN_KEYWORD_DO
+ 		/*{
+ 			n = new DoWhileLoopNode((ASToken)doT);
+ 			c.addItem(n);
+ 			b = n.getContentsNode();
+ 		}*/
+ 		
+        innerSubstatement[b]
+        
+        TOKEN_KEYWORD_WHILE /*e=*/statementParenExpression
+ 	 	/*{
+ 	 		n.setConditionalExpression(e); 	
+	        matchOptionalSemicolon(); 
+        }*/
+ 	;
+// 	exception catch [RecognitionException ex] {handleParsingError(ex);  }
+ 	
+/**
+ * Matches a "while" loop statement.
+ * 
+ *     while (x > 1) { x--; }
+ */
+whileStatement[ContainerNode c] 
+/*{
+	WhileLoopNode n = null; 
+	ExpressionNodeBase e = null; 
+	BlockNode b = null; 
+}*/
+ 	:   /*whileT:*/TOKEN_KEYWORD_WHILE /*e=*/statementParenExpression
+ 		/*{
+ 			n = new WhileLoopNode((ASToken)whileT);
+ 			n.setConditionalExpression(e);
+ 			c.addItem(n); 
+ 			b = n.getContentsNode();
+ 		}*/
+ 	
+ 	    substatement[b]
+ 	;
+// 	exception catch [RecognitionException ex] {handleParsingError(ex);  }
+ 	
+ 	
+/**
+ * Matches a "break statement" or a "continue statement". For example:
+ *
+ *    break;
+ *    break innerLoop;
+ *    continue;
+ *    continue outerLoop;
+ *
+ */
+breakOrContinueStatement[ContainerNode c]
+/*{
+    IdentifierNode id = null; 
+    IterationFlowNode n = null; 
+    final ASToken t = LT(1);
+}*/
+    :   ( TOKEN_KEYWORD_CONTINUE | TOKEN_KEYWORD_BREAK ) 
+    	/*{
+    		n = new IterationFlowNode(t); 
+    		c.addItem(n); 
+    		afterRestrictedToken(t);
+    	}*/
+    	
+    	// "greedy" mode is required to associate the following ID with the flow control.
+    	(options{greedy=true;}: 
+    	   /*id=*/identifier
+    	   /*{ n.setLabel(id); }*/
+	    )?
+    	/*{ matchOptionalSemicolon(); }*/
+    ;
+//    exception catch [RecognitionException ex] {handleParsingError(ex); }
+ 	
+/**
+ * Matches a "goto" statement.
+ */
+gotoStatement[ContainerNode c]
+/*{
+	IdentifierNode id = null; 
+	IterationFlowNode n = null; 
+	final ASToken t = LT(1);
+}*/
+    :   TOKEN_RESERVED_WORD_GOTO /*id=*/identifier
+        /*{
+    		n = new IterationFlowNode(t); 
+    		c.addItem(n);
+    		n.setLabel(id);
+    		matchOptionalSemicolon();
+        }*/
+    ;
+// 	exception catch [RecognitionException ex] { handleParsingError(ex); }
+ 	
+/**
+ * Matches a "with" statement.
+ */
+withStatement[ContainerNode c]
+/*{
+	WithNode n = null; 
+	ExpressionNodeBase e = null; 
+	BlockNode b = null; 
+}*/
+	:   /*withT:*/TOKEN_KEYWORD_WITH /*e=*/statementParenExpression
+		/*{
+			n = new WithNode((ASToken)withT); 
+			n.setConditionalExpression(e);
+			c.addItem(n);
+			b = n.getContentsNode(); 
+		}*/
+    	substatement[b]
+	;
+
+/**
+ * Matches a "try...catch...finally" statement.
+ */
+tryStatement[ContainerNode c] 
+/*{
+	TryNode n = null; 
+	BlockNode b = null; 
+}*/
+ 	:   /*tryT:*/TOKEN_KEYWORD_TRY
+ 		/*{
+ 			n = new TryNode((ASToken)tryT);
+ 			b = n.getContentsNode();
+ 			c.addItem(n);
+ 		}*/
+ 		
+        block[b]
+        
+        (   options { greedy=true;}: 
+            catchBlock[n]
+        )*
+
+        (   options { greedy=true;}: 
+            /*finallyT:*/TOKEN_KEYWORD_FINALLY
+            /*{
+            	TerminalNode t = new TerminalNode((ASToken)finallyT);
+            	n.addFinallyBlock(t);
+            	b = t.getContentsNode();
+            }*/
+            block[b]
+        )?
+ 	;  
+
+/**
+ * Matches the "catch" block in a "try" statement.
+ */
+catchBlock[TryNode tryNode]
+/*{
+	CatchNode n = null; 
+	ParameterNode arg = null; 
+	BlockNode b = null; 
+}*/
+	:   /*catchT:*/TOKEN_KEYWORD_CATCH TOKEN_PAREN_OPEN
+		/*{ disableSemicolonInsertion(); }*/
+
+	    /*arg=*/catchBlockArgument
+		/*{
+			n = new CatchNode(arg); 
+			tryNode.addCatchClause(n);
+			b = n.getContentsNode();
+			n.startBefore(catchT); 
+		}*/
+
+		(   /*rpT:*/TOKEN_PAREN_CLOSE
+			/*{
+				enableSemicolonInsertion();
+				n.endAfter(rpT);
+			}*/
+			
+// 			exception catch [RecognitionException ex] {handleParsingError(ex);  enableSemicolonInsertion(); }
+ 		)
+ 		
+	    block[b]
+	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches the argument in the "try...catch(arg)" statement.
+ */
+catchBlockArgument returns [ParameterNode p]
+/*{
+	p = null; 
+	IdentifierNode name = null; 
+	ExpressionNodeBase t = null; 
+}*/
+	:   /*name=*/identifier
+		/*{ p = new ParameterNode(name); }*/
+		
+		(   /*colonT:*/TOKEN_COLON
+			/*{ p.setType((ASToken)colonT, null); }*/
+			/*t=*/type
+			/*{ p.setType((ASToken)colonT, t); }*/
+		)?
+	;	
+//	exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches an "if" statement.
+ */
+ifStatement[ContainerNode c]
+/*{
+	IfNode i = null; 
+	ExpressionNodeBase cond = null; 
+	ContainerNode b = null; 
+	boolean hasElse = false; 
+}*/
+	:   /*ifT:*/TOKEN_KEYWORD_IF cond=statementParenExpression
+		/*{
+			i = new IfNode((ASToken)ifT);
+			ConditionalNode cNode = new ConditionalNode((ASToken)ifT);			
+			cNode.setConditionalExpression(cond);
+			b = cNode.getContentsNode();
+			i.addBranch(cNode);
+			c.addItem(i);
+		}*/
+		innerSubstatement[b]
+	
+		(options{greedy=true;}: 
+            /*hasElse=*/elsePart[i]
+			/*{ if (hasElse == true) return; }*/
+		)*
+	;
+// 	exception catch [RecognitionException ex] { handleParsingError(ex); }
+ 	
+/**
+ * Matches the optional "else" block of an "if" statement.
+ *
+ * @return true if there is an "else" block.
+ */
+elsePart[IfNode i] returns [boolean hasElse]
+/*{
+	hasElse = false; 
+	ContainerNode b = null; 
+	ExpressionNodeBase cond = null; 
+	ConditionalNode elseIf = null; 
+}*/
+	
+	:   /*elseT:*/TOKEN_KEYWORD_ELSE
+		(options{greedy=true;}: 
+            TOKEN_KEYWORD_IF /*cond=*/statementParenExpression
+			/*{
+		    	elseIf = new ConditionalNode((ASToken) elseT);
+		    	elseIf.setConditionalExpression(cond);
+		    	i.addBranch(elseIf);
+				b = elseIf.getContentsNode();
+			}*/
+		)?
+		
+		/*{
+			if (elseIf == null){
+				hasElse = true;
+				TerminalNode t = new TerminalNode((ASToken) elseT);
+				i.addBranch(t);
+				b = t.getContentsNode();
+			}
+		}*/
+		substatement[b]
+	;
+//	exception catch [RecognitionException ex] {handleParsingError(ex);  }
+	
+/**
+ * Matches a "switch" statement.
+ */
+switchStatement[ContainerNode c]
+/*{
+	SwitchNode sw = null; 
+	ExpressionNodeBase e = null; 
+}*/
+ 	:   /*switchT:*/TOKEN_KEYWORD_SWITCH /*e=*/statementParenExpression
+ 		/*{
+			sw = new SwitchNode((ASToken)switchT);			
+			c.addItem(sw);
+			if(e != null)
+				sw.setConditionalExpression(e);
+ 		}*/
+ 
+ 	    cases[sw]
+ 	;
+
+/**
+ * Matches the "case" block in a "switch" statement.
+ */
+cases[SwitchNode sw]
+/*{
+	final ContainerNode b = sw.getContentsNode(); 
+}*/
+    :   TOKEN_BLOCK_OPEN caseClauses[b] TOKEN_BLOCK_CLOSE
+	;
+
+/**
+ * Matches the "case" clauses in a "switch" statement.
+ */
+caseClauses[ContainerNode swb]
+ 	:    (caseClause[swb])*	
+ 	;
+
+/**
+ * Matches a single "case" clause in a "switch" statement.
+ */ 	
+caseClause[ContainerNode swb]
+/*{
+	ExpressionNodeBase e = null; 
+	ContainerNode b = null; 
+}*/
+ 	:   /*caseT:*/TOKEN_KEYWORD_CASE /*e=*/expression colon
+ 		/*{
+ 			ConditionalNode cond = new ConditionalNode((ASToken) caseT);
+ 			cond.setConditionalExpression(e);
+ 		 	swb.addItem(cond);
+ 		 	b = cond.getContentsNode(); 
+ 		}*/
+ 		caseStatementList[b]
+ 		
+ 	|   /*defaultT:*/TOKEN_KEYWORD_DEFAULT colon
+ 		/*{
+ 			TerminalNode t = new TerminalNode((ASToken)defaultT);
+ 			swb.addItem(t);
+ 			b = t.getContentsNode();
+ 		}*/
+ 		caseStatementList[b]
+ 	;
+// 	exception catch [RecognitionException ex] {handleParsingError(ex);  }
+
+/**
+ * Matches a colon token ":" or recover from a missing colon.
+ */
+colon
+	:	TOKEN_COLON
+	;
+// 	exception catch [RecognitionException ex] { addProblem(unexpectedTokenProblem(LT(1), ASTokenKind.COLON)); }
+
+/**
+ * Matches the statements in a "case" clause.
+ */ 	 
+caseStatementList[ContainerNode b]
+ 	:   (directive[b, TOKEN_BLOCK_CLOSE])*
+ 	;
+// 	exception catch [RecognitionException ex] {handleParsingError(ex);  }
+ 
+/**
+ * Matches an identifier token. An identifier can come from different token
+ * types such as: 
+ *
+ *   - IDENTIFIER
+ *   - namespace
+ *   - get 
+ *   - set
+ *
+ * This is because in AS3, these elements are not reserved keyword. However they
+ * have special meaning in some syntactic contexts.
+ * See "AS3 syntax spec - 3.5 Keywords and Punctuators" for details.
+ */
+identifier returns [IdentifierNode n]
+/*{
+    n = null;  
+    final ASToken token = LT(1);
+}*/
+    :   (	TOKEN_IDENTIFIER 
+    	|	TOKEN_RESERVED_WORD_NAMESPACE 
+    	|	TOKEN_RESERVED_WORD_GET 
+    	| 	TOKEN_RESERVED_WORD_SET 
+    	)
+		/*{ n = new IdentifierNode(token); }*/
+    ;
+/*    exception
+    catch [NoViableAltException e1] { n = expectingIdentifier(e1); }
+    catch [RecognitionException e2] { n = handleMissingIdentifier(e2); }*/
+    
+/**
+ * Matches an "import-able" name.
+ *
+ *     flash.display.Sprite;
+ *     flash.events.*;
+ */    
+importName returns [ExpressionNodeBase n]
+/*{
+	n=null; 
+	ExpressionNodeBase e = null;
+}*/
+	
+	: 	/*n=*/packageName
+		(	/*dot:*/TOKEN_OPERATOR_MEMBER_ACCESS
+			/*{
+				n = new FullNameNode(n, (ASToken) dot, null); 
+			}*/
+			/*e=*/starLiteral
+			/*{
+				((FullNameNode)n).setRightOperandNode(e);
+			}*/
+		)?
+	;
+//	exception catch [RecognitionException ex] { return handleMissingIdentifier(ex, n); }
+
+/**
+ * Matches a restricted name. For example:
+ *
+ *     my.package.name.Clock;
+ *     private::myPrivateVar;
+ *     UnqualifiedTypeClock;
+ *
+ */
+restrictedName returns [ExpressionNodeBase ne]
+/*{
+    nameExpression = null;
+ 	IdentifierNode placeHolderRightNode = null;
+    ASToken opToken = null;
+    ExpressionNodeBase part = null;
+}*/
+    :   /*nameExpression=*/restrictedNamePart
+    	
+    	// LL(1) grammar can only branch on the next token. 
+        // The LA(2) semantic predicate is used to disambiguate:
+        // 1. "foo.bar" - a restricted name consisting two identifiers
+        // 2. "foo.(bar)" - a member expression whose left-hand side is an identifier
+        //                  and the right-hand side is a parenthesis expression
+        (options { greedy=true; }: { _input.LA(2) != TOKEN_PAREN_OPEN }?
+            /*{
+                opToken = LT(1); 
+                
+                // The place-holder node is a safe-net in case parsing the 
+                // "right" node fails, so that we will still have a balanced
+                // FullNameNode.
+                placeHolderRightNode = IdentifierNode.createEmptyIdentifierNodeAfterToken(opToken);
+                
+                final ExpressionNodeBase nameLeft = nameExpression;
+            }*/
+            (   TOKEN_OPERATOR_MEMBER_ACCESS 
+                /*{ nameExpression = new FullNameNode(nameLeft, opToken, placeHolderRightNode); }*/
+            |   TOKEN_OPERATOR_NS_QUALIFIER 
+                /*{ nameExpression = new NamespaceAccessExpressionNode(nameLeft, opToken, placeHolderRightNode); }*/
+            )
+            
+            (	{ opToken.getType() == TOKEN_OPERATOR_NS_QUALIFIER && _input.LA(1) == TOKEN_SQUARE_OPEN }?
+                // matches ns::["var_in_ns"]
+            	/*nameExpression=*/bracketExpression[nameLeft]
+	        |   /*part=*/restrictedNamePart
+	            /*{
+	            	((BinaryOperatorNodeBase)nameExpression).setRightOperandNode(part);
+	            	checkForChainedNamespaceQualifierProblem(opToken, part);
+	        	}*/
+        	)
+        )*
+    ;
+/*	exception catch [RecognitionException ex]
+	{  
+	   if (nameExpression == null)
+	       nameExpression = handleMissingIdentifier(ex); 
+       else
+           consumeParsingError(ex);
+    }*/
+
+    
+/**
+ * Matches the identifier part of a restricted name. For example:
+ * 
+ *     private
+ *     public
+ *     foo
+ *     MyType
+ *
+ */
+restrictedNamePart returns [IdentifierNode id]
+/*{
+    id = null;
+    final ASToken lt = LT(1);
+}*/
+    :   /*id=*/identifier
+    |   TOKEN_NAMESPACE_NAME 
+        /*{ id = new IdentifierNode(lt); }*/
+    |   TOKEN_KEYWORD_SUPER
+        /*{ id = LanguageIdentifierNode.buildSuper(lt); }*/
+    ;
+    // "identifier", "namespace name" and "super" are all "identifiers" to
+    // the user. So we override the default error handling in order to emit
+    // "expecting identifier but found ..." syntax problem.
+//    exception catch [NoViableAltException ex] { id = expectingIdentifier(ex); }
+
+/**
+ * Keep legacy rule for Falcon-JS.
+ */
+typedNameOrStar returns [ExpressionNodeBase n]
+    :    /*n=*/type
+    ;
+    
+/**
+ * Matches a type reference.
+ *
+ *     String
+ *     int
+ *     *
+ *     Vector.<Clock>
+ *     foo.bar.Vector.<T>
+ *
+ */
+type returns [ExpressionNodeBase n]
+/*{
+    n = null; 
+}*/
+    :   /*n=*/starLiteral
+    |   /*n=*/restrictedName ( /*n=*/typeApplication[n] )?
+    ;	
+//    exception catch [RecognitionException ex] { n = handleMissingIdentifier(ex); }
+  
+/**
+ * Matches a "type application" part>
+ *
+ *     .<String>
+ *     .<Clock>
+ *     .<uint>
+ *
+ */
+typeApplication [ExpressionNodeBase root] returns[TypedExpressionNode n]
+/*{
+    n = null; 
+    ExpressionNodeBase t = null; 
+    Token closeT = null;
+    enterTypeApplication(root);
+}*/
+    :   /*openT:*/TOKEN_TYPED_COLLECTION_OPEN
+        /*t=*/type
+        /*{
+            n = new TypedExpressionNode(root, t, (ASToken)openT);
+            closeT = LT(1);
+        }*/
+        ( TOKEN_TYPED_COLLECTION_CLOSE | TOKEN_OPERATOR_GREATER_THAN )
+        /*{ n.endAfter(closeT); }*/
+    ; 
+//    exception catch [RecognitionException ex] { consumeParsingError(ex); }
+
+
+/**
+ * Matches an optional expression.
+ * @return NilNode or ExpressionNodeBase.
+ */	 		
+optExpression returns[ExpressionNodeBase e]
+/*{
+	e = null; 
+}*/
+	:   (options{greedy=true;}: /*e=*/expression)?
+		/*{ if (e == null) e = new NilNode(); }*/
+	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex); }
+		
+/**
+ * Matches an expression or a comma-separated expression list.
+ */
+expression returns [ExpressionNodeBase n]
+/*{
+    n = null; 
+    ExpressionNodeBase e1 = null; 
+}*/
+    :   /*n=*/assignmentExpression
+    	(options{greedy=true;}: 
+            /*op:*/TOKEN_COMMA
+            /*e1=*/assignmentExpression
+            /*{ n = BinaryOperatorNodeBase.create((ASToken)op,n,e1); }*/
+    	)*
+    ;	
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches an "assignment expression".
+ *
+ * According to ASL sytax spec, the productions for an "assignment expression"
+ * is either a "conditional expression" or a "left-hand side expression" followed
+ * by an "assignment operator" and an "assignment expression". However, since
+ * "assignmentExpression" and "conditionaExpression" is ambiguous at indefinite 
+ * look-ahead distance, this LL(1) grammar can't decide which alternative to
+ * choose. As a result, the implementation is more lenient in that an AST node
+ * for an assignment binary node will be built even the left-hand side expression
+ * is not a valid "LeftHandSideExpression", such as a constant.
+ * 
+ * For example:
+ * <code>100 = "hello";</code>
+ * This statement will be parsed without syntax error, generating tree like:
+ * <pre>
+ *        =
+ *       / \
+ *    100  "hello"
+ * </pre>
+ *
+ * A possible solution to this is to find out the difference between "conditional
+ * expression" and "left-hand side expression", then insert a semantic predicate
+ * before matching a "assignment operator".
+ */
+assignmentExpression returns [ExpressionNodeBase n]
+/*{
+	n = null; 
+	ASToken op = null; 
+	ExpressionNodeBase r = null;
+}*/
+	:   /*n=*/condExpr
+		(options{greedy=true;}: 
+		    /*op=*/assignOp
+		    /*r=*/assignmentRightValue
+	        /*{ n = BinaryOperatorNodeBase.create(op,n,r); }*/
+		)?
+	;
+	
+/**
+ * Matches the right-hand side of an assignment expression.
+ * "public" namespace is allowed as an R-value for backward compatibility.
+ * @see "CMP-335 and ASLSPEC-19"
+ */
+assignmentRightValue returns [ExpressionNodeBase rightExpr]
+/*{
+	rightExpr = null;
+}*/
+    :   { isNextTokenPublicNamespace() }? /*p:*/TOKEN_NAMESPACE_ANNOTATION
+        /*{ rightExpr = new NamespaceIdentifierNode((ASToken)p); }*/
+    |   /*rightExpr=*/assignmentExpression
+    ;
+	
+assignOp returns [ASToken op]
+/*{
+	op = LT(1); 
+}*/
+    :   TOKEN_OPERATOR_ASSIGNMENT 
+    |   TOKEN_OPERATOR_LOGICAL_AND_ASSIGNMENT
+    |   TOKEN_OPERATOR_LOGICAL_OR_ASSIGNMENT
+    |   TOKEN_OPERATOR_PLUS_ASSIGNMENT
+    |   TOKEN_OPERATOR_MINUS_ASSIGNMENT
+    |   TOKEN_OPERATOR_MULTIPLICATION_ASSIGNMENT
+    |   TOKEN_OPERATOR_DIVISION_ASSIGNMENT
+    |   TOKEN_OPERATOR_MODULO_ASSIGNMENT
+    |   TOKEN_OPERATOR_BITWISE_AND_ASSIGNMENT
+    |   TOKEN_OPERATOR_BITWISE_OR_ASSIGNMENT
+    |   TOKEN_OPERATOR_BITWISE_XOR_ASSIGNMENT
+    |   TOKEN_OPERATOR_BITWISE_LEFT_SHIFT_ASSIGNMENT
+    |   TOKEN_OPERATOR_BITWISE_RIGHT_SHIFT_ASSIGNMENT
+    |   TOKEN_OPERATOR_BITWISE_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT
+    ;
+
+/**
+ * Matches a ternary expression such as: 
+ *
+ *     (x > 2) ? "greater" : "smaller"
+ */		
+condExpr returns [ExpressionNodeBase n]
+/*{
+    n = null; 
+    ExpressionNodeBase trueExpr = null; 
+    ExpressionNodeBase falseExpr = null;
+    TernaryOperatorNode ternary = null;
+}*/
+	:   /*n=*/binaryExpr
+        (   /*op:*/TOKEN_OPERATOR_TERNARY
+            /*{
+                ternary = new TernaryOperatorNode((ASToken)op,n,null,null);
+                n = ternary; 
+            }*/
+            /*trueExpr=*/assignmentExpression   /*{ ternary.setLeftOperandNode(trueExpr); }*/
+            TOKEN_COLON 
+            /*falseExpr=*/assignmentExpression  /*{ ternary.setRightOperandNode(falseExpr); }*/
+        )?
+//        exception catch [RecognitionException ex] { handleParsingError(ex); }
+	;
+	
+/**
+ * Binary expression uses operator precedence parser in BaseASParser.
+ */
+binaryExpr returns [ExpressionNodeBase n]
+/*{
+	n = precedenceParseExpression(4);
+	if (true)	return n;
+}*/
+	: fakeExpr
+	;
+	
+/**
+ * fakeExpr simulates the set of allowable follow tokens in an expression context, which allows antlr to function.
+ * It is unreachable.
+ */
+fakeExpr
+/*{
+	ExpressionNodeBase n = null; 
+}*/
+	:	/*n=*/unaryExpr (options{greedy=true;}: binaryOperators fakeExpr)?
+	;
+	
+/**
+ * Declares all the binary operators.
+ */
+binaryOperators
+    :   TOKEN_OPERATOR_LOGICAL_OR 
+    |   TOKEN_OPERATOR_LOGICAL_AND
+    |   TOKEN_OPERATOR_BITWISE_OR 
+    |   TOKEN_OPERATOR_BITWISE_XOR 
+    |   TOKEN_OPERATOR_BITWISE_AND
+    |   TOKEN_OPERATOR_EQUAL 
+    |   TOKEN_OPERATOR_NOT_EQUAL 
+    |   TOKEN_OPERATOR_STRICT_EQUAL 
+    |   TOKEN_OPERATOR_STRICT_NOT_EQUAL
+    |   TOKEN_OPERATOR_GREATER_THAN 
+    |   TOKEN_OPERATOR_GREATER_THAN_EQUALS
+    |   TOKEN_OPERATOR_LESS_THAN 
+    |   TOKEN_OPERATOR_LESS_THAN_EQUALS
+    |   TOKEN_KEYWORD_INSTANCEOF
+    |   TOKEN_KEYWORD_IS 
+    |   TOKEN_KEYWORD_AS 
+    |   TOKEN_KEYWORD_IN
+    |   TOKEN_OPERATOR_BITWISE_LEFT_SHIFT 
+    |   TOKEN_OPERATOR_BITWISE_RIGHT_SHIFT 
+    |   TOKEN_OPERATOR_BITWISE_UNSIGNED_RIGHT_SHIFT
+    |   TOKEN_OPERATOR_MINUS 
+    |   TOKEN_OPERATOR_PLUS
+    |   TOKEN_OPERATOR_DIVISION 
+    |   TOKEN_OPERATOR_MODULO 
+    |   TOKEN_OPERATOR_STAR
+	;	
+
+/**
+ * Matches a "prefix expression".
+ *
+ *     delete x[i]
+ *     ++i
+ *     --i
+ *
+ * The distinction between this rule and "unary expression" makes the parser
+ * more strict about what expressions can follow what tokens.
+ */
+prefixExpression returns [ExpressionNodeBase n]
+/*{
+	n = null;
+	final ASToken op = LT(1);
+}*/
+	:	/*n=*/postfixExpr
+	|	(	TOKEN_KEYWORD_DELETE /*n=*/postfixExpr
+	    |   TOKEN_OPERATOR_INCREMENT /*n=*/lhsExpr
+	    |   TOKEN_OPERATOR_DECREMENT /*n=*/lhsExpr
+	    )
+        /*{
+	    	if (n == null)
+	            n = IdentifierNode.createEmptyIdentifierNodeAfterToken(op);
+	    	n = UnaryOperatorNodeBase.createPrefix(op, n); 
+    	}*/
+	;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a "unary expression".
+ *
+ * This rule is called out of the precedence parser in BaseASParser.
+ * If you need to change the name of this rule, you'll also need to update 
+ * the base class.
+ */
+unaryExpr returns [ExpressionNodeBase n]
+/*{
+    n = null; 
+    ASToken op = null; 
+}*/
+    :   (   /*n=*/prefixExpression
+        |   /*op=*/unaryOp /*n=*/unaryExpr
+            /*{
+            	if (n == null)
+                    n = IdentifierNode.createEmptyIdentifierNodeAfterToken(op);
+            	n = UnaryOperatorNodeBase.createPrefix(op, n); 
+        	}*/
+        ) 
+        (options { greedy = true; }: 
+            /*n=*/propertyAccessExpression[n]
+        |   /*n=*/arguments[n]
+        )*
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a unary operator.
+ */
+unaryOp returns [ASToken op]
+/*{
+	op = LT(1);
+}*/
+    :   TOKEN_KEYWORD_VOID
+    |   TOKEN_KEYWORD_TYPEOF
+    |   TOKEN_OPERATOR_PLUS 
+    |   TOKEN_OPERATOR_MINUS 
+    |   TOKEN_OPERATOR_BITWISE_NOT 
+    |   TOKEN_OPERATOR_LOGICAL_NOT
+    ;
+	   
+/**
+ * Matches "Postfix Expression" such as: i++, i--
+ *
+ * Since ECMA semicolon insertion rule requires that if a "++" or "--" is not
+ * on the same line as its left-hand side expression, a semicolon is inserted
+ * before the "--" or "++" token. The side-effect of the inserted semicolon is
+ * to terminate the expression parsing at this point. As a result, we have to
+ * return "null" to stop parsing the expression. An upstream production will
+ * pickup the "--" or "++" by starting a new expression.
+ *
+ * A good test case for such situation would be:
+ *
+ *    var i = 99
+ *    ++i
+ *
+ * A semicolon should be inserted after "99", resulting in two separate ASTs
+ * for "var i=99" and "++i". Otherwise, "var i=99++" is a bad recognition.
+ */
+postfixExpr returns [ExpressionNodeBase n]
+/*{
+    n = null; 
+    boolean isSemicolonInserted = false;
+}*/
+	: /*n=*/lhsExpr
+	  /*{
+	      final ASToken nextToken = LT(1); 
+	      if (nextToken.getType() == ASTokenTypes.TOKEN_OPERATOR_INCREMENT ||
+	          nextToken.getType() == ASTokenTypes.TOKEN_OPERATOR_DECREMENT)
+	          isSemicolonInserted = beforeRestrictedToken(nextToken);
+      }*/
+      (   {!isSemicolonInserted}? (options{greedy=true;}: /*n=*/postfixOp[n])?
+      |   // Do nothing if optional semicolon is inserted.
+          // This empty alternative is required because otherwise a semantic 
+          // predicate exception will be thrown, leading the code enter error 
+          // handling, which will create incorrect tree shape.
+      )
+	;
+
+/**
+ * Matches a "postfix" operator such as: ++, --
+ * The parameter "n" is the expression the postfix operator acts on.
+ * The return value "top" is a UnaryOperatorNode.
+ */ 
+postfixOp[ExpressionNodeBase n] returns [UnaryOperatorNodeBase top]
+/*{
+    final ASToken op = LT(1); 
+    top = null;
+}*/
+	:  ( TOKEN_OPERATOR_INCREMENT 
+	   | TOKEN_OPERATOR_DECREMENT )
+       /*{ top = UnaryOperatorNodeBase.createPostfix(op, n); }*/
+	;
+
+/**
+ * Matches a primary expression.
+ */ 
+primaryExpression returns [ExpressionNodeBase n]
+/*{
+    n = null;  
+    ASToken token = LT(1);
+}*/
+    :   TOKEN_KEYWORD_NULL
+        /*{ n = new LiteralNode(token, LiteralType.NULL); }*/
+    |   TOKEN_KEYWORD_TRUE
+        /*{ n = new LiteralNode(token, LiteralType.BOOLEAN); }*/
+    |   TOKEN_KEYWORD_FALSE
+        /*{ n = new LiteralNode(token, LiteralType.BOOLEAN); }*/
+    |   TOKEN_KEYWORD_THIS
+        /*{ n = LanguageIdentifierNode.buildThis(token); }*/
+    |   token=numericLiteral
+        /*{ n = new NumericLiteralNode(token); }*/
+    |   TOKEN_LITERAL_STRING
+        /*{ n = new LiteralNode(token, LiteralType.STRING); }*/
+    |   TOKEN_VOID_0
+        /*{ n = new LiteralNode(token, LiteralType.OBJECT); }*/
+    |   TOKEN_LITERAL_REGEXP
+        /*{ n = new RegExpLiteralNode(token, this); }*/
+    |   /*{ n = new ArrayLiteralNode(); }*/ arrayInitializer[(ArrayLiteralNode)n]
+    |   /*n=*/objectLiteralExpression
+    |   /*n=*/xmlInitializer      /*{ leaveXMLLiteral(); }*/
+    |   /*n=*/xmlListInitializer  /*{ leaveXMLLiteral(); }*/
+    |   /*n=*/functionExpression
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+	
+/**
+ * Matches a numeric literal token.
+ */
+numericLiteral returns [ASToken op]
+/*{
+	op = LT(1); 
+}*/
+    :   TOKEN_LITERAL_NUMBER 
+    |   TOKEN_LITERAL_HEX_NUMBER
+	;
+	
+/**
+ * Matches an "object literal".
+ */
+objectLiteralExpression returns [ExpressionNodeBase n]
+/*{
+	ObjectLiteralNode o = new ObjectLiteralNode(); 
+	n = o; 
+	ContainerNode b = o.getContentsNode(); 
+	ExpressionNodeBase vp = null;
+}*/
+    :   /*openT:*/TOKEN_BLOCK_OPEN           /*{ n.startAfter(openT); }*/
+        (   /*vp=*/objectLiteralValuePair    /*{ b.addItem(vp); }*/
+      	    (   TOKEN_COMMA /*vp=*/objectLiteralValuePair
+    	        /*{ if (vp != null) b.addItem(vp); }*/
+//     		    exception catch [RecognitionException ex] { handleParsingError(ex); }
+      	    )*
+        )?		
+        /*closeT:*/TOKEN_BLOCK_CLOSE         /*{ n.endAfter(closeT); }*/
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a "field" in an "object literal".
+ * The "field" can be gated with a "config condition". If the condition is
+ * "false", return "null" value; Otherwise, return the expression node of the
+ * key/value pair.
+ */
+objectLiteralValuePair returns [ExpressionNodeBase n]
+/*{
+	ExpressionNodeBase v = null;  
+	n = null;            
+	boolean condition = true;   
+    ASToken numberT = null;     
+}*/
+    :   (   { isConfigCondition() && _input.LA(4) != TOKEN_COLON && _input.LA(4) != TOKEN_BLOCK_CLOSE }?
+            /*condition=*/configCondition
+        |   // Skip - no config varaible.
+        )
+        
+        // Field name:
+        (   /*nameT:*/TOKEN_IDENTIFIER
+        	/*{ n = new NonResolvingIdentifierNode(nameT != null ? nameT.getText() : "",nameT); }*/
+        |   /*numberT=*/numericLiteral
+        	/*{ n = new NumericLiteralNode(numberT); }*/
+        |   /*stringT:*/TOKEN_LITERAL_STRING
+        	/*{ n = new LiteralNode(LiteralType.STRING, stringT); }*/
+        )
+        
+        /*c:*/TOKEN_COLON
+        
+        // Field value:
+        /*v=*/assignmentExpression
+    	/*{
+    		if (condition)
+    		    n = new ObjectLiteralValuePairNode((ASToken)c,n,v); 
+		    else
+		        n = null;
+	    }*/
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex);  }
+ 
+
+/**
+ * Matches array literal. For example:
+ *
+ *    []
+ *    ["hello", 3.14, foo]
+ *    [ , x, y]
+ *    [ , ,]
+ *
+ * "Holes" (empty array elements) are allowed. See "arrayElements" rule for details.
+ */ 
+arrayInitializer [ArrayLiteralNode node] 
+/*    {
+        final ContainerNode contents = node.getContentsNode(); 
+    }*/
+    :   /*open:*/TOKEN_SQUARE_OPEN            /*{ contents.startAfter(open); }*/
+        arrayElements[contents]
+        /*close:*/TOKEN_SQUARE_CLOSE          /*{ contents.endBefore(close); }*/
+    ;	
+/*    exception catch [RecognitionException ex]
+    { 
+    	// Do not convert keywords to identifiers.
+    	// This is for recovering from:
+    	// [
+    	// var x:int;
+    	handleParsingError(ex); 
+    	// Notify the caller that the array literal failed.
+    	throw ex; 
+    }*/
+	
+/**
+ * Matches all the elements in an "arrayInitializer". For example:
+ *
+ *    x,y,z
+ *    x,,
+ *    (empty)
+ *    ,,,,,,
+ *
+ * "Holes" are compiled as "undefined".
+ * Leading "holes" are kept as "undefined" values.
+ * "Holes" in the middle are kept as "undefined" values.
+ * Trailing "holes" are kept as "undefined" values except that the last "hole"
+ * is dropped.
+ *
+ * For example: x=[,,1,,,2,,,] has 2 leading holes, 2 holes in the middle, and 3
+ * holes at the end. All the holes except for the last trailing holes are kept
+ * as undefined values:
+ *
+ * x[0]=undefined
+ * x[1]=undefined
+ * x[2]=1
+ * x[3]=undefined
+ * x[4]=undefined
+ * x[5]=2
+ * x[6]=undefined
+ * x[7]=undefined
+ * (end)
+ *
+ */
+arrayElements[ContainerNode b]
+/*{
+    ExpressionNodeBase e = null;  
+}*/
+    :   ( TOKEN_COMMA /*{ b.addItem(new NilNode()); }*/ )*
+        (   { _input.LA(1) != TOKEN_SQUARE_CLOSE}?
+            	/*e=*/arrayElement /*{ b.addItem(e); }*/
+                (   TOKEN_COMMA 
+                    (   { _input.LA(1) != TOKEN_SQUARE_CLOSE && _input.LA(1) != TOKEN_COMMA }? /*e=*/arrayElement /*{ b.addItem(e); }*/
+
+                    |   { _input.LA(1) != TOKEN_SQUARE_CLOSE && _input.LA(1) == TOKEN_COMMA }? /*{ b.addItem(new NilNode()); }*/
+                    |   // Next token is "]" - pass.
+            	 	)
+//             		exception catch [RecognitionException ex] { handleParsingError(ex); }
+              	)*
+      	|    // Next token is "]" - the initializer is a list of commas: [,,,,,]
+      	)
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches an "array element" in an "array literal". An array element can be 
+ * gated with a config variable. If the config variable is false, the element
+ * will be matched as a "hole" in the array literal.
+ */
+arrayElement returns [ExpressionNodeBase e]
+/*{
+	e = null; 
+	boolean c = true;  // config variable
+}*/
+    :   (   { isConfigCondition() && _input.LA(4) != TOKEN_COMMA && _input.LA(4) != TOKEN_SQUARE_CLOSE }?
+            c=configCondition
+        |   // Skip - no config varaible.
+        )
+        /*e=*/assignmentExpression
+        /*{
+        	if (!c) 
+        	{
+        		final NilNode nilNode = new NilNode(); 
+        		nilNode.span(e, e);
+        		e = nilNode;
+    		}
+        }*/
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex);  }
+	
+/**
+ * Matches a "vector initializer".
+ */
+vectorLiteralExpression returns [VectorLiteralNode node] 
+/*{
+	node = new VectorLiteralNode(); 
+	ContainerNode b = node.getContentsNode(); 
+	ExpressionNodeBase type = null; 
+}*/
+	:   /*open:*/TOKEN_TYPED_LITERAL_OPEN      /*{ node.endAfter(open); }*/
+	 	/*type=*/type                          /*{ node.setCollectionTypeNode(type); }*/
+        /*close:*/TOKEN_TYPED_LITERAL_CLOSE    /*{ node.endAfter(close); }*/
+        /*openT:*/TOKEN_SQUARE_OPEN            /*{ b.startAfter(openT); }*/
+	 	(vectorLiteralContents[b])?
+        /*closeT:*/TOKEN_SQUARE_CLOSE          /*{ b.endBefore(closeT); }*/
+	;
+//	exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a "vector element" in a vector initializer.
+ */
+vectorLiteralContents[ContainerNode b]
+/*{
+	ExpressionNodeBase e = null;  
+}*/
+    :   /*e=*/arrayElement       /*{ b.addItem(e); }*/
+        (   TOKEN_COMMA
+            /*{
+                //  A trailing comma is allowed, but 
+                //  an intermediate comma is not.
+                if ( LA(1) != TOKEN_SQUARE_CLOSE ){
+                    e=arrayElement();
+                    b.addItem(e); 
+                }
+    	 	}*/
+//            exception catch [RecognitionException ex] { handleParsingError(ex); }
+      	)*
+    ;
+
+/**
+ * Matches "XML literal expression".
+ */
+xmlInitializer returns [XMLLiteralNode n]
+/*{
+	n = new XMLLiteralNode(); 
+	final ASToken lt = LT(1);
+	enterXMLLiteral();
+}*/
+    :   { _input.LA(1) == TOKEN_E4X_COMMENT ||
+    	  _input.LA(1) == TOKEN_E4X_CDATA ||
+    	  _input.LA(1) == TOKEN_E4X_PROCESSING_INSTRUCTION
+    	}? 
+        xmlMarkup
+        /*{ n.appendLiteralToken(lt); }*/
+        xmlWhitespace[n]
+    |   (options { greedy = true; }: xmlElementContent[n] )+
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+    
+/**
+ * Match XML whitespace tokens. If {@code ContainerNode} is null, drop the
+ * whitespace tokens.
+ */
+xmlWhitespace [BaseLiteralContainerNode n]
+    :   (options { greedy = true; }: 
+	        /*ws:*/TOKEN_E4X_WHITESPACE
+            /*{
+            	if (n != null) 
+            	    n.appendLiteralToken((ASToken)ws); 
+    	    }*/
+        )*
+	;
+    
+/**
+ * Matches an XML comment, XML CDATA or XML PI token.
+ */
+xmlMarkup
+    :   TOKEN_E4X_COMMENT
+    |   TOKEN_E4X_CDATA
+    |   TOKEN_E4X_PROCESSING_INSTRUCTION
+    ;    
+       
+/**
+ * Matches an E4X token that can be aggregated in "xmlTokenAggregated".
+ * Instead of a full recursive descent parser for XML tags, the base class
+ * uses a tag name stack to check matching tags. A complete parse tree with
+ * XML structure is unnecessary and adds extra overhead to the parser.
+ */
+xmlToken [BaseLiteralContainerNode n]
+/*{
+	final ASToken t = LT(1);
+}*/
+    :   (   xmlMarkup
+        |   TOKEN_E4X_WHITESPACE 
+        |   TOKEN_E4X_ENTITY
+        |   TOKEN_E4X_DECIMAL_ENTITY
+        |   TOKEN_E4X_HEX_ENTITY 
+        |   TOKEN_E4X_TEXT
+        |   TOKEN_E4X_STRING
+        )
+        /*{ n.appendLiteralToken(t); }*/
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+    
+/**
+ * Matches an XML tag.
+ *
+ *     <foo>
+ *     </foo>
+ *     <foo />
+ *     <{name}>
+ *     <foo name={nameValue}>
+ *     <foo {attrs}>
+ */
+xmlTag [BaseLiteralContainerNode n]
+    :   (   /*openT:*/TOKEN_E4X_OPEN_TAG_START          // <foo
+            /*{
+            	xmlTagOpen((ASToken)openT); 
+                n.appendLiteralToken((ASToken)openT);
+        	}*/
+        |   /*closeT:*/TOKEN_E4X_CLOSE_TAG_START        // </foo
+            /*{
+            	xmlTagClose((ASToken)closeT); 
+                n.appendLiteralToken((ASToken)closeT);
+        	}*/
+        |   /*openNoNameT:*/HIDDEN_TOKEN_E4X            // <
+            /*{
+            	xmlTagOpenBinding((ASToken)openNoNameT); 
+                n.appendLiteralToken((ASToken)openNoNameT);
+        	}*/
+        	
+        	// Note about compatibility:
+        	// x = <  tagName foo="bar" />;
+        	//      ^
+        	// Whitespace isn't allowed here according to ASL spec.
+            // Avik from AS3 spec team confirmed it was a bug that the old ASC allowed it.
+
+        	(   xmlContentBlock[n]
+        	|   /*nT:*/TOKEN_E4X_NAME
+        	    /*{ n.appendLiteralToken((ASToken)nT); }*/
+        	)
+        )
+        xmlWhitespace[n]
+        (   ( xmlAttribute[n] | xmlContentBlock[n] )
+            xmlWhitespace[n]
+        )*
+        (   /*endT:*/TOKEN_E4X_TAG_END                  // >
+            /*{ n.appendLiteralToken((ASToken)endT); }*/
+        |   /*emptyEndT:*/TOKEN_E4X_EMPTY_TAG_END       // />
+            /*{
+            	xmlEmptyTagEnd((ASToken)emptyEndT); 
+                n.appendLiteralToken((ASToken)emptyEndT);
+            }*/
+        )
+    ;
+    
+/**
+ * Matches an XML attribute.
+ * 
+ *     name="value"
+ *     name='value'
+ *     name={value}
+ */
+xmlAttribute [BaseLiteralContainerNode n]
+    :   (   /*nT:*/TOKEN_E4X_NAME
+            /*{ n.appendLiteralToken((ASToken)nT); }*/
+        |   /*nsT:*/TOKEN_E4X_XMLNS
+            /*{ n.appendLiteralToken((ASToken)nsT); }*/
+        )
+        (   /*dT:*/TOKEN_E4X_NAME_DOT
+            /*{ n.appendLiteralToken((ASToken)dT); }*/
+            /*dnT:*/TOKEN_E4X_DOTTED_NAME_PART
+            /*{ n.appendLiteralToken((ASToken)dnT); }*/
+        )* 
+        xmlWhitespace[n]
+        /*eqT:*/TOKEN_E4X_EQUALS
+        /*{ n.appendLiteralToken((ASToken)eqT); }*/
+        xmlWhitespace[n]
+        (options { greedy = true; }:
+            /*strT:*/TOKEN_E4X_STRING
+            /*{ n.appendLiteralToken((ASToken)strT); }*/
+        |   /*eT:*/TOKEN_E4X_ENTITY
+            /*{ n.appendLiteralToken((ASToken)eT); }*/
+        |   /*hexT:*/TOKEN_E4X_HEX_ENTITY
+            /*{ n.appendLiteralToken((ASToken)hexT); }*/
+        |   xmlContentBlock[n]
+        )+
+    ;
+
+/**
+ * Matches an expression block in XML literals.
+ *
+ *    <foo>{ this.fooValue }</foo>
+ */
+xmlElementContent [BaseLiteralContainerNode n]
+    :   xmlToken[n] 
+    |   xmlContentBlock[n]
+    |   xmlTag[n]
+    ;
+    
+/**
+ * Matches an E4X XML list expression.
+ */
+xmlListInitializer returns [XMLListLiteralNode n]
+/*{
+	n = new XMLListLiteralNode(); 
+	enterXMLLiteral();
+}*/
+    :   /*xmlListT:*/TOKEN_LITERAL_XMLLIST
+    	/*{ n.getContentsNode().addItem(new LiteralNode(LiteralType.XML, xmlListT)); }*/
+        ( xmlElementContent[n] )*
+        /*closeT: */TOKEN_E4X_XMLLIST_CLOSE
+    	/*{ n.getContentsNode().addItem(new LiteralNode(LiteralType.XML, closeT)); }*/
+    	xmlWhitespace[null]
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a binding expression in an XML literal.
+ */
+xmlContentBlock[BaseLiteralContainerNode n]
+/*{
+	ExpressionNodeBase e = null; 
+}*/
+    :   TOKEN_E4X_BINDING_OPEN 
+        /*e=*/expression
+    	/*{
+            if(e != null) 
+                n.getContentsNode().addItem(e); 
+    	}*/
+        TOKEN_E4X_BINDING_CLOSE
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+    
+
+/**
+ * Matches a left-hand side (of asssignment) expression.
+ */
+lhsExpr returns [ExpressionNodeBase n]
+/*{
+	n = null;
+}*/
+    :   (   /*n=*/newExpression
+        |   /*n=*/parenExpression
+        |   /*n=*/nameExpression
+        |   /*n=*/primaryExpression
+        |   /*n=*/xmlAttributeName
+        )
+    	(options { greedy = true; }: 
+            /*n=*/propertyAccessExpression[n]
+        |   /*n=*/arguments[n]
+    	)*	
+    ;
+//	exception catch [RecognitionException ex] { handleParsingError(ex); }
+	
+/**
+ * Matches a member expression. See ASL syntax spec for details.
+ */
+memberExpression returns [ExpressionNodeBase n]
+    :   (   /*n=*/primaryExpression
+        |   /*n=*/parenExpression
+        |   /*n=*/propertyName
+        |   /*n=*/newExpression
+        )
+        ( options { greedy = true; }: /*n=*/propertyAccessExpression[n] )*
+    ;
+
+/**
+ * Matches a new expression. See ASL syntax spec for details.
+ */			
+newExpression returns[ExpressionNodeBase n]
+/*{
+	n = null; 
+}*/
+	:   /*newT:*/TOKEN_KEYWORD_NEW
+        (   { _input.LA(1) != TOKEN_KEYWORD_FUNCTION }?
+        	(   /*n=*/vectorLiteralExpression
+            |   /*n=*/memberExpression
+            )   
+            /*{
+                if (n == null) 
+                	n= handleMissingIdentifier(null); 
+            	else 
+            		n = FullNameNode.toMemberAccessExpressionNode(n);
+				n = new FunctionCallNode((ASToken)newT, n); 
+			}*/
+            (options{greedy=true;}: /*n=*/arguments[n])?
+        |   /*n=*/functionExpression  /*{ n = new FunctionCallNode((ASToken)newT, n); }*/
+        )
+/*		exception catch [RecognitionException ex] {
+			//if we have the 'new' keyword, but no expression, drop in a dummy identifier
+		    if(newT != null && n == null) {
+			    IdentifierNode identifier = handleMissingIdentifier(ex);
+			    if(identifier != null) {
+			        //if we're here, that means identifier fixup is turned on
+			        n = new FunctionCallNode((ASToken)newT, identifier);
+			    }
+			} else {
+			    handleParsingError(ex); 
+			}
+		}*/
+	;
+
+/**
+ * Matches an expression with parenthesis.
+ *
+ *     (id)
+ *     (1 + 2)
+ *     (name == "hello")
+ *
+ */
+parenExpression returns[ExpressionNodeBase n]
+/*{
+    n = null; 
+}*/
+    :   TOKEN_PAREN_OPEN /*n=*/expression TOKEN_PAREN_CLOSE
+	    /*{ if(n != null) n.setHasParenthesis(true); }*/
+    ;
+//    exception catch [RecognitionException ex] { handleParsingError(ex); }
+
+/**
+ * Matches a property name in a member expression.
+ */
+propertyName returns [ExpressionNodeBase n]
+/*{
+    n = null;
+}*/
+    :   /*n=*/starLiteral                 // *
+    |   /*n=*/restrictedName              // qualified & unqualified name
+    |   /*n=*/xmlAttributeName            // e4x attribute
+    ;
+    
+/**
+ * This is a non-greedy and non-aggregating version of "restricted name".
+ * It is defined in addition to "propertyName" in order to get correct
+ * precedence in the name expressions and expected tree shapes.
+ */
+nameExpression returns[ExpressionNodeBase n]
+/*	{ n = null; }*/
+	
+	: /*n=*/identifier
+	| /*n=*/starLiteral
+	| /*superT:*/TOKEN_KEYWORD_SUPER
+		/*{ n = LanguageIdentifierNode.buildSuper((IASToken)superT); }*/
+	| /*nsT:*/TOKEN_NAMESPACE_NAME
+		/*{
+			n = new NamespaceIdentifierNode((ASToken)nsT); 
+			((NamespaceIdentifierNode)n).setIsConfigNamespace(isConfigNamespace((NamespaceIdentifierNode)n));	
+		}*/
+	;	
+	
+	
+/**
+ * Matches an E4X attribute name. For example:
+ *  
+ *     "@*", @data, @[foo="hello"]
+ *
+ */
+xmlAttributeName returns [ExpressionNodeBase result]
+/*{
+    result = UnaryOperatorNodeBase.createPrefix(LT(1), null);
+    ExpressionNodeBase e = null;
+}*/
+    :   TOKEN_OPERATOR_ATSIGN
+        (	(   /*e=*/starLiteral
+	        |   /*e=*/identifier
+	        |   /*nsT:*/TOKEN_NAMESPACE_NAME     /*{ e = new NamespaceIdentifierNode((ASToken)nsT); }*/
+	        )
+	        /*{
+	        	((UnaryOperatorNodeBase)result).setExpression(e); 
+        	}*/
+        |   /*result=*/bracketExpression[result]
+        )
+    ;
+
+/**
+ * Matches a property access expression:
+ * For example: (assuming 

<TRUNCATED>