All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sk.uniq.protobuf.parser.impl.ProtoParserImpl Maven / Gradle / Ivy

The newest version!
/* 
 * Copyright 2016 Jakub Herkel.
 *
 * Licensed 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 sk.uniq.protobuf.parser.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.BailErrorStrategy;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.ConsoleErrorListener;
import org.antlr.v4.runtime.DefaultErrorStrategy;
import org.antlr.v4.runtime.DiagnosticErrorListener;
import org.antlr.v4.runtime.atn.PredictionMode;
import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.antlr.v4.runtime.tree.ParseTree;
import sk.uniq.protobuf.grammar.ProtoLexer;
import sk.uniq.protobuf.parser.ProtoParserOptions;
import sk.uniq.protobuf.parser.ProtoParserResult;
import sk.uniq.protobuf.schema.ProtoFile;
import sk.uniq.protobuf.parser.ProtoErrorListener;
import sk.uniq.protobuf.parser.ProtoParser;

/**
 *
 * @author jherkel
 */
public class ProtoParserImpl implements ProtoParser {

    private final List listeners = new ArrayList<>();
    private final ProtoParserOptions parserOptions;
    private final String filename;

    /**
     *
     * @param filename proto file name
     * @param parserOptions
     */
    public ProtoParserImpl(String filename, ProtoParserOptions parserOptions) {
        this.filename = filename;
        this.parserOptions = parserOptions;
    }

    /**
     *
     * @return
     */
    @Override
    public ProtoParserOptions getParserOptions() {
        return parserOptions;
    }

    /**
     *
     * @param inputStream
     * @return
     * @throws IOException
     */
    @Override
    public ProtoParserResult parse(InputStream inputStream) throws IOException {
        long startTime = System.nanoTime();
        ANTLRInputStream stream = new ANTLRInputStream(inputStream);
        return parse(protoLexer(stream), startTime);
    }

    /**
     *
     * @param file the file to be opened for reading
     * @return
     * @throws IOException
     */
    @Override
    public ProtoParserResult parse(File file) throws IOException {
        long startTime = System.nanoTime();
        try (InputStream fileStream = new FileInputStream(file)) {
            ANTLRInputStream stream = new ANTLRInputStream(fileStream);
            return parse(protoLexer(stream), startTime);
        }
    }

    /**
     *
     * @param text
     * @return
     */
    @Override
    public ProtoParserResult parse(String text) {
        long startTime = System.nanoTime();
        ANTLRInputStream stream = new ANTLRInputStream(text);
        return parse(protoLexer(stream), startTime);
    }

    private ProtoLexer protoLexer(CharStream stream) {
        ProtoLexer lexer = new ProtoLexer(stream);
        return lexer;
    }

    private ProtoParserResult parse(ProtoLexer lexer, long startTime) {
        ErrorListener errorListener = new ErrorListener(listeners);
        lexer.removeErrorListeners();
        lexer.addErrorListener(errorListener);
        CommonTokenStream tokenStream = new CommonTokenStream(lexer);
        sk.uniq.protobuf.grammar.ProtoParser parser = new sk.uniq.protobuf.grammar.ProtoParser(tokenStream);
        parser.removeErrorListeners();
        parser.addErrorListener(errorListener);
        if (parserOptions.isDebugOutput() == true) {
            parser.addErrorListener(new ConsoleErrorListener());
            parser.addErrorListener(new DiagnosticErrorListener());
        }
        // convert parser to ProtoFile
        ParseTree tree;
        try {
            parser.getInterpreter().setPredictionMode(PredictionMode.SLL);
            parser.setErrorHandler(new BailErrorStrategy());
            tree = parser.proto();
        } catch (ParseCancellationException ex) {
            tokenStream.reset(); // rewind input stream
            parser.reset();
            parser.setErrorHandler(new DefaultErrorStrategy());
            if (parserOptions.isDebugOutput() == true) {
                parser.getInterpreter().setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);
            } else {
                parser.getInterpreter().setPredictionMode(PredictionMode.LL);
            }
            tree = parser.proto();
        }
        ProtoFile ret = (ProtoFile) new ProtoFileVisitor(filename, this, tokenStream,errorListener).visit(tree);
        long stopTime = System.nanoTime();
        return ProtoParserResult.good(ret, TimeUnit.MILLISECONDS.convert(stopTime - startTime, TimeUnit.NANOSECONDS));
    }

    /**
     *
     * @param listener
     */
    @Override
    public void addListener(ProtoErrorListener listener) {
        listeners.add(listener);
    }

    /**
     *
     * @param listener
     */
    @Override
    public void removeListener(ProtoErrorListener listener) {
        listeners.remove(listener);

    }

    /**
     *
     */
    @Override
    public void removeAllListeners() {
        listeners.clear();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy