2525import io .trino .sql .tree .RowPattern ;
2626import io .trino .sql .tree .Statement ;
2727import org .antlr .v4 .runtime .ANTLRErrorListener ;
28+ import org .antlr .v4 .runtime .BailErrorStrategy ;
2829import org .antlr .v4 .runtime .BaseErrorListener ;
2930import org .antlr .v4 .runtime .CharStreams ;
3031import org .antlr .v4 .runtime .CommonToken ;
3940import org .antlr .v4 .runtime .atn .PredictionMode ;
4041import org .antlr .v4 .runtime .misc .Interval ;
4142import org .antlr .v4 .runtime .misc .Pair ;
43+ import org .antlr .v4 .runtime .misc .ParseCancellationException ;
4244import org .antlr .v4 .runtime .tree .TerminalNode ;
4345
4446import java .util .Arrays ;
@@ -144,44 +146,16 @@ private Node invokeParser(String name, String sql, Optional<NodeLocation> locati
144146 SqlBaseParser parser = new SqlBaseParser (tokenStream );
145147 initializer .accept (lexer , parser );
146148
147- // Override the default error strategy to not attempt inserting or deleting a token.
148- // Otherwise, it messes up error reporting
149- parser .setErrorHandler (new DefaultErrorStrategy ()
150- {
151- @ Override
152- public Token recoverInline (Parser recognizer )
153- throws RecognitionException
154- {
155- if (nextTokensContext == null ) {
156- throw new InputMismatchException (recognizer );
157- }
158- throw new InputMismatchException (recognizer , nextTokensState , nextTokensContext );
159- }
160- });
161-
162149 parser .addParseListener (new PostProcessor (Arrays .asList (parser .getRuleNames ()), parser ));
163150
164151 lexer .removeErrorListeners ();
165152 lexer .addErrorListener (LEXER_ERROR_LISTENER );
166153
167154 parser .removeErrorListeners ();
168- parser .addErrorListener (PARSER_ERROR_HANDLER );
169155
170156 ParserRuleContext tree ;
171157 try {
172- try {
173- // first, try parsing with potentially faster SLL mode
174- parser .getInterpreter ().setPredictionMode (PredictionMode .SLL );
175- tree = parseFunction .apply (parser );
176- }
177- catch (ParsingException ex ) {
178- // if we fail, parse with LL mode
179- tokenStream .seek (0 ); // rewind input stream
180- parser .reset ();
181-
182- parser .getInterpreter ().setPredictionMode (PredictionMode .LL );
183- tree = parseFunction .apply (parser );
184- }
158+ tree = twoStageParse (parseFunction , parser );
185159 }
186160 catch (ParsingException e ) {
187161 location .ifPresent (statementLocation -> {
@@ -203,6 +177,39 @@ public Token recoverInline(Parser recognizer)
203177 }
204178 }
205179
180+ private static ParserRuleContext twoStageParse (Function <SqlBaseParser , ParserRuleContext > parseFunction , SqlBaseParser parser )
181+ {
182+ try {
183+ // first, try parsing with potentially faster SLL mode
184+ parser .getInterpreter ().setPredictionMode (PredictionMode .SLL );
185+ parser .setErrorHandler (new BailErrorStrategy ());
186+ return parseFunction .apply (parser );
187+ }
188+ catch (ParseCancellationException e ) {
189+ // if we fail, parse with LL mode
190+ parser .reset ();
191+ parser .getInterpreter ().setPredictionMode (PredictionMode .LL );
192+ parser .setErrorHandler (new NonRecoveringErrorStrategy ());
193+ parser .addErrorListener (PARSER_ERROR_HANDLER );
194+ return parseFunction .apply (parser );
195+ }
196+ }
197+
198+ // Override the default error strategy to not attempt inserting or deleting a token.
199+ // Otherwise, it messes up error reporting.
200+ private static final class NonRecoveringErrorStrategy
201+ extends DefaultErrorStrategy
202+ {
203+ @ Override
204+ public Token recoverInline (Parser recognizer )
205+ {
206+ if (nextTokensContext == null ) {
207+ throw new InputMismatchException (recognizer );
208+ }
209+ throw new InputMismatchException (recognizer , nextTokensState , nextTokensContext );
210+ }
211+ }
212+
206213 private static class PostProcessor
207214 extends SqlBaseBaseListener
208215 {
0 commit comments