package org.batfish.grammar; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.TokenStream; import org.antlr.v4.runtime.atn.PredictionMode; import org.batfish.common.BatfishException; public abstract class BatfishCombinedParser<P extends BatfishParser, L extends BatfishLexer> { private int _currentModeStart; private final List<String> _errors; private String _input; protected L _lexer; private BatfishLexerErrorListener _lexerErrorListener; protected P _parser; private BatfishParserErrorListener _parserErrorListener; private GrammarSettings _settings; private List<Integer> _tokenModes; protected CommonTokenStream _tokens; private final List<String> _warnings; public BatfishCombinedParser(Class<P> pClass, Class<L> lClass, String input, GrammarSettings settings) { _settings = settings; _tokenModes = new ArrayList<>(); _currentModeStart = 0; _warnings = new ArrayList<>(); _errors = new ArrayList<>(); _input = input; ANTLRInputStream inputStream = new ANTLRInputStream(input); try { _lexer = lClass.getConstructor(CharStream.class) .newInstance(inputStream); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { throw new BatfishException("Error constructing lexer using reflection", e); } _lexer.initErrorListener(this); _tokens = new CommonTokenStream(_lexer); try { _parser = pClass.getConstructor(TokenStream.class) .newInstance(_tokens); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { throw new Error(e); } _parser.initErrorListener(this); _parser.getInterpreter().setPredictionMode(PredictionMode.SLL); } public List<String> getErrors() { return _errors; } public String getInput() { return _input; } public L getLexer() { return _lexer; } public BatfishLexerErrorListener getLexerErrorListener() { return _lexerErrorListener; } public P getParser() { return _parser; } public BatfishParserErrorListener getParserErrorListener() { return _parserErrorListener; } public GrammarSettings getSettings() { return _settings; } public int getTokenMode(Token t) { int tokenIndex = t.getTokenIndex(); if (tokenIndex == -1) { // token probably added manually, not by parser return -1; } if (tokenIndex < _tokenModes.size()) { return _tokenModes.get(tokenIndex); } else { return _lexer._mode; } } public CommonTokenStream getTokens() { return _tokens; } public List<String> getWarnings() { return _warnings; } public abstract ParserRuleContext parse(); public void setLexerErrorListener( BatfishLexerErrorListener lexerErrorListener) { _lexerErrorListener = lexerErrorListener; } public void setParserErrorListener( BatfishParserErrorListener parserErrorListener) { _parserErrorListener = parserErrorListener; } public void updateTokenModes(int mode) { for (int i = _currentModeStart; i <= _tokens.size(); i++) { _tokenModes.add(mode); } _currentModeStart = _tokens.size() + 1; } }