private static (IParseTree parseTree, TokenStreamRewriter rewriter) ParseInternal(ParserMode mode, VBAParser parser, CommonTokenStream tokenStream, ParserStartRule startRule) { if (mode == ParserMode.Ll) { parser.Interpreter.PredictionMode = PredictionMode.Ll; } else { parser.Interpreter.PredictionMode = PredictionMode.Sll; } var tree = startRule.Invoke(parser); return(tree, new TokenStreamRewriter(tokenStream)); }
/// <summary> /// Parses the supplied code. /// </summary> /// <param name="code">The code to parse.</param> /// <param name="startRule">The parser rule to begin the process with.</param> /// <param name="mode">(Optional) The parser mode to run.</param> public static (IParseTree parseTree, TokenStreamRewriter rewriter) Parse(string code, ParserStartRule startRule, ParserMode mode = ParserMode.Default) { var tokenStreamProvider = new SimpleVBAModuleTokenStreamProvider(); var tokenStream = tokenStreamProvider.Tokens(code ?? string.Empty); var parser = new VBAParser(tokenStream); try { return(ParseInternal(ParserMode.Sll, parser, tokenStream, startRule)); } catch (ParsePassSyntaxErrorException exception) { var actualMode = parser.Interpreter.PredictionMode.ToString().ToUpperInvariant(); System.Diagnostics.Debug.Assert(actualMode == ParserMode.Sll.ToString().ToUpperInvariant()); var message = $"{actualMode} mode failed while parsing the code at symbol {exception.OffendingSymbol.Text} at L{exception.LineNumber}C{exception.Position}. Retrying using LL."; LogAndReset(message, exception, parser, tokenStream); if (parser.Interpreter.PredictionMode == PredictionMode.Sll) { return(ParseInternal(ParserMode.Ll, parser, tokenStream, startRule)); } } catch (Exception exception) { var actualMode = parser.Interpreter.PredictionMode.ToString().ToUpperInvariant(); System.Diagnostics.Debug.Assert(actualMode == ParserMode.Sll.ToString().ToUpperInvariant()); var message = $"{actualMode} mode threw an exception. Retrying LL mode."; LogAndReset(message, exception, parser, tokenStream); if (parser.Interpreter.PredictionMode == PredictionMode.Sll) { return(ParseInternal(ParserMode.Ll, parser, tokenStream, startRule)); } } return(null, null); }