/*
 *
 *  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.royale.compiler.internal.parsing.as;

import static org.apache.royale.compiler.common.ISourceLocation.UNKNOWN;
import static org.apache.royale.compiler.internal.parsing.as.ASTokenTypes.*;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;

import org.apache.royale.abc.semantics.ECMASupport;
import org.apache.royale.compiler.parsing.GenericTokenStream;
import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.compiler.parsing.IASToken.ASTokenKind;
import org.apache.royale.compiler.problems.InvalidConfigLocationProblem;
import org.apache.royale.compiler.problems.NonConstConfigVarProblem;
import org.apache.royale.compiler.problems.ShadowedConfigNamespaceProblem;

import org.apache.commons.io.IOUtils;

import antlr.ANTLRException;
import antlr.LLkParser;
import antlr.MismatchedTokenException;
import antlr.NoViableAltException;
import antlr.ParserSharedInputState;
import antlr.RecognitionException;
import antlr.Token;
import antlr.TokenBuffer;
import antlr.TokenStream;
import antlr.TokenStreamException;

import org.apache.royale.compiler.asdoc.IASDocComment;
import org.apache.royale.compiler.asdoc.IASParserASDocDelegate;
import org.apache.royale.compiler.common.IFileSpecificationGetter;
import org.apache.royale.compiler.common.ISourceLocation;
import org.apache.royale.compiler.common.SourceLocation;
import org.apache.royale.compiler.config.CompilerDiagnosticsConstants;
import org.apache.royale.compiler.constants.IASKeywordConstants;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.constants.IMetaAttributeConstants;
import org.apache.royale.compiler.filespecs.IFileSpecification;
import org.apache.royale.compiler.internal.filespecs.StringFileSpecification;
import org.apache.royale.compiler.internal.parsing.TokenBase;
import org.apache.royale.compiler.internal.scopes.ASScope;
import org.apache.royale.compiler.internal.semantics.PostProcessStep;
import org.apache.royale.compiler.internal.tree.as.ArrayLiteralNode;
import org.apache.royale.compiler.internal.tree.as.BaseDefinitionNode;
import org.apache.royale.compiler.internal.tree.as.BinaryOperatorNodeBase;
import org.apache.royale.compiler.internal.tree.as.BlockNode;
import org.apache.royale.compiler.internal.tree.as.ClassNode;
import org.apache.royale.compiler.internal.tree.as.ConfigConstNode;
import org.apache.royale.compiler.internal.tree.as.ConfigExpressionNode;
import org.apache.royale.compiler.internal.tree.as.ContainerNode;
import org.apache.royale.compiler.internal.tree.as.EmbedNode;
import org.apache.royale.compiler.internal.tree.as.ExpressionNodeBase;
import org.apache.royale.compiler.internal.tree.as.FileNode;
import org.apache.royale.compiler.internal.tree.as.FullNameNode;
import org.apache.royale.compiler.internal.tree.as.FunctionNode;
import org.apache.royale.compiler.internal.tree.as.FunctionObjectNode;
import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
import org.apache.royale.compiler.internal.tree.as.ImportNode;
import org.apache.royale.compiler.internal.tree.as.LiteralNode;
import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
import org.apache.royale.compiler.internal.tree.as.ModifierNode;
import org.apache.royale.compiler.internal.tree.as.NamespaceAccessExpressionNode;
import org.apache.royale.compiler.internal.tree.as.NamespaceIdentifierNode;
import org.apache.royale.compiler.internal.tree.as.NamespaceNode;
import org.apache.royale.compiler.internal.tree.as.NodeBase;
import org.apache.royale.compiler.internal.tree.as.QualifiedNamespaceExpressionNode;
import org.apache.royale.compiler.internal.tree.as.ScopedBlockNode;
import org.apache.royale.compiler.internal.tree.as.UnaryOperatorNodeBase;
import org.apache.royale.compiler.internal.tree.as.VariableNode;
import org.apache.royale.compiler.internal.tree.as.metadata.MetaTagsNode;
import org.apache.royale.compiler.internal.workspaces.Workspace;
import org.apache.royale.compiler.mxml.IMXMLTextData;
import org.apache.royale.compiler.problems.AttributesNotAllowedOnPackageDefinitionProblem;
import org.apache.royale.compiler.problems.CanNotInsertSemicolonProblem;
import org.apache.royale.compiler.problems.EmbedInitialValueProblem;
import org.apache.royale.compiler.problems.EmbedMultipleMetaTagsProblem;
import org.apache.royale.compiler.problems.EmbedOnlyOnClassesAndVarsProblem;
import org.apache.royale.compiler.problems.EmbedUnsupportedTypeProblem;
import org.apache.royale.compiler.problems.ExpectDefinitionKeywordAfterAttributeProblem;
import org.apache.royale.compiler.problems.ExtraCharactersAfterEndOfProgramProblem;
import org.apache.royale.compiler.problems.FileNotFoundProblem;
import org.apache.royale.compiler.problems.ICompilerProblem;
import org.apache.royale.compiler.problems.InternalCompilerProblem;
import org.apache.royale.compiler.problems.InternalCompilerProblem2;
import org.apache.royale.compiler.problems.InvalidAttributeProblem;
import org.apache.royale.compiler.problems.InvalidLabelProblem;
import org.apache.royale.compiler.problems.InvalidTypeProblem;
import org.apache.royale.compiler.problems.MXMLInvalidDatabindingExpressionProblem;
import org.apache.royale.compiler.problems.MissingLeftBraceBeforeFunctionBodyProblem;
import org.apache.royale.compiler.problems.MultipleConfigNamespaceDecorationsProblem;
import org.apache.royale.compiler.problems.MultipleNamespaceAttributesProblem;
import org.apache.royale.compiler.problems.MultipleReservedNamespaceAttributesProblem;
import org.apache.royale.compiler.problems.NamespaceAttributeNotAllowedProblem;
import org.apache.royale.compiler.problems.NestedClassProblem;
import org.apache.royale.compiler.problems.NestedInterfaceProblem;
import org.apache.royale.compiler.problems.NestedPackageProblem;
import org.apache.royale.compiler.problems.ParserProblem;
import org.apache.royale.compiler.problems.SyntaxProblem;
import org.apache.royale.compiler.problems.UnboundMetadataProblem;
import org.apache.royale.compiler.problems.UnexpectedEOFProblem;
import org.apache.royale.compiler.problems.UnexpectedTokenProblem;
import org.apache.royale.compiler.problems.XMLOpenCloseTagNotMatchProblem;
import org.apache.royale.compiler.projects.IASProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.tree.as.IExpressionNode;
import org.apache.royale.compiler.tree.as.IFileNodeAccumulator;
import org.apache.royale.compiler.tree.as.IIdentifierNode;
import org.apache.royale.compiler.tree.as.ILiteralNode.LiteralType;
import org.apache.royale.compiler.tree.as.INamespaceDecorationNode;
import org.apache.royale.compiler.tree.as.INamespaceDecorationNode.NamespaceDecorationKind;
import org.apache.royale.compiler.tree.as.IOperatorNode.OperatorType;
import org.apache.royale.compiler.tree.metadata.IMetaTagNode;
import org.apache.royale.compiler.tree.metadata.IMetaTagsNode;
import org.apache.royale.compiler.units.ICompilationUnit;
import org.apache.royale.compiler.units.IInvisibleCompilationUnit;
import org.apache.royale.compiler.workspaces.IWorkspace;
import org.apache.royale.utils.FilenameNormalization;
import org.apache.royale.utils.NonLockingStringReader;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;

/**
 * Base class for the ANTLR-generated ActionScript parser {@link ASParser}.
 * Complex Java action code should be put in this base class instead of in the
 * ANTLR grammar.
 */
abstract class BaseASParser extends LLkParser implements IProblemReporter
{
    private static final String CONFIG_AS = "config.as";

    /**
     * Variable to use as an empty project configuration
     */
    public static final IProjectConfigVariables EMPTY_CONFIGURATION = null;

    /**
     * Used to specify "directive" rule's end token as "no end token" - the
     * parser will consume till the end of the input stream when recover from
     * errors.
     */
    protected static final int NO_END_TOKEN = -1;

    private static final String SUB_SYSTEM = "ASParser";

    /**
     * Produces an AST from the given file input. A FileNode will always be
     * returned, however it is not guaranteed to contain any content. This is
     * provided as a convenience, as it is equivalent to calling:
     * <code>parseFile(spec, workspace, EnumSet.of(PostProcessStep.CALCULATE_OFFSETS), true, true)</code>
     * meaning we follow includes, fix the tree and calculate offsets.
     * 
     * @param spec the {@link IFileSpecification} that points to the file that
     * will be parsed
     * @param fileSpecGetter the {@link IFileSpecificationGetter} that should be
     * used to open files.
     * @return a {@link FileNode} built from the given input
     */
    public static FileNode parseFile(IFileSpecification spec, IFileSpecificationGetter fileSpecGetter)
    {
        return parseFile(spec, fileSpecGetter, EnumSet.of(PostProcessStep.CALCULATE_OFFSETS), EMPTY_CONFIGURATION, true);
    }

    /**
     * Produces an AST from the given file input. A FileNode will always be
     * returned, however it is not guaranteed to contain any content
     * 
     * @param spec the {@link IFileSpecification} that points to the file that
     * will be parsed
     * @param fileSpecGetter the {@link IFileSpecificationGetter} that should be
     * used to open files.
     * @param postProcess the set of operations we want to perform on this tree
     * before it is returned. See {@link PostProcessStep}
     * @param variables the {@link IProjectConfigVariables} containing
     * project-level conditional compilation variables
     * @param followIncludes flag to determine if include statements should be
     * followed
     * @return a {@link FileNode} built from the given input
     */
    public static FileNode parseFile(IFileSpecification spec,
            IFileSpecificationGetter fileSpecGetter,
            EnumSet<PostProcessStep> postProcess,
            IProjectConfigVariables variables,
            boolean followIncludes)
    {
        return parseFile(spec, fileSpecGetter, postProcess, variables, followIncludes, true, Collections.<String> emptyList(), DeferFunctionBody.DISABLED, null, null);
    }

    /**
     * Produces an AST from the given file input. A FileNode will always be
     * returned, however it is not guaranteed to contain any content
     * 
     * @param spec the {@link IFileSpecification} that points to the file that
     * will be parsed
     * @param postProcess the set of operations we want to perform on this tree
     * before it is returned. See {@link PostProcessStep}
     * @param variables the {@link IProjectConfigVariables} containing
     * project-level conditional compilation variables
     * @param followIncludes flag to determine if include statements should be
     * followed
     * @param allowEmbeds flag to indicate if we should ignore embed meta data
     * or create EmbedNodes
     * @param includedFiles Files included by {@code asc -in} option.
     * @param flashProject Used to resolve included files in all the source
     * folders. Use {@code null} if the project is not a {@link IASProject}.
     * @param compilationUnit used to manage missing include files. both project
     * and compilation unit must be passed if you wish to have compilation units
     * re-built when their missing referenced files are added to the project.
     * @return a {@link FileNode} built from the given input
     */
    public static FileNode parseFile(IFileSpecification spec,
            IFileSpecificationGetter fileSpecGetter,
            EnumSet<PostProcessStep> postProcess,
            IProjectConfigVariables variables,
            boolean followIncludes,
            boolean allowEmbeds,
            List<String> includedFiles,
            DeferFunctionBody deferFunctionBody,
            IASProject flashProject,
            ICompilationUnit compilationUnit)
    {
        assert spec != null : "File spec can't be null.";
        assert fileSpecGetter != null : "File specification getter can't be null";
        assert fileSpecGetter.getWorkspace() instanceof Workspace : "Expected Workspace type.";

        final FileNode node = new FileNode(fileSpecGetter, spec.getPath());
        final IncludeHandler includeHandler = node.getIncludeHandler();
        includeHandler.setProjectAndCompilationUnit(flashProject, compilationUnit);

        StreamingASTokenizer tokenizer = null;
        try
        {
            tokenizer = StreamingASTokenizer.createForASParser(
                    spec,
                    includeHandler,
                    followIncludes,
                    includedFiles);

            final IRepairingTokenBuffer buffer = new StreamingTokenBuffer(tokenizer);

            final ASParser parser = new ASParser(fileSpecGetter.getWorkspace(), buffer);
            parser.deferFunctionBody = deferFunctionBody;
            parser.setProjectConfigVariables(variables);
            parser.setFilename(spec.getPath());
            parser.setAllowEmbeds(allowEmbeds);
            parser.parseFile(node, postProcess);
            if (node.getAbsoluteEnd() < tokenizer.getEndOffset())
                node.setEnd(tokenizer.getEndOffset());

            node.setProblems(tokenizer.getTokenizationProblems());
            node.setProblems(parser.getSyntaxProblems());
            final OffsetLookup offsetLookup =
                    new OffsetLookup(includeHandler.getOffsetCueList());
            node.setOffsetLookup(offsetLookup);

            int[] absoluteOffset = offsetLookup.getAbsoluteOffset(spec.getPath(), tokenizer.getEndOffset());
            //Absolute offset for the last token in a file shouldn't be more than one.
            assert absoluteOffset.length == 1 : "There seems to be a cycle in the include tree which has not been handled.";
            if (node.getAbsoluteEnd() < absoluteOffset[0])
                node.setEnd(absoluteOffset[0]);

        }
        catch (FileNotFoundException e)
        {
            // Use the message from the FileNotFoundException exception as that
            // will have the actual file that is missing in cases where .as files
            // are combined.
            node.addProblem(new FileNotFoundProblem(e.getMessage()));
        }
        catch (Exception e)
        {
            ICompilerProblem problem = new InternalCompilerProblem2(spec.getPath(), e, SUB_SYSTEM);
            node.addProblem(problem);
        }
        finally
        {
            IOUtils.closeQuietly(tokenizer);
        }
        return node;
    }

