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 2016/04/18 15:32:01 UTC

[12/14] git commit: [flex-falcon] [refs/heads/feature/maven-migration-test] - Merge branches 'develop' and 'feature/maven-migration-test' of https://git-wip-us.apache.org/repos/asf/flex-falcon into feature/maven-migration-test

http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/beaf5b63/compiler/src/main/antlr/org/apache/flex/compiler/internal/parsing/as/ASParser.g
----------------------------------------------------------------------
diff --cc compiler/src/main/antlr/org/apache/flex/compiler/internal/parsing/as/ASParser.g
index 34cb240,0000000..4d4936b
mode 100644,000000..100644
--- a/compiler/src/main/antlr/org/apache/flex/compiler/internal/parsing/as/ASParser.g
+++ b/compiler/src/main/antlr/org/apache/flex/compiler/internal/parsing/as/ASParser.g
@@@ -1,3223 -1,0 +1,3223 @@@
 +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.
 + *
 + */
 +
 +package org.apache.flex.compiler.internal.parsing.as;
 +
 +/*
 + * 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.*;
 +
 +}
 +
 +/**
 + * 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;
 +}	
 +
 +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; 
 +}
 +
 +{
 +
 +    /**
 +     * 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, NO_END_TOKEN])*
 +    ;
 +    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);
 +}
 +    :   { la1 == TOKEN_BLOCK_OPEN }? groupDirective[c, endToken]
 +    |   { la1 == TOKEN_RESERVED_WORD_NAMESPACE && la2 == TOKEN_PAREN_OPEN }? statement[c, endToken] 
 +    |   { la1 == TOKEN_IDENTIFIER && la2 == TOKEN_NAMESPACE_ANNOTATION && lt1.getLine() == lt2.getLine() }?
 +        // Skip over the user-defined namespace name and continue.
 +        nsT:TOKEN_IDENTIFIER attributedDefinition[c]
 +        { trapInvalidNamespaceAttribute((ASToken)nsT); }
 +    |   asDocComment
 +    |   importDirective[c]
 +    |   useNamespaceDirective[c] 
 +    |   { la1 == TOKEN_NAMESPACE_NAME && 
 +    	  la2 == TOKEN_OPERATOR_NS_QUALIFIER && 
 +    	  la3 == TOKEN_IDENTIFIER && 
 +    	  la4 == TOKEN_BLOCK_OPEN}?
 +        // ns::var { ... }
 +        groupDirectiveWithConfigVariable[c, endToken]
 +    |   { la1 == TOKEN_NAMESPACE_NAME &&
 +    	  la2 == TOKEN_OPERATOR_NS_QUALIFIER &&
 +    	  la3 == TOKEN_NAMESPACE_ANNOTATION }?
 +        // ns::var private var foo:int;
 +        attributedDefinition[c]  
 +    |   { la1 == TOKEN_NAMESPACE_NAME &&
 +    	  la2 == 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(new NamespaceIdentifierNode((ASToken)ns), (ASToken) op, new IdentifierNode((ASToken)id));
 +        }
 +    ;
 +    
 +/**
 + * 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(new NamespaceIdentifierNode((ASToken)ns), (ASToken) op, new IdentifierNode((ASToken)id));
 +        }
 +    ;
 +    
 +/**
 + * 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
 +    |   { la1 == TOKEN_IDENTIFIER && la2 == TOKEN_COLON }? labeledStatement[c, exitCondition]
 +    |   { la1 != TOKEN_SQUARE_OPEN && 
 +    	  la1 != TOKEN_OPERATOR_LESS_THAN && 
 +    	  la1 != 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]
 +    :   (   { LA(1) != TOKEN_BLOCK_OPEN }? statement[c,NO_END_TOKEN]
 +        |   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);
 +        }
 +        (   { LA(1) == TOKEN_RESERVED_WORD_NAMESPACE && 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:TOKEN_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(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;}: { 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.startBefore(lpT);
 +		}
 +    	formalParameters[p]
 +    	rpT:TOKEN_PAREN_CLOSE
 + 		{ p.endAfter(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();
 +}
 +    :   { 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;}:
 +	        	{ LA(2) != TOKEN_PAREN_OPEN}? getT:TOKEN_RESERVED_WORD_GET
 +        	|   { 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.startBefore(lpT);
 + 		}
 +     	formalParameters[parameters]	
 +     	(	rpT:TOKEN_PAREN_CLOSE 
 +     		{ parameters.endAfter(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 nameExpression]
 +{
 +    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; }: { 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 && 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.startBefore(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() && LA(4) != TOKEN_COLON && 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.startBefore(open); }
++    :   open:TOKEN_SQUARE_OPEN            { node.startBefore(open); contents.startAfter(open); }
 +        arrayElements[contents]
-         close:TOKEN_SQUARE_CLOSE          { contents.endAfter(close); }
++        close:TOKEN_SQUARE_CLOSE          { node.endAfter(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()); } )*
 +        (   { LA(1) != TOKEN_SQUARE_CLOSE}?   
 +            	e=arrayElement { b.addItem(e); /*1*/ }
 +                (   TOKEN_COMMA 
 +                    (   { LA(1) != TOKEN_SQUARE_CLOSE && LA(1) != TOKEN_COMMA }? e=arrayElement { b.addItem(e); /*2*/}
 +                    |   { LA(1) != TOKEN_SQUARE_CLOSE && 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() && LA(4) != TOKEN_COMMA && 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();
 +}
 +    :   { LA(1) == TOKEN_E4X_COMMENT || 
 +    	  LA(1) == TOKEN_E4X_CDATA || 
 +    	  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]
 +        (   ( { isXMLAttribute() }? 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}
 + *     {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); }
 +        |   xmlAttributeBlock[n]
 +        ) 
 +        (   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 binding expression in an XML literal attribute name.
 + */
 +xmlAttributeBlock[BaseLiteralContainerNode n]
 +{ 
 +	ExpressionNodeBase e = null; 
 +}
 +    :   TOKEN_E4X_BINDING_OPEN 
 +        e=lhsExpr 
 +    	{ 
 +            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 
 +        (   { 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((NamespaceIdentifie

<TRUNCATED>