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>

Reply via email to