    /**
     * Parse a fragment of ActionScript. The resulting AST node is the return
     * value. The resulting definitions and scopes will be attached to the given
     * {@code containingScope}. This is used by MXML script tags.
     * 
     * @param fragment ActionScript block.
     * @param path Containing source path of the ActionScript fragment.
     * @param offset Start offset of the script.
     * @param line Line offset of the script.
     * @param column Column offset of the script.
     * @param problems Problems parsing the script.
     * @param workspace Owner workspace.
     * @param fileNodeAccumulator Collect data that needs to be stored on
     * {@code FileNode}.
     * @param containingScope The resulting definitions and scopes from the
     * script will be attached to this scope.
     * @param variables Project config variables.
     * @param postProcess Post process steps.
     * @param followIncludes True if includes are followed.
     * @param includeHandler The include handler to use.
     * @return The resulting AST subtree generated from the ActionScript
     * fragment.
     */
    public static ScopedBlockNode parseFragment2(
            final String fragment,
            final String path,
            final int offset,
            final int line,
            final int column,
            final Collection<ICompilerProblem> problems,
            final IWorkspace workspace,
            final IFileNodeAccumulator fileNodeAccumulator,
            final ASScope containingScope,
            final IProjectConfigVariables variables,
            final EnumSet<PostProcessStep> postProcess,
            final boolean followIncludes,
            final IncludeHandler includeHandler)
    {
        assert fragment != null;
        assert path != null;
        assert workspace != null;
        assert includeHandler != null;
        assert problems != null;

        StreamingASTokenizer tokenizer = null;
        ASParser parser = null;

        final IFileSpecification textFileSpec = new StringFileSpecification(path, fragment);

        final ScopedBlockNode container = new ScopedBlockNode();
        container.setScope(containingScope);
        try
        {
            tokenizer = StreamingASTokenizer.create(textFileSpec, includeHandler);
            tokenizer.setSourcePositionAdjustment(offset, line, column);

            final IRepairingTokenBuffer buffer = new StreamingTokenBuffer(tokenizer);
            parser = new ASParser(workspace, buffer);
            parser.setFileNodeAccumulator(fileNodeAccumulator);
            parser.setFilename(path);
            parser.setProjectConfigVariables(variables);

            // Initialize depth of {...} to be positive number so that nested
            // package/class definitions can be detected.
            ((BaseASParser)parser).blockDepth = 1;
            while (buffer.LA(1) != ASTokenTypes.EOF)
                parser.directive(container, NO_END_TOKEN);
            problems.addAll(tokenizer.getTokenizationProblems());
            problems.addAll(parser.getSyntaxProblems());
            problems.addAll(container.runPostProcess(postProcess, containingScope));
        }
        catch (RecognitionException e)
        {
            parser.consumeParsingError(e);
            problems.addAll(parser.getSyntaxProblems());
        }
        catch (TokenStreamException e)
        {
            ICompilerProblem problem = genericParserProblem(path, offset, offset, line, column);
            problems.add(problem);
        }
        catch (FileNotFoundException e)
        {
            ICompilerProblem problem = genericParserProblem(path, offset, offset, line, column);
            problems.add(problem);
        }
        finally
        {
            if (parser != null)
                parser.disconnect();
            IOUtils.closeQuietly(tokenizer);
            if (includeHandler != null && tokenizer != null)
                includeHandler.leaveFile(tokenizer.getEndOffset());
        }
        return container;
    }

    /**
     * Parser entry-point for rebuild function body nodes.
     * 
     * @param container Function body container node.
     * @param reader Function body reader.
     * @param path Source path.
     * @param blockOpenToken "{" of the function body.
     * @param problems Compiler problems.
     * @param workspace Current workspace.
     * @param fileNode AS file node.
     * @param configProcessor Configuration variables.
     */
    public static void parseFunctionBody(
            final ScopedBlockNode container,
            final Reader reader,
            final String path,
            final ASToken blockOpenToken,
            final Collection<ICompilerProblem> problems,
            final IWorkspace workspace,
            final FileNode fileNode,
            final ConfigProcessor configProcessor)
    {
        assert container != null;
        assert reader != null;
        assert path != null;
        assert blockOpenToken != null;
        assert problems != null;
        assert workspace != null;
        assert fileNode != null;
        assert configProcessor != null;

        StreamingASTokenizer tokenizer = null;
        ASParser parser = null;

        try
        {
            tokenizer = new StreamingASTokenizer();
            tokenizer.setReader(reader);
            tokenizer.setPath(path);
            tokenizer.setSourcePositionAdjustment(
                    blockOpenToken.getEnd(),
                    blockOpenToken.getLine(),
                    blockOpenToken.getColumn());

            final IRepairingTokenBuffer buffer = new StreamingTokenBuffer(tokenizer);
            parser = new ASParser(workspace, buffer);
            parser.setFileNodeAccumulator(fileNode);
            parser.setFilename(path);
            parser.setConfigProcessor(configProcessor);

            // Initialize "{..}" depth to positive number so that nested "package"
            // problems can be detected.
            ((BaseASParser)parser).blockDepth = 1;
            while (buffer.LA(1) != ASTokenTypes.EOF && buffer.LA(1) != ASTokenTypes.TOKEN_BLOCK_CLOSE)
                parser.directive(container, ASTokenTypes.TOKEN_BLOCK_CLOSE);
            problems.addAll(tokenizer.getTokenizationProblems());
            problems.addAll(parser.getSyntaxProblems());
        }
        catch (RecognitionException e)
        {
            parser.consumeParsingError(e);
            problems.addAll(parser.getSyntaxProblems());
        }
        catch (TokenStreamException e)
        {
            problems.add(new ParserProblem(container));
        }
        finally
        {
            if (parser != null)
                parser.disconnect();
            IOUtils.closeQuietly(tokenizer);
        }
    }

    private static ICompilerProblem genericParserProblem(String path, int start, int end, int line, int column)
    {
        ISourceLocation location = new SourceLocation(path, start, end, line, column);
        return new ParserProblem(location);
    }

    /**
     * Parse a script tag with inline ActionScript. This function does not
     * trigger "enter" and "leave" event for the inlined script, because the
     * script's token offset is still in the same offset space with its parent
     * document.
     * <p>
     * Both {@code MXMLScopeBuilder} and {@code MXMLScriptNode} use
     * this parser entry point. Different post-process tasks are requested.
     */
    public static ScopedBlockNode parseInlineScript(
            final IFileNodeAccumulator fileNodeAccumulator,
            final IMXMLTextData mxmlTextData,
            final Collection<ICompilerProblem> problems,
            final ASScope containingScope,
            final IProjectConfigVariables variables,
            final IncludeHandler includeHandler,
            final EnumSet<PostProcessStep> postProcess)
    {
        assert mxmlTextData != null : "MXMLTextData can't be null.";
        assert includeHandler != null : "IncludeHandler can't be null.";
        assert problems != null : "Problem container can't be null";

        // create a file specification for the script from MXML tag data
        final String scriptSourcePath = mxmlTextData.getParent().getPath();
        final String scriptContent = mxmlTextData.getCompilableText();
        final Reader scriptReader = new StringReader(scriptContent);

        // source adjustment
        final int compilableTextStart = mxmlTextData.getCompilableTextStart();
        final int compilableTextLine = mxmlTextData.getCompilableTextLine();
        final int compilableTextColumn = mxmlTextData.getCompilableTextColumn();

        final ScopedBlockNode container = new ScopedBlockNode();

        // create lexer
        final StreamingASTokenizer tokenizer =
                StreamingASTokenizer.createForInlineScriptScopeBuilding(
                        scriptReader,
                        scriptSourcePath,
                        includeHandler,
                        compilableTextStart,
                        compilableTextLine,
                        compilableTextColumn);
        final IRepairingTokenBuffer buffer = new StreamingTokenBuffer(tokenizer);

        // create parser
        final ASParser parser = new ASParser(containingScope.getWorkspace(), buffer);

        try
        {
            // parse script
            parser.setFilename(scriptSourcePath);
            parser.setProjectConfigVariables(variables);
            parser.setFileNodeAccumulator(fileNodeAccumulator);
            while (buffer.LA(1) != ASTokenTypes.EOF)
                parser.directive(container, NO_END_TOKEN);
            problems.addAll(tokenizer.getTokenizationProblems());
            problems.addAll(parser.getSyntaxProblems());

            // attach to given outer scope
            container.setScope(containingScope);

            // run post-processes
            final Collection<ICompilerProblem> postProcessProblems =
                    container.runPostProcess(postProcess, containingScope);
            problems.addAll(postProcessProblems);
        }
        catch (RecognitionException e)
        {
            parser.consumeParsingError(e);
            problems.addAll(parser.getSyntaxProblems());
        }
        catch (TokenStreamException e)
        {
            ICompilerProblem problem = genericParserProblem(
                    scriptSourcePath,
                    mxmlTextData.getAbsoluteStart(),
                    mxmlTextData.getAbsoluteEnd(),
                    mxmlTextData.getLine(),
                    mxmlTextData.getColumn());
            problems.add(problem);
        }
        finally
        {
            parser.disconnect();
            IOUtils.closeQuietly(tokenizer);
        }
        return container;
    }

    /**
     * Parse an expression from the passed in Reader. This method can handle
     * expressions that are inline (such as the body of a Function tag) or
     * expressions that just come from a java String. For the inline case, the
     * Reader should be a SourceFragmentsReader - it is up to the caller to set
     * up the SourceFragmentsReader correctly - see
     * MXMLExpressionNodeBase.parseExpressionFromTag. For the String case, the
     * Reader can just be a StringReader. This will parse an Expression from the
     * Reader and return the ExpressionNodeBase. It will return null, if there
     * is no expression, or it can't be parsed.
     */
    public static ExpressionNodeBase parseExpression(
            final IWorkspace workspace,
            final Reader scriptReader,
            final Collection<ICompilerProblem> problems,
            final IProjectConfigVariables variables,
            final ISourceLocation location)
    {
        assert scriptReader != null : "reader can't be null.";
        assert problems != null : "Problem container can't be null";

        String sourcePath = location.getSourcePath();

        // create tokenizer
        final StreamingASTokenizer tokenizer =
                StreamingASTokenizer.createForInlineExpressionParsing(
                        scriptReader,
                        sourcePath);

        final IRepairingTokenBuffer buffer = new StreamingTokenBuffer(tokenizer);

        // create parser
        final ASParser parser = new ASParser(workspace, buffer);

        ExpressionNodeBase expressionNode = null;
        try
        {
            // parse script
            parser.setFilename(sourcePath);
            parser.setProjectConfigVariables(variables);
            if (buffer.LA(1) != ASTokenTypes.EOF)
                expressionNode = parser.expression();
            problems.addAll(tokenizer.getTokenizationProblems());
            problems.addAll(parser.getSyntaxProblems());
        }
        catch (RecognitionException e)
        {
            parser.consumeParsingError(e);
            problems.addAll(parser.getSyntaxProblems());
        }
        catch (TokenStreamException e)
        {
            final ParserProblem genericParserProblem = new ParserProblem(location);
            problems.add(genericParserProblem);
        }
        finally
        {
            parser.disconnect();
            IOUtils.closeQuietly(tokenizer);
        }
        return expressionNode;
    }

    /**
     * Parses a string into a name valid in ActionScript. If the code is not
     * valid or does not yield an identifier, null will be returned
     * 
     * @param fragment the string that contains a name
     * @return an {@link IIdentifierNode}, or null
     */
    public static final IASNode[] parseProjectConfigVariables(IWorkspace workspace, String fragment, Collection<ICompilerProblem> problems)
    {
        ScopedBlockNode container = new ScopedBlockNode();
        ASParser parser = null;

        try
        {
            IFileSpecification fileSpec = new StringFileSpecification(CONFIG_AS, fragment, 0);
            IncludeHandler includeHandler = new IncludeHandler(workspace);

            StreamingASTokenizer tokenizer = StreamingASTokenizer.create(fileSpec, includeHandler);
            tokenizer.setReader(new NonLockingStringReader(fragment));
            tokenizer.setPath(CONFIG_AS);
            tokenizer.setFollowIncludes(false);

            final IRepairingTokenBuffer buffer = new StreamingTokenBuffer(tokenizer);

            parser = new ASParser(workspace, buffer, true);
            parser.setFilename(CONFIG_AS);

            while (buffer.LA(1) != ASTokenTypes.EOF)
                parser.directive(container, NO_END_TOKEN);
            problems.addAll(tokenizer.getTokenizationProblems());
            problems.addAll(parser.getSyntaxProblems());
            return parser.getConfigProcessorResults();
        }
        catch (FileNotFoundException e)
        {
            assert false : "StringFileSpecification never raises this exception";
        }
        catch (ANTLRException e)
        {
            // Ignore any parsing errors.
        }
        catch (RuntimeException e)
        {
            String path = parser.getSourceFilePath();
            ICompilerProblem problem = (path == null) ?
                    new InternalCompilerProblem(e) :
                    new InternalCompilerProblem2(path, e, SUB_SYSTEM);
            parser.errors.add(problem);
        }
        finally
        {
            if (parser != null)
                parser.disconnect();
        }

        int n = container.getChildCount();
        IASNode[] children = new IASNode[n];
        for (int i = 0; i < n; i++)
        {
            children[i] = container.getChild(i);
        }
        return children;
    }

