sk.uniq.protobuf.parser.impl.ProtoParserImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of protobuf-parser Show documentation
Show all versions of protobuf-parser Show documentation
Java parser for Protocol Buffers
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();
}
}