org.tvl.goworks.editor.go.parser.CompiledModelParser.java Source code

Java tutorial

Introduction

Here is the source code for org.tvl.goworks.editor.go.parser.CompiledModelParser.java

Source

/*
 *  Copyright (c) 2012 Sam Harwell, Tunnel Vision Laboratories LLC
 *  All rights reserved.
 *
 *  The source code of this document is proprietary work, and is not licensed for
 *  distribution. For information about licensing, contact Sam Harwell at:
 *      sam@tunnelvisionlabs.com
 */
package org.tvl.goworks.editor.go.parser;

import java.util.Collection;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.antlr.netbeans.editor.classification.TokenTag;
import org.antlr.netbeans.editor.tagging.Tagger;
import org.antlr.netbeans.editor.text.DocumentSnapshot;
import org.antlr.netbeans.parsing.spi.BaseParserData;
import org.antlr.netbeans.parsing.spi.ParseContext;
import org.antlr.netbeans.parsing.spi.ParserData;
import org.antlr.netbeans.parsing.spi.ParserDataDefinition;
import org.antlr.netbeans.parsing.spi.ParserResultHandler;
import org.antlr.netbeans.parsing.spi.ParserTaskManager;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.antlr.works.editor.antlr4.classification.TaggerTokenSource;
import org.antlr.works.editor.antlr4.parsing.SyntaxErrorListener;
import org.netbeans.api.annotations.common.NonNull;
import org.openide.filesystems.FileObject;
import org.openide.util.Parameters;
import org.tvl.goworks.editor.go.GoParserDataDefinitions;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.SourceFileContext;

/**
 *
 * @author Sam Harwell
 */
public class CompiledModelParser {
    // -J-Dorg.tvl.goworks.editor.go.parser.CompiledModelParser.level=FINE
    private static final Logger LOGGER = Logger.getLogger(CompiledModelParser.class.getName());

    private final Object lock = new Object();
    private DocumentSnapshot lastSnapshot;
    private CompiledFileModel lastResult;
    private Throwable lastException;

    public void parse(ParserTaskManager taskManager, ParseContext context, DocumentSnapshot snapshot,
            Collection<? extends ParserDataDefinition<?>> requestedData, ParserResultHandler results)
            throws InterruptedException, ExecutionException {

        try {
            if (requestedData.contains(GoParserDataDefinitions.COMPILED_MODEL)) {
                CompiledModel result = parseImpl(taskManager, context, snapshot);
                BaseParserData<CompiledModel> data = new BaseParserData<>(context,
                        GoParserDataDefinitions.COMPILED_MODEL, snapshot, result);
                results.addResult(data);
            }
        } catch (ExecutionException ex) {
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.log(Level.FINE, "An error occurred while parsing.", ex);
            }
        }
    }

    protected CompiledModel parseImpl(@NonNull ParserTaskManager taskManager, ParseContext context,
            DocumentSnapshot snapshot) throws InterruptedException, ExecutionException {

        Parameters.notNull("snapshot", snapshot);

        synchronized (lock) {
            if (snapshot.equals(lastSnapshot)) {
                if (lastException != null) {
                    throw new ExecutionException("An unexpected error occurred.", lastException);
                }

                return new CompiledModel(snapshot, lastResult);
            }

            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.log(Level.FINE, "Reparsing snapshot {0}", snapshot);
            }

            try {
                Future<ParserData<Tagger<TokenTag<Token>>>> futureTokensData = taskManager.getData(snapshot,
                        GoParserDataDefinitions.LEXER_TOKENS);
                Tagger<TokenTag<Token>> tagger = futureTokensData != null ? futureTokensData.get().getData() : null;
                TaggerTokenSource tokenSource = new TaggerTokenSource(tagger, snapshot);
                CommonTokenStream tokenStream = new CommonTokenStream(tokenSource);
                GoParser parser = GoParserFactory.DEFAULT.getParser(tokenStream, ParserConfiguration.FASTEST);
                try {
                    SyntaxErrorListener syntaxErrorListener = new SyntaxErrorListener(snapshot);
                    SourceFileContext sourceFileContext;
                    try {
                        try {
                            sourceFileContext = parser.sourceFile();
                        } catch (ParseCancellationException ex) {
                            if (ex.getCause() instanceof RecognitionException) {
                                // retry with hybrid parser
                                tokenStream.reset();
                                parser = GoParserFactory.DEFAULT.getParser(tokenStream, ParserConfiguration.HYBRID);
                                sourceFileContext = parser.sourceFile();
                            } else {
                                throw ex;
                            }
                        }
                    } catch (ParseCancellationException ex) {
                        if (ex.getCause() instanceof RecognitionException) {
                            // retry with precise parser and default error handler
                            tokenStream.reset();
                            parser = GoParserFactory.DEFAULT.getParser(tokenStream, ParserConfiguration.PRECISE);
                            parser.removeErrorListeners();
                            parser.addErrorListener(syntaxErrorListener);
                            sourceFileContext = parser.sourceFile();
                        } else {
                            throw ex;
                        }
                    }

                    FileObject fileObject = snapshot.getVersionedDocument().getFileObject();
                    Token[] groupTokens = tokenStream.getTokens().toArray(new Token[0]);
                    lastSnapshot = snapshot;
                    lastResult = new CompiledFileModel(sourceFileContext, syntaxErrorListener.getSyntaxErrors(),
                            fileObject, groupTokens);
                    lastException = null;
                    return new CompiledModel(snapshot, lastResult);
                } catch (RecognitionException ex) {
                    if (LOGGER.isLoggable(Level.FINE)) {
                        LOGGER.log(Level.FINE, "A recognition exception occurred while parsing.", ex);
                    }

                    lastSnapshot = snapshot;
                    lastResult = null;
                    lastException = null;
                    return null;
                }
            } catch (InterruptedException | ExecutionException | ParseCancellationException ex) {
                lastSnapshot = snapshot;
                lastResult = null;
                lastException = ex;
                throw new ExecutionException("An unexpected error occurred.", ex);
            }
        }
    }

}