    /**
     * Parses a databinding expression.
     */
    public static final IExpressionNode parseDataBinding(IWorkspace workspace, Reader reader,
            Collection<ICompilerProblem> problems)
    {
        StreamingASTokenizer tokenizer = new StreamingASTokenizer();
        tokenizer.setReader(reader);
        IRepairingTokenBuffer buffer = new StreamingTokenBuffer(tokenizer);
        ASParser parser = new ASParser(workspace, buffer);
        FileNode fileNode = new FileNode(workspace);

        // Parse the databinding and build children inside the FileNode.
        parser.parseFile(fileNode, EnumSet.noneOf(PostProcessStep.class));

        // Run post-processing to calculate all offsets.
        // Without this, identifiers have the right offsets but operators don't.
        EnumSet<PostProcessStep> postProcessSteps = EnumSet.of(
                PostProcessStep.CALCULATE_OFFSETS);
        Collection<ICompilerProblem> postProcessProblems =
                fileNode.runPostProcess(postProcessSteps, null);

        problems.addAll(tokenizer.getTokenizationProblems());
        problems.addAll(parser.getSyntaxProblems());
        problems.addAll(postProcessProblems);

        int n = fileNode.getChildCount();

        // If we didn't get any children of the file node,
        // we must have parsed whitespace (or nothing).
        // An databinding like {} or { } represents the empty string.
        if (n == 0)
        {
            return new LiteralNode(LiteralType.STRING, "");
        }

        // If we got more than one child, report that the databinding expression
        // is invalid. It must be a single expression.
        else if (n > 1)
        {
            final ICompilerProblem problem = new MXMLInvalidDatabindingExpressionProblem(fileNode);
            problems.add(problem);
            return null;
        }

        IASNode firstChild = fileNode.getChild(0);

        // If we got a single child but it isn't an expression,
        // report a problem.
        if (!(firstChild instanceof IExpressionNode))
        {
            final ICompilerProblem problem = new MXMLInvalidDatabindingExpressionProblem(fileNode);
            problems.add(problem);
            return null;
        }

        // We got a single expression, so return it.
        return (IExpressionNode)firstChild;
    }

    /**
     * Our version of a token buffer that allows us to handle optional
     * semicolons, etc
     */
    protected IRepairingTokenBuffer buffer;

    /**
     * Current metadata attributes. Attributes go into this container, then are
     * pulled out when the corresponding class, function, or variable is parsed.
     */
    protected MetaTagsNode currentAttributes;

    /**
     * {@link IASParserASDocDelegate} used to track ASDoc information.
     */
    protected final IASParserASDocDelegate asDocDelegate;

    /**
     * Last token that produced an error
     */
    protected Token errorToken = null;

    /**
     * Flag to determine if we should create EmbedNodes or ignore embed metadata
     */
    protected boolean allowEmbeds = true;

    /**
     * flag that tracks whether the parser is currently inside of a class
     * definition this is "borrowed" from the old parser to deal with some ASDoc
     * functionality
     */
    protected boolean insideClass = false;

    /**
     * Flag that indicates we are parsing a pseudo file that represents the
     * config vars on the command line (or from some other project configuration
     * option)
     */
    private final boolean parsingProjectConfigVariables;

    /**
     * Cut down on object construction when we throw on the matches call
     */
    private MismatchedTokenException exceptionPool = new MismatchedTokenException(tokenNames, null, null, false);

    /**
     * Errors we've collected as we're moving forward
     */
    protected final Set<ICompilerProblem> errors = new LinkedHashSet<ICompilerProblem>();

    /**
     * This object allows the parser to store data on a given {@code FileNode}.
     */
    private IFileNodeAccumulator fileNodeAccumulator;

    /**
     * Config processor used to handle config namespace expressions
     */
    protected ConfigProcessor configProcessor;

    /**
     * Determines if we should allowe errors. Used in conditional compilation to
     * suppress blocks that are excluded
     */
    private boolean allowErrorsInContext = true;

    /**
     * True if the current input source is an ActionScript file, as opposed to
     * AS3 scripts in MXML or other synthesized source fragments.
     */
    protected DeferFunctionBody deferFunctionBody = DeferFunctionBody.DISABLED;

    /**
     * A secondary reader to capture function body text on-the-fly. This is an
     * optimization for large files in order to avoid {@link Reader#skip(long)}
     * when the function body is rebuilt from source file and start offset.
     * <p>
     * This optimization is turned off if there's an {@code include} directive
     * in the function body.
     */
    private final Reader secondaryReader;

    /**
     * Character offset into the {@link #secondaryReader}.
     */
    private int secondaryReaderPosition = 0;

    /**
     * Number of nested "packages".
     */
    private int packageDepth = 0;

    /**
     * Number of nested "blocks".
     */
    private int blockDepth = 0;

    /**
     * Number of nested "groups" in "group directives".
     */
    private int groupDepth = 0;

    /**
     * A recursive descent parsing stack of XML tags.
     */
    private final Stack<XMLTagInfo> xmlTags;

    /**
     * Create an ActionScript parser from a workspace and a token buffer.
     * 
     * @param workspace Current workspace.
     * @param buffer Token buffer.
     */
    protected BaseASParser(IWorkspace workspace, IRepairingTokenBuffer buffer)
    {
        this(workspace, buffer, false);
    }

    /**
     * This constrcutor should ONLY be used in the very special case of parsing
     * project config vars. Typically this is done as part of parsing the
     * command line. For normal case, use the two argument constructor
     * 
     * @param workspace Current workspace.
     * @param buffer Token buffer.
     * @param parsingProjectConfigVariables true for special case when we are
     * parsing not text, but a fake "file" of configuration variables.
     */
    protected BaseASParser(IWorkspace workspace, IRepairingTokenBuffer buffer, boolean parsingProjectConfigVariables)
    {
        super(new ParserSharedInputState(), 1);
        xmlTags = new Stack<XMLTagInfo>();
        this.buffer = buffer;
        configProcessor = new ConfigProcessor(workspace, this);

        // If there are no include directives in the function body, we
        // can cache the function body text to save the seeking time.
        secondaryReader = tryGetSecondaryReader(workspace, buffer);

        this.asDocDelegate = workspace.getASDocDelegate().getASParserASDocDelegate();
        this.parsingProjectConfigVariables = parsingProjectConfigVariables;
    }

    /**
     * Try to initialize {@link #secondaryReader}. If fails, this optimization
     * is not available for the current file.
     * 
     * @param workspace Current workspace.
     * @param buffer Underlying token buffer.
     * @return Initialized secondary reader or null.
     */
    private static Reader tryGetSecondaryReader(IWorkspace workspace, IRepairingTokenBuffer buffer)
    {
        if (buffer instanceof StreamingTokenBuffer)
        {
            final StreamingTokenBuffer streamingTokenBuffer = (StreamingTokenBuffer)buffer;

            // token without source path (probably from string literals
            if (streamingTokenBuffer.getSourcePath() == null)
                return null;

            // token source path doesn't exist: imaginary sources
            final String sourcePath = FilenameNormalization.normalize(streamingTokenBuffer.getSourcePath());
            if (!new File(sourcePath).isFile())
                return null;

        	if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.WORKSPACE) == CompilerDiagnosticsConstants.WORKSPACE)
        		System.out.println("BaseASParser waiting for lock in tryGetSecondaryReader");
            // try to create a reader from file specification
            final IFileSpecification fileSpec = workspace.getFileSpecification(sourcePath);
        	if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.WORKSPACE) == CompilerDiagnosticsConstants.WORKSPACE)
        		System.out.println("BaseASParser done with lock in tryGetSecondaryReader");
            if (fileSpec != null)
            {
                try
                {
                    // success - optimization is available
                    return fileSpec.createReader();
                }
                catch (FileNotFoundException e)
                {
                    return null;
                }
            }
        }
        return null;
    }

    protected BaseASParser(TokenBuffer tokenBuf, int k)
    {
        super(tokenBuf, k);
        throw new UnsupportedOperationException();
    }

    protected BaseASParser(TokenStream lexer, int k)
    {
        super(lexer, k);
        throw new UnsupportedOperationException();
    }

    protected BaseASParser(ParserSharedInputState state, int i)
    {
        super(state, i);
        throw new UnsupportedOperationException();
    }

    protected final void addConditionalCompilationNamespace(final NamespaceNode node)
    {

        // Need to process the node even if there is an error so the node will 
        // have the location information needed to display an error.
        configProcessor.addConditionalCompilationNamespace(node);

        if (!isGlobalContext())
        {
            ICompilerProblem problem = new InvalidConfigLocationProblem(node);
            addProblem(problem);
        }
    }

    /**
     * Sets the {@link IProjectConfigVariables} to be used to support
     * conditional compilation
     * 
     * @param variables {@link IProjectConfigVariables} for the given context
     */
    public void setProjectConfigVariables(IProjectConfigVariables variables)
    {
        configProcessor.connect(variables);
    }

    /**
     * Bind the current parser to the given {@code ConfigProcessor}.
     * 
     * @param configProcessor Resolve configuration variables at parse-time.
     */
    protected final void setConfigProcessor(ConfigProcessor configProcessor)
    {
        assert configProcessor != null;
        configProcessor.setParser(this);
        this.configProcessor = configProcessor;
    }

    void addConfigConstNode(ConfigConstNode node)
    {
        configProcessor.addConfigConstNode(node);

        if (node.getKeywordNode().getKeywordId() != ASTokenTypes.TOKEN_KEYWORD_CONST)
        {
            ICompilerProblem problem = new NonConstConfigVarProblem(node.getNameExpressionNode());
            addProblem(problem);
        }
        if (!isGlobalContext())
        {
            ICompilerProblem problem = new InvalidConfigLocationProblem(node.getNameExpressionNode());
            addProblem(problem);
        }
    }

    IASNode[] getConfigProcessorResults()
    {
        if (configProcessor != null)
        {
            return configProcessor.getConfigChildren();
        }

        return new IASNode[0];
    }

    protected final IASNode evaluateConstNodeExpression(final ConfigExpressionNode node)
    {
        return configProcessor.evaluateConstNodeExpression(node);
    }

    protected final boolean isConfigNamespace(final NamespaceIdentifierNode id)
    {
        return configProcessor.isConfigNamespace(id.getName());
    }

    public Collection<ICompilerProblem> getSyntaxProblems()
    {
        return errors;
    }

    /**
     * Close the parser and release resources.
     */
    protected final void disconnect()
    {
        if (configProcessor != null)
            configProcessor.detachParser(this);
        IOUtils.closeQuietly(secondaryReader);
    }

    void setFileNodeAccumulator(IFileNodeAccumulator fileNodeAccumulator)
    {
        this.fileNodeAccumulator = fileNodeAccumulator;
    }

    @Override
    public String getSourceFilePath()
    {
        return getFilename();
    }

    protected void setAllowErrorsInContext(boolean allow)
    {
        allowErrorsInContext = allow;
    }

    @Override
    public void addProblem(ICompilerProblem problem)
    {
        if (allowErrorsInContext)
            errors.add(problem);
    }

    public void setAllowEmbeds(boolean allowEmbeds)
    {
        this.allowEmbeds = allowEmbeds;
    }

    /**
     * Assemble the tokens into a parse tree with a root FileNode.
     * 
     * @param fileNode The parser builds AST into this root {@code FileNode}.
     * @param features Post-process steps to be performed.
     */
    public void parseFile(FileNode fileNode, EnumSet<PostProcessStep> features)
    {
        currentAttributes = null;
        fileNode.setStart(0);
        fileNode.setLine(0);
        fileNode.setColumn(0);
        String sourcePath = fileNode.getSourcePath();
        setFilename(sourcePath);
        exceptionPool.fileName = sourcePath;
        exceptionPool.mismatchType = MismatchedTokenException.RANGE;
        fileNodeAccumulator = fileNode;
        try
        {
            file(fileNode);
        }
        catch (RecognitionException e)
        {
            final ASToken current = buffer.LT(1);
            if (e instanceof NoViableAltException)
            {
                addProblem(new SyntaxProblem(current));
            }
            else if (e instanceof MismatchedTokenException)
            {
                ASToken expected = new ASToken(((MismatchedTokenException)e).expecting, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, "");
                addProblem(unexpectedTokenProblem(current, expected.getTokenKind()));
            }

        }
        catch (TokenStreamException e)
        {
            addProblem(new SyntaxProblem(fileNode, null));
        }
        finally
        {
            disconnect();
        }
        fileNode.processAST(features);
    }

    protected abstract void fileLevelDirectives(ContainerNode containerNode) throws RecognitionException, TokenStreamException;

    protected void encounteredImport(ImportNode importNode)
    {
        if (fileNodeAccumulator != null)
        {
            fileNodeAccumulator.addImportNode(importNode);
        }
    }

    /**
     * Parse a String of meta data from an @function, by changing a string such
     * as: <code>@Embed(source='a.png')</code> to:
     * <code>[Embed(source='a.png')]</code> and then running it through the meta
     * data parser
     * 
     * @param metadataTagText The @function text.
     * @param problems The collection of compiler problems to which this method will add problems.
     * @return MetaTagsNode or null if error parsing the meta data
     */
    public static MetaTagsNode parseAtFunction(IWorkspace workspace, String metadataTagText, String sourcePath, int start, int line, int column, Collection<ICompilerProblem> problems)
    {
        StringBuilder stringBuffer = new StringBuilder();

        stringBuffer.append("[");
        stringBuffer.append(metadataTagText.substring(1));
        stringBuffer.append("]");

        return ASParser.parseMetadata(workspace, stringBuffer.toString(), sourcePath, start, line, column, problems);
    }

    /**
     * Parse metadata tags from a string.
     * 
     * @param workspace Current workspace.
     * @param metadataContent Source text.
     * @param sourcePath Source path.
     * @param start Start offset.
     * @param line Line offset.
     * @param column Column offset.
     * @param problems Problem collection.
     * @return A {@code MetaTagsNode} containing all the parsed metadata tags.
     */
    public static MetaTagsNode parseMetadata(
            final IWorkspace workspace,
            final String metadataContent,
            final String sourcePath,
            final int start,
            final int line,
            final int column,
            final Collection<ICompilerProblem> problems)
    {
    	if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.WORKSPACE) == CompilerDiagnosticsConstants.WORKSPACE)
    		System.out.println("BaseASParser waiting for lock in parseMetadata");
        final long lastModified = workspace.getFileSpecification(sourcePath).getLastModified();
    	if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.WORKSPACE) == CompilerDiagnosticsConstants.WORKSPACE)
    		System.out.println("BaseASParser done with lock in parseMetadata");
        final IFileSpecification fileSpec = new StringFileSpecification(sourcePath, metadataContent, lastModified);
        final IncludeHandler includeHandler = new IncludeHandler(workspace);
        final ASParser parser = new ASParser(workspace, (IRepairingTokenBuffer)null);

        try
        {
            final StreamingASTokenizer tokenizer = StreamingASTokenizer.create(fileSpec, includeHandler);
            tokenizer.setSourcePositionAdjustment(start, line, column);

            for (ASToken asToken = tokenizer.next(); asToken != null; asToken = tokenizer.next())
            {
                // Only metadata tokens and ASDoc tokens are relevant.
                switch (asToken.getType())
                {
                    case TOKEN_ATTRIBUTE:
                        parser.parseMetadata(asToken, problems);
                        break;
                    case TOKEN_ASDOC_COMMENT:
                        parser.asDocDelegate.setCurrentASDocToken(asToken);
                        break;
                    default:
                        // Ignore other tokens.
                        break;
                }
            }

        }
        catch (FileNotFoundException e)
        {
            // Do nothing. Source is from a string literal, so there should 
            // never be FileNotFoundException.
        }
        return parser.currentAttributes;
    }

    /**
     * Parse metadata tags with a forked sub-parser.
     * 
     * @param attributeToken Metadata token.
     * @param problems Problem collection.
     */
    protected final void parseMetadata(Token attributeToken, Collection<ICompilerProblem> problems)
    {
        assert problems != null : "Expected problem collection.";
        assert attributeToken != null : "Expected attribute token.";

        // Extract metadata tokens.
        final List<MetadataToken> metadataTokens;
        if (attributeToken instanceof MetaDataPayloadToken)
        {
            metadataTokens = ((MetaDataPayloadToken)attributeToken).getPayload();
        }
        else
        {
            final NonLockingStringReader metadataReader = new NonLockingStringReader(attributeToken.getText());
            final MetadataTokenizer tokenizer = new MetadataTokenizer(metadataReader);
            tokenizer.setAdjust(((TokenBase)attributeToken).getStart());
            metadataTokens = tokenizer.parseTokens();
        }

        // Initialize metadata parser.
        final GenericTokenStream metadataTokenStream = new GenericTokenStream(metadataTokens);
        final MetadataParser metadataParser = new MetadataParser(metadataTokenStream);
        metadataParser.setASDocDelegate(asDocDelegate.getMetadataParserASDocDelegate());

        // The parsed metadata tags will be added to this container node.
        if (currentAttributes == null)
            currentAttributes = new MetaTagsNode();

        // Parse metadata.
        try
        {
            metadataParser.meta(currentAttributes);
        }
        catch (RecognitionException e)
        {
            final ParserProblem problem = new ParserProblem((TokenBase)attributeToken);
            problems.add(problem);
        }
        catch (TokenStreamException e)
        {
            //do nothing
        }
    }

    /**
     * Determines if the current metadata is found within a pure statement
     * context, or if it is going to be bound to a definition. If the item is
     * free-floating (not about to be bound to a definition) then we set its
     * parent as the passed in container, and log an error.
     * 
     * @param attributeToken the token that contains the metadata
     * @param container the {@link ContainerNode} we will potentially add our
     * metadata to as a child
     */
    protected final void preCheckMetadata(Token attributeToken, ContainerNode container)
    {
        if (currentAttributes == null)
            return;

        final int la = LA(1);
        if (ASToken.isDefinitionKeyword(la) ||
            ASToken.isModifier(la) ||
            isConfigCondition() ||
            la == TOKEN_NAMESPACE_ANNOTATION ||
            la == TOKEN_ASDOC_COMMENT ||
            la == TOKEN_ATTRIBUTE)
            return;

        container.addItem(currentAttributes);
        final ICompilerProblem problem = new UnboundMetadataProblem((TokenBase)attributeToken);
        addProblem(problem);
        currentAttributes = null;
    }

    /**
     * Check if the look-ahead can be matched as a "ConfigCondition".
     * 
     * @return True if the following input is "ConfigCondition".
     */
    protected final boolean isConfigCondition()
    {
        return LA(1) == TOKEN_NAMESPACE_NAME &&
               LA(2) == TOKEN_OPERATOR_NS_QUALIFIER &&
               LA(3) == TOKEN_IDENTIFIER;
    }

    /**
     * Check if the look-ahead can be matched as a "XMLAttribute".
     * 
     * @return True if the following input is "XMLAttribute".
     */
    protected final boolean isXMLAttribute()
    {
        return LA(1) == TOKEN_E4X_NAME ||
               LA(1) == TOKEN_E4X_XMLNS ||
               (LA(1) == TOKEN_E4X_BINDING_OPEN && hasEqualsAfterClose());
    }

    /** 
     * See if there is an assignment right after the close of the binding expr.
     * If there is, then it is an attribute name otherwise no
     */
    private final boolean hasEqualsAfterClose()
    {
        int i = 2;
        while (true)
        {
            if (LA(i) == TOKEN_E4X_BINDING_CLOSE)
                return LA(i+1) == TOKEN_E4X_EQUALS;
            i++;
        }
    }
    
    /**
     * Stores decorations on the given variable definition. This will set any
     * collected modifiers, namespace, metadata or comment we've encountered
     * 
     * @param decoratedNode
     * @param node
     */
    protected void storeVariableDecorations(VariableNode decoratedNode, ContainerNode node, INamespaceDecorationNode namespace, List<ModifierNode> modList)
    {
        storeDecorations(decoratedNode, node, namespace, modList);
        storeEmbedDecoration(decoratedNode, decoratedNode.getMetaTags());
    }

    protected void storeEmbedDecoration(VariableNode variable, IMetaTagsNode metaTags)
    {
        if (!allowEmbeds)
            return;

        // no embed meta tag, so nothing more to do
        if (metaTags == null || !metaTags.hasTagByName(IMetaAttributeConstants.ATTRIBUTE_EMBED))
            return;

        // can't have an initial value on an embed variable
        if (variable.getAssignedValueNode() != null)
        {
            addProblem(new EmbedInitialValueProblem(variable));
            return;
        }

        // This type checking was ported from the old compiler in EmbedEvaluator.evaluate(Context, MetaDataNode)
        // Under normal circumstances type checking should be done on ITypeDefinition NOT string compares.
        // To make that happen, it should be done during codegen reduce_embed().
        String typeName = variable.getTypeName();
        if (!(IASLanguageConstants.Class.equals(typeName) || IASLanguageConstants.String.equals(typeName)))
        {
            addProblem(new EmbedUnsupportedTypeProblem(variable));
            return;
        }

        IMetaTagNode[] embedMetaTags = metaTags.getTagsByName(IMetaAttributeConstants.ATTRIBUTE_EMBED);
        if (embedMetaTags.length > 1)
        {
            addProblem(new EmbedMultipleMetaTagsProblem(variable));
            return;
        }

        EmbedNode embedNode = new EmbedNode(getFilename(), embedMetaTags[0], fileNodeAccumulator);
        variable.setAssignedValue(null, embedNode);
    }

    /**
     * Stores decorations on the given definition. This will set any collected
     * modifiers, namespace, metadata or comment we've encountered
     * 
     * @param decoratedNode
     * @param node
     */
    protected void storeDecorations(BaseDefinitionNode decoratedNode, ContainerNode node, INamespaceDecorationNode namespace, List<ModifierNode> modList)
    {
        //add the metadata
        if (currentAttributes != null)
        {
            IMetaTagNode[] embedTags = currentAttributes.getTagsByName(IMetaAttributeConstants.ATTRIBUTE_EMBED);
            assert embedTags != null;
            if (embedTags.length > 0)
            {
                // only member variables and classes can be annotated with embed data
                if (!((decoratedNode instanceof VariableNode) || (decoratedNode instanceof ClassNode)))
                {
                    for (IMetaTagNode embedTag : embedTags)
                        addProblem(new EmbedOnlyOnClassesAndVarsProblem(embedTag));
                }
            }

            decoratedNode.setMetaTags(currentAttributes);
        }
        //add modifiers
        if (modList != null)
        {
            int size = modList.size();
            for (int i = 0; i < size; i++)
            {
                ModifierNode modifierNode = modList.get(i);
                decoratedNode.addModifier(modifierNode);
            }
        }
        //set the namespace
        if (namespace != null)
            decoratedNode.setNamespace(namespace);

        final IASDocComment asDocComment = asDocDelegate.afterDefinition(decoratedNode);
        if (asDocComment != null)
            decoratedNode.setASDocComment(asDocComment);

        currentAttributes = null;
    }

    protected final boolean namespaceIsConfigNamespace(INamespaceDecorationNode node)
    {
        return node != null && node.getNamespaceDecorationKind() == NamespaceDecorationKind.CONFIG;
    }

    protected void logMultipleConfigNamespaceDecorationsError(NodeBase source)
    {
        ICompilerProblem problem = new MultipleConfigNamespaceDecorationsProblem(source);
        addProblem(problem);
    }

    /**
     * Check if the namespace conflicts with a config namespace
     * 
     * @param ns the NamespaceNode to check
     */
    protected void checkNamespaceDefinition(NamespaceNode ns)
    {
        if (configProcessor.isConfigNamespace(ns.getName()))
            addProblem(new ShadowedConfigNamespaceProblem(ns, ns.getName()));
    }

    /**
     * Create AST for various types of namespace access expressions.
     * 
     * @param left left-hand side of {@code ::} is the namespace expression
     * @param op {@code ::} token
     * @param right right-hand side of {@code ::} is the variable
     * @return AST for the namespace access expressions.
     */
    protected final ExpressionNodeBase transformToNSAccessExpression(ExpressionNodeBase left, ASToken op, ExpressionNodeBase right)
    {
        checkForChainedNamespaceQualifierProblem(op, right);

        final ExpressionNodeBase result;

        if (left instanceof FullNameNode)
        {
            // Left-hand side is a "full name", for example: "ns1::ns2::member".
            // Then convert the "full name" node into a namespace qualifier, 
            // and associate it with the variable.
            final QualifiedNamespaceExpressionNode qualifier = new QualifiedNamespaceExpressionNode((FullNameNode)left);
            result = new NamespaceAccessExpressionNode(qualifier, op, right);
        }
        else if (left instanceof MemberAccessExpressionNode)
        {
            // In this case, we need to turn the right side into the full qualified bit.
            IExpressionNode maRight = ((MemberAccessExpressionNode)left).getRightOperandNode();
            if (maRight instanceof NamespaceIdentifierNode)
            {
                ((MemberAccessExpressionNode)left).setRightOperandNode(new NamespaceAccessExpressionNode((NamespaceIdentifierNode)maRight, op, right));
            }
            else if (maRight instanceof IdentifierNode)
            {
                ((MemberAccessExpressionNode)left).setRightOperandNode(new NamespaceAccessExpressionNode(new NamespaceIdentifierNode((IdentifierNode)maRight), op, right));
                //this is the @ case, so @x::y
            }
            else if (maRight instanceof UnaryOperatorNodeBase && ((UnaryOperatorNodeBase)maRight).getOperator() == OperatorType.AT)
            {
                ((UnaryOperatorNodeBase)maRight).setExpression(new NamespaceAccessExpressionNode((IdentifierNode)((UnaryOperatorNodeBase)maRight).getOperandNode(), op, right));
            }
            if (maRight.hasParenthesis() && maRight instanceof MemberAccessExpressionNode)
            {
                ((MemberAccessExpressionNode)left).setRightOperandNode(new NamespaceAccessExpressionNode(new QualifiedNamespaceExpressionNode((MemberAccessExpressionNode)maRight), op, right));
            }
            result = left;
        }
        else if (left instanceof NamespaceIdentifierNode &&
                 right instanceof IdentifierNode &&
                 ((NamespaceIdentifierNode)left).getNamespaceDecorationKind() == NamespaceDecorationKind.CONFIG)
        {
            // Check to see if this is a "configCondition".  
            final ConfigExpressionNode cn = new ConfigExpressionNode(
                    (NamespaceIdentifierNode)left,
                    (ASToken)op,
                    (IdentifierNode)right);
            IASNode possibleResult = evaluateConstNodeExpression(cn);
            //it's possible for evaluateConstNodeExpression() to return null
            //if that happens, fall back to the same behavior as the final
            //else to avoid a null reference exception -JT
            if (possibleResult != null)
            {
                result = (ExpressionNodeBase) possibleResult;
            }
            else
            {
                result = new NamespaceAccessExpressionNode(left, op, right);
            }
        }
        else
        {
            result = new NamespaceAccessExpressionNode(left, op, right);
        }

        return result;
    }

    /**
     * Check for syntax error of chained namespace qualifiers:
     * 
     * <pre>
     * ns1::ns2::ns3::foo = 10;
     * </pre>
     */
    protected final void checkForChainedNamespaceQualifierProblem(ASToken nsAccessOp, ExpressionNodeBase right)
    {
        if (nsAccessOp != null &&
            right != null &&
            right.getNodeID() == ASTNodeID.NamespaceIdentifierID)
        {
            final ICompilerProblem problem = new UnexpectedTokenProblem(nsAccessOp, ASTokenKind.IDENTIFIER);
            addProblem(problem);
        }
    }

    /**
     * Set the offsets of an empty BlockNode generated from a {} token.
     * 
     * @param blockToken {} token
     * @param block BlockNode corresponding to that token
     */
    protected void setOffsetsOfEmptyBlock(IASToken blockToken, BlockNode block)
    {
        if (blockToken.isImplicit())
        {
            block.span((Token)blockToken);
        }
        else
        {
            block.span(blockToken.getStart() + 1, blockToken.getStart() + 1, blockToken.getLine(), blockToken.getColumn(), blockToken.getLine(), blockToken.getColumn());
        }
    }

    protected final void disableSemicolonInsertion()
    {
        buffer.setEnableSemicolonInsertion(false);
    }

    protected final void enableSemicolonInsertion()
    {
        buffer.setEnableSemicolonInsertion(true);
    }

    /**
     * Create a syntax error or warning based on the
     * {@code RecognitionException}.
     * 
     * @param ex ANTLR-generated parsing exception.
     * @param endToken The expected end token for the currently parsing
     * fragment. It is used to determine the compiler problem type to create.
     */
    protected final void consumeParsingError(RecognitionException ex, int endToken)
    {
        // Skip over inserted semicolon, because the fix-up token shouldn't 
        // appear in the error message.
        final ASToken current = buffer.lookAheadSkipInsertedSemicolon();
        final ICompilerProblem syntaxProblem;
        if (ex instanceof MismatchedTokenException)
        {
        	if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.ASTOKEN) == CompilerDiagnosticsConstants.ASTOKEN)
        		System.out.println("BaseASParser waiting for lock for typeToKind");
            final ASTokenKind expectedKind = ASToken.typeToKind(((MismatchedTokenException)ex).expecting);
        	if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.ASTOKEN) == CompilerDiagnosticsConstants.ASTOKEN)
        		System.out.println("BaseASParser done with lock for typeToKind");
            syntaxProblem = unexpectedTokenProblem(current, expectedKind);
        }
        else if (endToken != NO_END_TOKEN)
        {
        	if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.ASTOKEN) == CompilerDiagnosticsConstants.ASTOKEN)
        		System.out.println("BaseASParser waiting for lock for typeToKind");
            final ASTokenKind expectedKind = ASToken.typeToKind(endToken);
        	if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.ASTOKEN) == CompilerDiagnosticsConstants.ASTOKEN)
        		System.out.println("BaseASParser done with lock for typeToKind");
            syntaxProblem = unexpectedTokenProblem(current, expectedKind);
        }
        else
        {
            final ASToken errorToken = current.getType() == EOF ? buffer.previous() : current;
            syntaxProblem = new SyntaxProblem(errorToken);
        }

        addProblem(syntaxProblem);
    }

    /**
     * @see #consumeParsingError(RecognitionException, int)
     */
    protected final void consumeParsingError(RecognitionException ex)
    {
        consumeParsingError(ex, NO_END_TOKEN);
    }

    /**
     * Force the parser to report a {@code MismatchedTokenException} when failed
     * to parse an identifier. The reason is that an identifier can either be an
     * {@code IDENTIFIER} token or one of the "contextual reserved words" like
     * {@code namespace}. Since we always want the error message to be
     * "Expected ... but got ....", we convert the exception here.
     * 
     * @param ex {@code NoViableAltException} thrown in
     * {@link ASParser#identifier()}.
     * @return missing identifier
     */
    protected IdentifierNode expectingIdentifier(NoViableAltException ex)
    {
        final MismatchedTokenException mismatchedTokenException = new MismatchedTokenException(
                new String[] {"IDENTIFIER"},
                ex.token,
                ASTokenTypes.TOKEN_IDENTIFIER,
                false,
                ex.fileName);
        return handleMissingIdentifier(mismatchedTokenException);
    }

    /**
     * handles a case where we expected an identifier but our production
     * produced an error, while we were trying to produce a short name. If tree
     * fixing is enabled, this will return a new identifier to make the tree
     * "correct"
     * 
     * @param ex the exception that was thrown
     * @return an {@link IdentifierNode} or null if tree fixing is not turned on
     */
    protected IdentifierNode handleMissingIdentifier(RecognitionException ex)
    {
        consumeParsingError(ex); //we don't want to drop a semicolon here
        //now let's guard against the case where the very next token is an identifier.
        //if we produce an identifier here, everything downstream might fail
        final IdentifierNode node;
        ASToken current = buffer.previous();
        ASToken la2 = LT(1 + 1);
        ASToken la1 = LT(1);

        if (current.getType() == ASTokenTypes.TOKEN_RESERVED_WORD_EXTENDS)
        {
            // Fix for CMP-1087: the following two branches are too greedy.
            // i.e. 
            //   public class T extends   implements MyInterface
            //                          ^
            // The "extends" keyword expects an identifier. However, instead of 
            // reporting the missing identifier and continue with "implements", 
            // the following recovery logic throws away "implements" keyword and
            // sends back "MyInterface".
            node = IdentifierNode.createEmptyIdentifierNodeAfterToken(current);
        }
        else if (la2.getType() == ASTokenTypes.TOKEN_IDENTIFIER && la2.getLine() == current.getLine())
        {
            //let's make sure this is on the same line, avoiding possibly going past the end of the statement
            //since this is all repair code anyway, this produces a much "saner" repaired tree
            ASToken token = LT(1 + 1);
            node = new IdentifierNode(token.getText(), (IASToken)token);
            consume(); //consume error token
            consume(); //act as match() for identifier, which consumes it
        }
        else if (la1.isKeywordOrContextualReservedWord() && la1.getLine() == current.getLine())
        {
            // If it's a keyword, repair by making an identifier node with the text of the keyword
            // This makes a more sensible tree - the user may be in the middle of typing an identifier that
            // starts with a keyword.  They probably meant "f.is" rather than "(f.)is" for example 
            node = new IdentifierNode(la1.getText(), (IASToken)la1);
            consume();
        }
        else
        {
            node = IdentifierNode.createEmptyIdentifierNodeAfterToken(current);
        }

        return node;
    }

    /**
     * handles a case where we expected an identifier but our production
     * produced an error, while we were trying to produce a dotted name. If tree
     * fixing is enabled, this will return a new identifier to make the tree
     * "correct"
     * 
     * @param ex the exception that was thrown
     * @return an {@link IdentifierNode} or null if tree fixing is not turned on
     */
    protected ExpressionNodeBase handleMissingIdentifier(RecognitionException ex, ExpressionNodeBase n)
    {
        if (n instanceof FullNameNode)
        {
            ExpressionNodeBase temp = handleMissingIdentifier(ex);
            if (temp != null)
            {
                ((FullNameNode)n).setRightOperandNode(temp);
            }
            return n;
        }
        handleParsingError(ex);
        return n;
    }

    /**
     * Logs a syntax error against the given token
     * 
     * @param badToken the token that caused the syntax error
     */
    protected final void logSyntaxError(ASToken badToken)
    {
        addProblem(new SyntaxProblem(badToken));
    }

    /**
     * Called by the parser to handle specific error cases we come across. If
     * the error handler can fix the error to potentially yield a successful
     * production then true is returned by this method. This method may insert
     * tokens into the token stream, or change the types of tokens that produced
     * the error.
     * 
     * @param ex the exception thrown by the parser
     * @param endToken expected end token
     * @return true if this error case can potentially be fixed
     */
    protected boolean handleParsingError(final RecognitionException ex, final int endToken)
    {
        final ASToken current = buffer.LT(1);

        // This variable will be assigned to "fErrorToken" after the error 
        // recovery. We don't want inserted "virtual semicolons" to be come 
        // an "error token", because it generates confusing syntax errors.
        final ASToken errorToken;
        if (current.getType() == TOKEN_SEMICOLON)
            errorToken = buffer.lookAheadSkipInsertedSemicolon();
        else
            errorToken = current;

        final boolean result = handleParsingError(ex, current, errorToken, endToken);
        this.errorToken = errorToken;
        return result;
    }

    /**
     * @see #handleParsingError(RecognitionException, int)
     */
    protected boolean handleParsingError(RecognitionException ex)
    {
        return handleParsingError(ex, NO_END_TOKEN);
    }

    private boolean handleParsingError(final RecognitionException ex, final ASToken current, final ASToken errorToken, final int endToken)
    {
        // Ignore ASDoc problems.
        if (current.getType() == ASTokenTypes.TOKEN_ASDOC_COMMENT)
        {
            consume();
            return true;
        }

        // Don't log an error if we've seen this token already.
        if (errorToken != this.errorToken)
            consumeParsingError(ex, endToken);

        return recoverFromRecognitionException(ex, current);
    }

    /**
     * Generic routine to recover from an {@code RecognitionException}.
     * 
     * @param ex ANTLR-generated parsing exception.
     * @param nextToken Next token.
     * @return True if error recovery succeeded.
     */
    private boolean recoverFromRecognitionException(final RecognitionException ex, final ASToken nextToken)
    {
        // Don't recover from EOF, because an "unexpected EOF" problem should
        // have been logged already.
        if (nextToken.getType() == EOF)
            return false;

        // Same token is producing an error, consume it.
        if (nextToken == errorToken)
        {
            consume();
            return true;
        }

        /*
         * if the token we had is a keyword, there is a chance that the user
         * could be in the middle of typing the name of an identifier that
         * starts with a keyword change it to an identifier, don't consume and
         * see if the parser can recover and turn it into a name the error,
         * however, will still be logged.
         */
        if (nextToken.isKeywordOrContextualReservedWord())
        {
            /*
             * There are a few cases where we don't want this to occur however.
             * Most notably, if the user is missing a close bracket or paren,
             * assume they are closing a structure and just return without
             * changing the type. Both of these can occur when adding metadata
             */
            if (ex instanceof MismatchedTokenException)
            {
                switch (((MismatchedTokenException)ex).expecting)
                {
                    case ASTokenTypes.TOKEN_SQUARE_CLOSE:
                    case ASTokenTypes.TOKEN_PAREN_CLOSE:
                        return true;
                }
            }
            nextToken.setType(ASTokenTypes.TOKEN_IDENTIFIER);
            return true;
        }

        if (nextToken.isOpenToken())
        {
            // Don't have the inserted semicolon be the next token we are 
            // looking for, since we're opening a statement.
            buffer.insertSemicolon(false);
        }
        else if (ASToken.isCloseToken(nextToken.getType()))
        {
            // Closed a block, semicolon will be matched later.
            buffer.insertSemicolon(true);
        }
        else if (nextToken.getType() == ASTokenTypes.TOKEN_SEMICOLON)
        {
            // Our semicolon isn't valid here, so don't bother inserting 
            // another one.
            consume();
        }
        else
        {
            buffer.insertSemicolon(true);
        }

        return true;
    }

    protected void endContainerAtError(RecognitionException ex, NodeBase node)
    {
        Token endToken = null;
        if (ex instanceof NoViableAltException)
        {
            endToken = ((NoViableAltException)ex).token;
        }
        else if (ex instanceof MismatchedTokenException)
        {
            endToken = ((MismatchedTokenException)ex).token;
        }
        if (endToken == null || endToken.getType() == ASTokenTypes.EOF)
        {
            endToken = buffer.previous();
        }
        node.endBefore(endToken);
    }

    @Override
    public final void consume()
    {
        buffer.consume();
    }

    /**
     * Match optional semicolon.
     * <p>
     * This method will report a {@link CanNotInsertSemicolonProblem} if a
     * "virtual semicolon" is expected but failed to be inserted, except when
     * there's already a syntax error on the same line, because the preceding
     * syntax error might early-terminate a statement, making the parser to
     * expect a optional semicolon.
     * <p>
     * It's not "wrong" to always report the semicolon problem. However, it
     * would make too much "noise" on the console, and it would break almost all
     * negative ASC tests.
     * 
     * @return True if optional semicolon is matched.
     * @see IRepairingTokenBuffer#matchOptionalSemicolon()
     */
    protected boolean matchOptionalSemicolon()
    {
        final boolean success = buffer.matchOptionalSemicolon();

        if (!success)
        {
            final ICompilerProblem lastError = Iterables.getLast(errors, null);
            if (lastError == null || lastError.getLine() < buffer.previous().getLine())
            {
                addProblem(new CanNotInsertSemicolonProblem(buffer.LT(1)));
            }
        }

        return success;
    }

    /**
     * An optional function body can either be a function block or a semicolon
     * (virtual semicolon). If neither is matched, a
     * {@link MissingLeftBraceBeforeFunctionBodyProblem} occurs. However, we
     * only report the problem if the function definition parsing doesn't have
     * other syntax issues so far.
     */
    protected void reportFunctionBodyMissingLeftBraceProblem()
    {
        final ICompilerProblem lastError = Iterables.getLast(errors, null);
        if (lastError == null || lastError.getLine() < buffer.previous().getLine())
        {
            final ICompilerProblem problem = new MissingLeftBraceBeforeFunctionBodyProblem(buffer.LT(1));
            addProblem(problem);
        }
    }

    /**
     * Consume until one of the following tokens:
     * <ul>
     * <li>keyword</li>
     * <li>identifier</li>
     * <li>EOF</li>
     * <li>metadata tag</li>
     * <li>ASDoc comment</li>
     * <li>token type of the given exit condition</li>
     * </ul>
     * 
     * @param exitCondition Stop if the next token type matches the exit
     * condition.
     */
    protected void consumeUntilKeywordOrIdentifier(int exitCondition)
    {
        consumeUntilKeywordOr(
                ASTokenTypes.TOKEN_IDENTIFIER,
                ASTokenTypes.TOKEN_ATTRIBUTE,
                ASTokenTypes.TOKEN_ASDOC_COMMENT,
                exitCondition);
    }

    /**
     * Consume until a keyword, EOF or specified token types.
     * 
     * @param types Stop if the next token's type is one of these.
     */
    protected void consumeUntilKeywordOr(final Integer... types)
    {
        final ImmutableSet<Integer> stopSet = new ImmutableSet.Builder<Integer>()
                .add(types)
                .add(ASTokenTypes.EOF)
                .build();

        while (!stopSet.contains(buffer.LA(1)) && !LT(1).isKeywordOrContextualReservedWord())
        {
            consume();
        }
    }

    @Override
    public final void match(final int t) throws MismatchedTokenException, TokenStreamException
    {
        final int la = LA(1);
        if (la != t)
        {
            exceptionPool.expecting = t;
            exceptionPool.token = LT(1);
            throw exceptionPool;
        }

        // Only update the "block depth" tracker when the parser is not in 
        // syntactic predicates.
        if (inputState.guessing == 0)
        {
            switch (la)
            {
                case TOKEN_BLOCK_OPEN:
                    blockDepth++;
                    break;
                case TOKEN_BLOCK_CLOSE:
                    blockDepth = blockDepth > 0 ? blockDepth - 1 : 0;
                    break;
                default:
                    // Ignore other tokens.
                    break;
            }
        }

        consume();
    }

    @Override
    public final int LA(final int i)
    {
        return buffer.LA(i);
    }

    @Override
    public final ASToken LT(final int i)
    {
        return buffer.LT(i);
    }

    @Override
    public final int mark()
    {
        return buffer.mark();
    }

    @Override
    public final void rewind(final int pos)
    {
        buffer.rewind(pos);
    }

    protected static enum ExpressionMode
    {
        normal, noIn, e4x
    }

    /**
     * Binary precedence table used for expression parsing optimization.
     */
    private static final ImmutableMap<Integer, Integer> BINARY_PRECEDENCE =
            new ImmutableMap.Builder<Integer, Integer>()
                    .put(TOKEN_COMMA, 1)
                    .put(TOKEN_OPERATOR_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_LOGICAL_AND_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_LOGICAL_OR_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_PLUS_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_MINUS_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_MULTIPLICATION_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_DIVISION_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_MODULO_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_BITWISE_AND_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_BITWISE_OR_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_BITWISE_XOR_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_BITWISE_LEFT_SHIFT_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_BITWISE_RIGHT_SHIFT_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_BITWISE_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT, 2)
                    .put(TOKEN_OPERATOR_TERNARY, 3)
                    .put(TOKEN_OPERATOR_LOGICAL_OR, 4)
                    .put(TOKEN_OPERATOR_LOGICAL_AND, 5)
                    .put(TOKEN_OPERATOR_BITWISE_OR, 6)
                    .put(TOKEN_OPERATOR_BITWISE_XOR, 7)
                    .put(TOKEN_OPERATOR_BITWISE_AND, 8)
                    .put(TOKEN_OPERATOR_EQUAL, 9)
                    .put(TOKEN_OPERATOR_NOT_EQUAL, 9)
                    .put(TOKEN_OPERATOR_STRICT_EQUAL, 9)
                    .put(TOKEN_OPERATOR_STRICT_NOT_EQUAL, 9)
                    .put(TOKEN_OPERATOR_GREATER_THAN, 10)
                    .put(TOKEN_OPERATOR_GREATER_THAN_EQUALS, 10)
                    .put(TOKEN_OPERATOR_LESS_THAN, 10)
                    .put(TOKEN_OPERATOR_LESS_THAN_EQUALS, 10)
                    .put(TOKEN_KEYWORD_INSTANCEOF, 10)
                    .put(TOKEN_KEYWORD_IS, 10)
                    .put(TOKEN_KEYWORD_AS, 10)
                    .put(TOKEN_KEYWORD_IN, 10)
                    .put(TOKEN_OPERATOR_BITWISE_LEFT_SHIFT, 11)
                    .put(TOKEN_OPERATOR_BITWISE_RIGHT_SHIFT, 11)
                    .put(TOKEN_OPERATOR_BITWISE_UNSIGNED_RIGHT_SHIFT, 11)
                    .put(TOKEN_OPERATOR_MINUS, 12)
                    .put(TOKEN_OPERATOR_PLUS, 12)
                    .put(TOKEN_OPERATOR_DIVISION, 13)
                    .put(TOKEN_OPERATOR_MODULO, 13)
                    .put(TOKEN_OPERATOR_STAR, 13)
                    .build();

    /**
     * Get the precedence of the given operator token.
     * 
     * @param op Operator token.
     * @return Precedence of the operator token.
     */
    private final int precedence(final ASToken op)
    {
        // When processing IN in a for-loop, drop precedence to 0, so that operator precedence parsing halts.
        if (expressionMode == ExpressionMode.noIn && op.getType() == TOKEN_KEYWORD_IN)
            return 0;

        final Integer precedence = BINARY_PRECEDENCE.get(op.getType());
        if (precedence != null)
            return precedence;
        else
            return 0;
    }

    /**
     * Operator precedence parser. Refer to Vaughan Pratt,
     * "top down operator precedence parsing" or Dijkstra's shunting yard
     * algorithm, or precedence climbing.
     */
    protected final ExpressionNodeBase precedenceParseExpression(int prec) throws RecognitionException, TokenStreamException
    {
        ExpressionNodeBase result = unaryExpr();

        ASToken op = LT(1);
        int p1 = precedence(op);
        int p2 = p1;

        for (; p1 >= prec; p1--)
        {
            while (p2 == p1)
            {
                consume();

                ExpressionNodeBase t = precedenceParseExpression(p1 + 1); // parse any sub expressions that are of higher precedence
                result = (ExpressionNodeBase)BinaryOperatorNodeBase.create(op, result, t);
                op = LT(1);
                p2 = precedence(op);
            }
        }
        return result;
    }

    /**
     * Expression mode of the current parsing state. {@code ASParser} updates
     * this field according to its context.
     */
    protected ExpressionMode expressionMode = ExpressionMode.normal;

    /**
     * Provides method signature to {@link ASParser#unaryExpr()} so that
     * {@link #precedenceParseExpression()} can call it.
     */
    abstract ExpressionNodeBase unaryExpr() throws RecognitionException, TokenStreamException;

    /**
     * True if a {@link ExtraCharactersAfterEndOfProgramProblem} was logged
     * already.
     */
    private boolean extraCharacterAfterEndOfProgramProblemLogged = false;

    /**
     * Call this method when extra characters were found after the end of the
     * program. The {@link ExtraCharactersAfterEndOfProgramProblem} is only
     * logged when it's the first error in the current file. Even though this
     * method might be called multiple times because of the parser recovery
     * logic, such problem can only be reported once.
     * 
     * @param token Token recognized as "extra characters".
     */
    protected void foundExtraCharacterAfterEndOfProgram(ASToken token)
    {
        if (!extraCharacterAfterEndOfProgramProblemLogged && errors.isEmpty())
        {
            extraCharacterAfterEndOfProgramProblemLogged = true;
            addProblem(new ExtraCharactersAfterEndOfProgramProblem(token));
        }
    }

    /**
     * Call this method in the grammar once a "restricted token" is matched.
     * According to ECMA-262 Section 7.9.1:
     * <p>
     * <blockquote> When, as the program is parsed from left to right, a token
     * is encountered that is allowed by some production of the grammar, but the
     * production is a restricted production and the token would be the first
     * token for a terminal or nonterminal immediately following the annotation
     * [no LineTerminator here] within the restricted production (and therefore
     * such a token is called a restricted token), and the restricted token is
     * separated from the previous token by at least one LineTerminator, then a
     * semicolon is automatically inserted before the restricted token.
     * </blockquote>
     * <p>
     * These are the only restricted productions in ECMA grammar:
     * 
     * <pre>
     * Expression [no LineTerminator] ++
     * Expression [no LineTerminator] --
     * continue [no LineTerminator] Identifier
     * break [no LineTerminator] Identifier
     * return [no LineTerminator] Expression
     * throw [no LineTerminator] Expression
     * </pre>
     * 
     * As a result, this method should be called after these tokens are matched:
     * {@code continue, break, return, throw}.
     * 
     * @param current The current token should be the restricted token.
     * @return True if the semicolon is inserted.
     * @note See ECMA 262 section 7.9.1 for details about semicolon insertion rules.
     */
    protected boolean afterRestrictedToken(final ASToken current)
    {
        assert RESTRICTED_TOKEN_TYPES.contains(current.getType()) : "Unexpected restricted token type: " + current.getTypeString();
        final ASToken nextToken = LT(1);

        // If the next token is a semicolon, even when there's a new-line, we 
        // needn't insert a virtual semicolon.
        if (nextToken != null &&
            nextToken.getLine() > current.getLine() &&
            nextToken.getType() != TOKEN_SEMICOLON)
            return buffer.insertSemicolon(true);
        else
            return false;
    }

    /**
     * If any of these tokens is followed by a new line, we must insert a
     * semicolon after it. The set is only used by the assertion in
     * {@link #afterRestrictedToken(ASToken)}.
     */
    private static final ImmutableSet<Integer> RESTRICTED_TOKEN_TYPES = ImmutableSet.of(
            ASTokenTypes.TOKEN_KEYWORD_RETURN,
            ASTokenTypes.TOKEN_KEYWORD_CONTINUE,
            ASTokenTypes.TOKEN_KEYWORD_BREAK,
            ASTokenTypes.TOKEN_KEYWORD_THROW);

    /**
     * See Javadoc for {@link #afterRestrictedToken(ASToken)} for details about
     * "restricted token" and semicolon insertion.
     * 
     * @param nextToken The next token should be the restricted token.
     * @return True if the semicolon is inserted.
     * @see #afterRestrictedToken(ASToken)
     */
    protected boolean beforeRestrictedToken(final ASToken nextToken)
    {
        // The next token should be the restricted token ++ or --.
        final ASToken current = buffer.previous();
        assert nextToken != null : "token can't be null";
        assert nextToken.getType() == ASTokenTypes.TOKEN_OPERATOR_INCREMENT ||
               nextToken.getType() == ASTokenTypes.TOKEN_OPERATOR_DECREMENT : "Unexpected restricted token type: " + nextToken.getTypeString();

        // If the next token is a semicolon, even when there's a new-line, we 
        // needn't insert a virtual semicolon.
        if (nextToken != null &&
            nextToken.getLine() > current.getLine() &&
            nextToken.getType() != TOKEN_SEMICOLON)
            return buffer.insertSemicolon(false);
        else
            return false;
    }

    /**
     * Log an "unexpected token" problem.
     * 
     * @param site offending token
     * @param expectedKind expected token kind
     * @return {@link UnexpectedTokenProblem} instance.
     */
    protected final ICompilerProblem unexpectedTokenProblem(ASToken site, ASTokenKind expectedKind)
    {
        if (site.getType() == EOF)
        {
            // EOF token is synthesized. It doesn't have reasonable source location.
            // Use the last token instead.
            return new UnexpectedEOFProblem(buffer.previous(), expectedKind);
        }
        else
        {
            return new UnexpectedTokenProblem(site, expectedKind);
        }
    }

    /**
     * @see ASL syntax spec chapter 4.1
     */
    private static final ImmutableSet<String> RESERVED_NAMESPACE_ATTRIBUTES =
            ImmutableSet.of("private", "public", "protected", "internal");

    /**
     * Make sure there's at most one namespace attribute found. Report syntax
     * problem otherwise.
     * 
     * @param namespaceAttributes A list of namespace attributes.
     * @note See AS3 syntax specification chapter 8 - Enforcement of Syntactic
     * Restrictions.
     */
    protected void verifyNamespaceAttributes(final List<INamespaceDecorationNode> namespaceAttributes)
    {
        if (namespaceAttributes.size() < 2)
            return;

        final List<INamespaceDecorationNode> reservedNamespaceAttributes = new ArrayList<INamespaceDecorationNode>();
        final List<INamespaceDecorationNode> userDefinedNamespaceAttributes = new ArrayList<INamespaceDecorationNode>();

        for (final INamespaceDecorationNode namespaceAttribute : namespaceAttributes)
        {
            final String namespaceName = namespaceAttribute.getName();
            if (RESERVED_NAMESPACE_ATTRIBUTES.contains(namespaceName))
                reservedNamespaceAttributes.add(namespaceAttribute);
            else
                userDefinedNamespaceAttributes.add(namespaceAttribute);
        }

        if (reservedNamespaceAttributes.size() > 1)
        {
            final MultipleReservedNamespaceAttributesProblem problem =
                    new MultipleReservedNamespaceAttributesProblem(reservedNamespaceAttributes.get(0));
            addProblem(problem);
        }

        if (userDefinedNamespaceAttributes.size() > 1)
        {
            final MultipleNamespaceAttributesProblem problem =
                    new MultipleNamespaceAttributesProblem(userDefinedNamespaceAttributes.get(0));
            addProblem(problem);
        }

        if (!userDefinedNamespaceAttributes.isEmpty() && !reservedNamespaceAttributes.isEmpty())
        {
            final NamespaceAttributeNotAllowedProblem problem =
                    new NamespaceAttributeNotAllowedProblem(userDefinedNamespaceAttributes.get(0));
            addProblem(problem);
        }
    }

    private static final ImmutableSet<String> CONTEXTUAL_RESERVED_KEYWORD_MODIFIERS =
            ImmutableSet.of("dynamic", "final", "native", "static", "override", "abstract");

    /**
     * Recover from {@link CanNotInsertSemicolonProblem} after an expression
     * statement. Such error pattern is usually a sign of invalid code being
     * parsed as expressions.
     * <p>
     * <h2>Recover from contextual keywords</h2> When there's syntax errors, the
     * token transformation logic in {@link StreamingASTokenizer} might fail.
     * For example, a contextual reserved keyword like "static" is labeled as
     * "identifier" instead of "modifier" when the token following "static"
     * doesn't start a definition. As a result "static" is parsed as a single
     * variable "expressionStatement", and the following content will be
     * reported with a {@link CanNotInsertSemicolonProblem}.
     * </p>
     * <p>
     * Since we want the error reporting to be user-friendly, we need to detect
     * such cases and override the compiler problems. The pattern is simple: an
     * {@link ExpressionNodeBase} of type {@link IdentifierNode} and it's
     * identifier name is one of the contextual reserved keywords:
     * {@code dynamic}, {@code final}, {@code native}, {@code static} and
     * {@code override}.
     * </p>
     * <p>
     * <h2>Recover from invalid labels</h2> When the next offending token is
     * colon, it means the parsed expression isn't a valid label identifier.
     * </p>
     * 
     * @param e The AST created for the parsed expression.
     */
    protected final void recoverFromExpressionStatementMissingSemicolon(final ExpressionNodeBase e)
    {
        final ASToken lt = buffer.LT(1);
        ICompilerProblem problem = null;
        if (e instanceof IdentifierNode)
        {
            final String name = ((IdentifierNode)e).getName();
            if (CONTEXTUAL_RESERVED_KEYWORD_MODIFIERS.contains(name))
            {
                if (lt.getType() == ASTokenTypes.TOKEN_KEYWORD_PACKAGE)
                {
                    problem = new AttributesNotAllowedOnPackageDefinitionProblem(lt);
                }
                else
                {
                    problem = new ExpectDefinitionKeywordAfterAttributeProblem(name, lt);
                }
            }
        }
        else if (lt.getType() == TOKEN_COLON)
        {
            problem = new InvalidLabelProblem(lt);
            consume(); // drop the colon
        }

        if (problem != null)
        {
            // replace the syntax problem
            final ICompilerProblem lastError = Iterables.getLast(errors);
            errors.remove(lastError);
            errors.add(problem);
        }
    }

    /**
     * Traps erroneous syntax like:
     * 
     * <pre>
     *     innerLabel: namespace ns1;
     * </pre>
     * 
     * Although the {@link InvalidAttributeProblem} doesn't make much sense in
     * this context, we are just being compatible with the old ASC's behavior.
     * 
     * @param offendingNSToken The offending "namespace" token after the label
     * and colon.
     */
    protected void trapInvalidSubstatement(ASToken offendingNSToken)
    {
        final InvalidAttributeProblem problem = new InvalidAttributeProblem(offendingNSToken);
        addProblem(problem);
    }

    /**
     * Traps erroneous syntax like:
     * 
     * <pre>
     * package foo 
     * {
     *     ns1 private class T {}
     * }
     * </pre>
     * 
     * @param offendingNSToken The unexpected namespace name token.
     */
    protected void trapInvalidNamespaceAttribute(ASToken offendingNSToken)
    {
        final NamespaceAttributeNotAllowedProblem problem =
                new NamespaceAttributeNotAllowedProblem(offendingNSToken);
        addProblem(problem);
    }

    /**
     * Evaluate configuration variable result.
     * 
     * @param configNamespace The configuration namespace.
     * @param opToken The operator token. Always "::".
     * @param configVar The unqualified configuration variable name.
     * @return True if the qualified configuration variable evaluates to true.
     */
    protected boolean evaluateConfigurationVariable(
            final IdentifierNode configNamespace,
            final ASToken opToken,
            final IdentifierNode configVar)
    {
        final ConfigExpressionNode configExpression = new ConfigExpressionNode(
                configNamespace,
                opToken,
                configVar);

        final Object value = configProcessor.evaluateConstNodeExpressionToJavaObject(configExpression);
        return value == null ? false : ECMASupport.toBoolean(value);
    }

    /**
     * Report unexpected token problem.
     * 
     * @param token Offending token.
     */
    protected final void reportUnexpectedTokenProblem(final ASToken token)
    {
        addProblem(new SyntaxProblem(token));
    }

    /**
     * Consume all the tokens in a function body, excluding the open curly and
     * close curly braces.
     * <p>
     * In order to allow lazy-parsing of the skipped function bodies, the
     * contents need to be cached. We can't cache all the tokens because they
     * take up huge amount of memory.
     * <p>
     * On the other hand, we can't cache the text of the function body by
     * accessing the underlying {@code Reader} directly, because it isn't
     * guaranteed to point to the start of the function block when then the
     * parser sees the function body due to the possible "look-ahead" operations
     * triggered by the tokenizer.
     * <p>
     * As a result, it leaves us the only option which is to capture the start
     * and end character offsets of the function body.
     * <p>
     * Since {@link Reader#skip(long)} is slow, the parser keeps a secondary
     * {@code Reader} ({@link #secondaryReader}) in order to cache the text of
     * the function body on-the-fly. The text is stored on the corresponding
     * {@link FunctionNode}.
     * <p>
     * This feature is turn on only <b>all</b> of the following conditions are
     * true:
     * <ul>
     * <li>The source is from a readable ActionScript source file.</li>
     * <li>The function is not a function closure.</li>
     * <li>The source file is not an in-memory compilation (see
     * {@link IInvisibleCompilationUnit}) unit in the editor.</li>
     * </ul>
     * 
     * @param functionNode Function node.
     * @param openT The open curly token of the function body.
     * @see <a
     * href="https://zerowing.corp.adobe.com/display/compiler/Deferring+function+body+nodes">Deferring
     * function body nodes</a>
     */
    protected final void skipFunctionBody(final FunctionNode functionNode, final ASToken openT)
    {
        assert functionNode != null : "Function node can't be null.";
        assert openT != null && openT.getType() == TOKEN_BLOCK_OPEN : "Expected '{' token";

        // this feature is not applicable to this function node
        if (deferFunctionBody != DeferFunctionBody.ENABLED ||
            functionNode.getParent() instanceof FunctionObjectNode)
            return;

        // If the first token in the function body is "}" or "EOF", the function
        // body is empty. There's nothing to skip.
        if (LA(1) == TOKEN_BLOCK_CLOSE || LA(1) == EOF)
            return;

        // Start skipping function body by matching curly braces.
        boolean functionBodyHasInclude = false;
        ASToken prevToken = null;

        tokenLoop:
        for (int depth = 0; depth > 0 || LA(1) != TOKEN_BLOCK_CLOSE; consume())
        {
            prevToken = LT(1);

            // If a function body token's source path is different from the
            // function node's source path, there's include processing. Then,
            // the function body text caching optimization can't be used. 
            if (!this.getSourceFilePath().equals(LT(1).getSourcePath()))
                functionBodyHasInclude = true;

            switch (prevToken.getType())
            {
                case TOKEN_BLOCK_OPEN:
                    depth++;
                    break;
                case TOKEN_BLOCK_CLOSE:
                    depth--;
                    break;
                case EOF:
                    break tokenLoop;
            }
        }

        assert LA(1) == TOKEN_BLOCK_CLOSE || LA(1) == EOF : "Loop should stop before the '}' of the function body or 'eof'.";
        assert prevToken != null : "Function body must have at least one token if we reached here.";

        final StringBuilder functionBodyText = tryGetFunctionBodyText(openT, functionBodyHasInclude, prevToken);
        functionNode.setFunctionBodyInfo(openT, prevToken, configProcessor, functionBodyText);
        fileNodeAccumulator.addDeferredFunctionNode(functionNode);
    }

    /**
     * Optimization: cache function body text if there's no include processing.
     * 
     * @param openT Open curly token of the function body.
     * @param functionBodyHasInclude True if there are "include" directives in
     * the function body.
     * @param lastToken Last token of the function body (excluding close curly
     * "}").
     * @return Function body text or null.
     */
    private StringBuilder tryGetFunctionBodyText(
            final ASToken openT,
            final boolean functionBodyHasInclude,
            final ASToken lastToken)
    {
        final StringBuilder functionBodyText;
        if (secondaryReader != null && !functionBodyHasInclude)
        {
            // Get function body text
            functionBodyText = new StringBuilder();
            try
            {
                // Move secondary reader to the beginning of a function body.
                final int readerSkip = openT.getLocalEnd() - secondaryReaderPosition;
                assert readerSkip >= 0 : "Invalid position";
                final long skip = secondaryReader.skip(readerSkip);
                assert skip == readerSkip : "The buffer didn't skip full length.";

                // Read text till the end of the function body (including the 
                // closing curly if there is one).
                final ASToken endToken;
                if (LA(1) == TOKEN_BLOCK_CLOSE)
                    endToken = LT(1);
                else
                    endToken = lastToken;

                for (int position = openT.getLocalEnd(); position < endToken.getLocalEnd(); position++)
                {
                    functionBodyText.append((char)secondaryReader.read());
                }

                // Update secondary reader position to the end of the function body.
                secondaryReaderPosition = endToken.getLocalEnd();
            }
            catch (IOException e)
            {
                String path = openT.getSourcePath();
                ICompilerProblem problem = (path == null) ?
                        new InternalCompilerProblem(e) :
                        new InternalCompilerProblem2(path, e, SUB_SYSTEM);
                errors.add(problem);
            }
        }
        else
        {
            functionBodyText = null;
        }
        return functionBodyText;
    }

    /**
     * Increment package depth counter and check for
     * {@link NestedPackageProblem}.
     * 
     * @param keywordPackage "package" keyword token.
     */
    protected final void enterPackage(ASToken keywordPackage)
    {
        if (packageDepth > 0)
        {
            final ICompilerProblem problem = new NestedPackageProblem(keywordPackage);
            addProblem(problem);
        }
        else if (!isGlobalContext())
        {
            final ICompilerProblem problem = new SyntaxProblem(keywordPackage);
            addProblem(problem);
        }
        packageDepth++;
    }

    /**
     * Called when the parser enters a type application expression. It validates
     * the "collection expression" of the type application expression. It must
     * be either a {@code MemberAccessExpressionNode} or an
     * {@code IdentifierNode}.
     * 
     * @param collectionExpression The expression node on the left-hand side of
     * {@code .< >}.
     */
    protected final void enterTypeApplication(final ExpressionNodeBase collectionExpression)
    {
        if (collectionExpression == null ||
            collectionExpression.getNodeID() == ASTNodeID.IdentifierID ||
            collectionExpression.getNodeID() == ASTNodeID.FunctionCallID ||
            collectionExpression.getNodeID() == ASTNodeID.TypedExpressionID ||
            collectionExpression instanceof MemberAccessExpressionNode)
        {
            return;
        }
        else
        {
            final ICompilerProblem problem = new InvalidTypeProblem(
                    LT(1),
                    collectionExpression.getNodeID().getParaphrase());
            addProblem(problem);
        }
    }

    /**
     * Enter a "group" and increment the depth counter.
     */
    protected final void enterGroup()
    {
        groupDepth++;
    }

    /**
     * Leave a "group" and decrement the depth counter.
     */
    protected final void leaveGroup()
    {
        groupDepth--;
    }

    /**
     * Check if class definition is allowed.
     * 
     * @param keywordClass {@code class} keyword token.
     */
    protected final void enterClassDefinition(final ASToken keywordClass)
    {
        if (!isGlobalContext())
            addProblem(new NestedClassProblem(keywordClass));
    }

    /**
     * Check if interface definition is allowed.
     * 
     * @param keywordInterface {@code interface} keyword token.
     */
    protected final void enterInterfaceDefinition(final ASToken keywordInterface)
    {
        if (!isGlobalContext())
            addProblem(new NestedInterfaceProblem(keywordInterface));
    }

    /**
     * Decrement package depth counter.
     */
    protected final void leavePackage()
    {
        assert blockDepth >= 0 : "package depth should never be negative";
        packageDepth = packageDepth > 0 ? packageDepth - 1 : 0;
    }

    /**
     * A syntax tree is in a global context if it is nested by a <i>program</i>
     * without crossing a <i>block</i>, or nested by the <i>block</i> of a
     * <i>package directive</i> without crossing another <i>block</i>.
     * <p>
     * Note that directive-level blocks are called "groups". Entering a group
     * doesn't cause the parser to leave global context.
     * 
     * @return True if the current context is global context.
     */
    protected final boolean isGlobalContext()
    {
        assert blockDepth >= 0 : "block depth should never be negative";
        assert packageDepth <= blockDepth : "package depth can't be greater than block depth";
        assert groupDepth <= blockDepth : "group depth can't be greater than block depth";
        assert packageDepth + groupDepth <= blockDepth : "invalid state of block depth";

        return blockDepth - packageDepth - groupDepth == 0;
    }

    /**
     * Disambiguate between a function definition and a function closure.
     * 
     * @return True if the next "function" keyword defines a closure.
     */
    protected final boolean isFunctionClosure()
    {
        return LA(1) == TOKEN_KEYWORD_FUNCTION && (LA(2) == TOKEN_PAREN_OPEN || buffer.previous().canPreceedAnonymousFunction());
    }

    /**
     * Ignore missing semicolons in the following two cases:
     * 
     * <pre>
     * do x++ while (x<10);     // after x++
     * if (x<10) x++ else x--;  // after x++
     * </pre>
     */
    protected final void afterInnerSubstatement()
    {
        final ICompilerProblem lastError = Iterables.getLast(errors, null);
        if (lastError != null && lastError instanceof CanNotInsertSemicolonProblem)
        {
            // Ideally, we should compare absolute offset. However, CMP-1828 requires
            // all syntax problems to have local offset.
            final int problemEnd = ((CanNotInsertSemicolonProblem)lastError).getEnd();
            final int lastTokenEnd = LT(1).getLocalEnd();
            if (problemEnd == lastTokenEnd)
                errors.remove(lastError);
        }
    }

    /**
     * Recover from metadata parsing failure. Code model require error recovery
     * logic for the following case:
     * 
     * <pre>
     * [
     * function hello():void {}
     * </pre>
     * 
     * The incomplete square bracket is expected to be matched as part of a
     * metadata tag, and the following function definition is properly built.
     * However, function objects in array literals are valid:
     * 
     * <pre>
     * var fs = [ function f1():void{}, function f2():void{} ];
     * </pre>
     * 
     * In order to appease code hinting, the recovery logic will hoist the
     * elements in the failed array literal into the parent node of the array
     * literal node.
     * 
     * @param container Parent node of array literal node.
     * @param arrayLiteralNode Array literal node, whose contents will be
     * hoisted.
     */
    protected final void recoverFromMetadataTag(final ContainerNode container, final ArrayLiteralNode arrayLiteralNode)
    {
        if (container == null || arrayLiteralNode == null)
            return;

        // Hoist content associated with the failed array literal.
        final ContainerNode contents = arrayLiteralNode.getContentsNode();
        for (int i = 0; i < contents.getChildCount(); i++)
        {
            final IASNode child = contents.getChild(i);
            if (child.getNodeID() == ASTNodeID.FunctionObjectID)
                container.addChild(((FunctionObjectNode)child).getFunctionNode());
            else
                container.addChild((NodeBase)child);
        }

        // Handle special case:
        // [
        // var x:int;
        // The keyword 'var' is turned into a identifier by 'handleParsingError()'.
        final ASToken lookback = buffer.previous();
        if (lookback != null &&
            lookback.getType() == TOKEN_IDENTIFIER &&
            lookback.getText().equals(IASKeywordConstants.VAR))
        {
            lookback.setType(TOKEN_KEYWORD_VAR);
            buffer.rewind(buffer.mark() - 1);
        }
    }

    /**
     * Determine if the parser should deploy an error trap for a
     * typing-in-progress metadata tag on a definition item. For example:
     * 
     * <pre>
     * class T
     * {
     *     [
     *     public var name:String;
     *     
     *     [
     *     public override function hello():void {}
     *     
     *     [
     *     function process();
     * }
     * </pre>
     * 
     * The error trap is enabled when the "[" token is the only token on the
     * current line, and the next token can start a definition item.
     */
    protected final boolean isIncompleteMetadataTagOnDefinition()
    {
        if (LA(1) == TOKEN_SQUARE_OPEN &&
            LT(1).getLine() > buffer.previous().getLine() &&
            LT(2).getLine() > LT(1).getLine())
        {
            // Note that function object is allowed inside array literal.
            switch (LA(2))
            {
                case TOKEN_KEYWORD_VAR:
                case TOKEN_KEYWORD_CLASS:
                case TOKEN_KEYWORD_INTERFACE:
                case TOKEN_NAMESPACE_ANNOTATION:
                case TOKEN_MODIFIER_DYNAMIC:
                case TOKEN_MODIFIER_FINAL:
                case TOKEN_MODIFIER_NATIVE:
                case TOKEN_MODIFIER_OVERRIDE:
                case TOKEN_MODIFIER_STATIC:
                case TOKEN_MODIFIER_VIRTUAL:
                case TOKEN_MODIFIER_ABSTRACT:
                    return true;
            }
        }
        return false;
    }

    /**
     * All tags with binding names such as {@code < foo}>} use this name in the
     * XML tag stack.
     */
    private static final String TAG_NAME_BINDING = "{...}";

    /**
     * Called when a {@code <foo} token is encountered.
     * 
     * @param token {@code TOKEN_E4X_OPEN_TAG_START} token.
     */
    protected final void xmlTagOpen(final ASToken token)
    {
        assert token.getType() == TOKEN_E4X_OPEN_TAG_START : "unexpected token type: " + token;
        assert token.getText().startsWith("<") : "unexpected token text: " + token;
        final String tagName = token.getText().substring(1);
        xmlTags.push(new XMLTagInfo(tagName, token));
    }

    /**
     * Called when a {@code <} token is encountered.
     * 
     * @param token {@code HIDDEN_TOKEN_E4X} token.
     */
    protected final void xmlTagOpenBinding(final ASToken token)
    {
        assert token.getType() == HIDDEN_TOKEN_E4X : "unexpected token " + token;
        assert token.getText().equals("<") : "unexpected token text: " + token;
        xmlTags.push(new XMLTagInfo(TAG_NAME_BINDING, token));
    }

    /**
     * Called when a {@code </foo} token is encountered.
     * 
     * @param token {@code TOKEN_E4X_CLOSE_TAG_START} token.
     */
    protected final void xmlTagClose(final ASToken token)
    {
        assert token.getType() == TOKEN_E4X_CLOSE_TAG_START : "unexpected token " + token;
        assert token.getText().startsWith("</") : "unexpected token text: " + token;
        final String tagName = token.getText().substring(2);
        if (!xmlTags.isEmpty())
        {
            final XMLTagInfo openTag = xmlTags.pop();
            if (TAG_NAME_BINDING.equals(openTag.name) || tagName.isEmpty())
            {
                // At least one of the open or close tag's name is a binding.
                // No need to check if tags match.
                return;
            }
            else if (openTag.name.equals(tagName))
            {
                // Open and close tags match.
                return;
            }
            else
            {
                addProblem(new XMLOpenCloseTagNotMatchProblem(token));
                return;
            }
        }
        else
        {
            addProblem(new SyntaxProblem(token));
        }
    }

    /**
     * Called when a {@code />} token is encountered.
     * 
     * @param token {@code TOKEN_E4X_EMPTY_TAG_END} token.
     */
    protected final void xmlEmptyTagEnd(final ASToken token)
    {
        assert token.getType() == TOKEN_E4X_EMPTY_TAG_END : "unexpected token " + token;
        assert token.getText().endsWith("/>") : "unexpected token text: " + token;
        if (!xmlTags.isEmpty())
        {
            xmlTags.pop();
        }
    }

    /**
     * Called when start parsing an XML literal.
     */
    protected final void enterXMLLiteral()
    {
        assert xmlTags.isEmpty() : "Invalid state: must clear tag stack after each XML literal.";
        xmlTags.clear();
    }

    /**
     * Called when finish parsing an XML literal. This method validates the XML.
     */
    protected final void leaveXMLLiteral()
    {
        while (!xmlTags.isEmpty())
        {
            final XMLTagInfo openTag = xmlTags.pop();
            final ICompilerProblem problem = new XMLOpenCloseTagNotMatchProblem(openTag.location);
            addProblem(problem);
        }
    }

    /**
     * A tuple of XML tag name and its source location.
     */
    private static final class XMLTagInfo
    {
        /**
         * XML tag name.
         */
        final String name;
        /**
         * XML tag location.
         */
        final ASToken location;

        XMLTagInfo(final String name, final ASToken location)
        {
            this.name = name;
            this.location = location;
        }
    }

    /**
     * Syntactic predicate for CMP-335.
     * 
     * @return True if the next token is "public" namespace token.
     */
    protected final boolean isNextTokenPublicNamespace()
    {
        final ASToken token = LT(1);
        return TOKEN_NAMESPACE_ANNOTATION == token.getType() &&
               IASKeywordConstants.PUBLIC.equals(token.getText());
    }

    /**
     * Check if the next attribute definition is gated with a configuration
     * condition variable. If it is, then return the evaluated result of the
     * condition.
     * 
     * @param containerNode parent node
     * @return True if the attributed definition is enabled.
     */
    protected final boolean isDefinitionEnabled(final ContainerNode containerNode)
    {
        assert containerNode != null : "Container node can't be null.";
        final int childCount = containerNode.getChildCount();
        if (childCount > 0)
        {
            final IASNode lastChild = containerNode.getChild(childCount - 1);
            if (lastChild.getNodeID() == ASTNodeID.LiteralBooleanID)
            {
                // evaluate
                final boolean eval = Boolean.parseBoolean(((LiteralNode)lastChild).getValue());
                // remove the configuration condition node
                containerNode.removeItem((NodeBase)lastChild);
                containerNode.setRemovedConditionalCompileNode(true);
                return eval;
            }
        }
        return true;
    }

    /**
     * Parses an ActionScript3 file and populate the FileNode. This method
     * forces the parser to retry after
     * {@code fileLevelDirectives(ContainerNode)} fails. Before retrying, the
     * parser makes sure one and only one
     * {@link ExtraCharactersAfterEndOfProgramProblem} is logged. Then, it
     * discards the offending token and continue matching at "directive" level.
     * <p>
     * I didn't write this as a regular ANTLR rule because the ANTLR-generated
     * code wouldn't enter {@code fileLevelDirectives(ContainerNode)} if the
     * lookahead is not one of the tokens in the "start set".
     */
    public final void file(ContainerNode c) throws RecognitionException, TokenStreamException
    {
        while (LA(1) != EOF)
        {
            fileLevelDirectives(c);
            if (LA(1) != EOF)
            {
                foundExtraCharacterAfterEndOfProgram(LT(1));
                consume();
            }
        }
    }

    /**
     * @return true when we are parsing project vars (like the command line)
     */
    public final boolean isParsingProjectConfigVariables()
    {
        return parsingProjectConfigVariables;
    }
}
