/// <summary> /// A copy constructor that creates a new parser interpreter by reusing /// the fields of a previous interpreter. /// </summary> /// <remarks> /// A copy constructor that creates a new parser interpreter by reusing /// the fields of a previous interpreter. /// </remarks> /// <param name="old">The interpreter to copy</param> /// <since>4.5</since> public ParserInterpreter(Antlr4.Runtime.ParserInterpreter old) : base(((ITokenStream)old.InputStream)) { this.grammarFileName = old.grammarFileName; this.atn = old.atn; this.pushRecursionContextStates = old.pushRecursionContextStates; this.tokenNames = old.tokenNames; this.ruleNames = old.ruleNames; this.vocabulary = old.vocabulary; Interpreter = new ParserATNSimulator(this, atn); }
/// <summary> /// Given an AmbiguityInfo object that contains information about an /// ambiguous decision event, return the list of ambiguous parse trees. /// </summary> /// <remarks> /// Given an AmbiguityInfo object that contains information about an /// ambiguous decision event, return the list of ambiguous parse trees. /// An ambiguity occurs when a specific token sequence can be recognized /// in more than one way by the grammar. These ambiguities are detected only /// at decision points. /// The list of trees includes the actual interpretation (that for /// the minimum alternative number) and all ambiguous alternatives. /// This method reuses the same physical input token stream used to /// detect the ambiguity by the original parser in the first place. /// This method resets/seeks within but does not alter originalParser. /// The input position is restored upon exit from this method. /// Parsers using a /// <see cref="UnbufferedTokenStream"/> /// may not be able to /// perform the necessary save index() / seek(saved_index) operation. /// The trees are rooted at the node whose start..stop token indices /// include the start and stop indices of this ambiguity event. That is, /// the trees returns will always include the complete ambiguous subphrase /// identified by the ambiguity event. /// Be aware that this method does NOT notify error or parse listeners as /// it would trigger duplicate or otherwise unwanted events. /// This uses a temporary ParserATNSimulator and a ParserInterpreter /// so we don't mess up any statistics, event lists, etc... /// The parse tree constructed while identifying/making ambiguityInfo is /// not affected by this method as it creates a new parser interp to /// get the ambiguous interpretations. /// Nodes in the returned ambig trees are independent of the original parse /// tree (constructed while identifying/creating ambiguityInfo). /// </remarks> /// <param name="originalParser"> /// The parser used to create ambiguityInfo; it /// is not modified by this routine and can be either /// a generated or interpreted parser. It's token /// stream *is* reset/seek()'d. /// </param> /// <param name="ambiguityInfo"> /// The information about an ambiguous decision event /// for which you want ambiguous parse trees. /// </param> /// <exception cref="RecognitionException"> /// Throws upon syntax error while matching /// ambig input. /// </exception> /// <since>4.5</since> public static IList <ParserRuleContext> GetAmbiguousParseTrees(Parser originalParser, AmbiguityInfo ambiguityInfo, int startRuleIndex) { IList <ParserRuleContext> trees = new List <ParserRuleContext>(); int saveTokenInputPosition = ((ITokenStream)originalParser.InputStream).Index; try { // Create a new parser interpreter to parse the ambiguous subphrase ParserInterpreter parser; if (originalParser is ParserInterpreter) { parser = new ParserInterpreter((ParserInterpreter)originalParser); } else { parser = new ParserInterpreter(originalParser.GrammarFileName, originalParser.Vocabulary, Arrays.AsList(originalParser.RuleNames), originalParser.Atn, ((ITokenStream)originalParser.InputStream)); } // Make sure that we don't get any error messages from using this temporary parser parser.RemoveErrorListeners(); parser.RemoveParseListeners(); parser.Interpreter.PredictionMode = PredictionMode.LlExactAmbigDetection; // get ambig trees int alt = ambiguityInfo.AmbiguousAlternatives.NextSetBit(0); while (alt >= 0) { // re-parse input for all ambiguous alternatives // (don't have to do first as it's been parsed, but do again for simplicity // using this temp parser.) parser.Reset(); ((ITokenStream)parser.InputStream).Seek(ambiguityInfo.startIndex); parser.overrideDecision = ambiguityInfo.decision; parser.overrideDecisionInputIndex = ambiguityInfo.startIndex; parser.overrideDecisionAlt = alt; ParserRuleContext t = parser.Parse(startRuleIndex); ParserRuleContext ambigSubTree = Trees.GetRootOfSubtreeEnclosingRegion(t, ambiguityInfo.startIndex, ambiguityInfo.stopIndex); trees.Add(ambigSubTree); alt = ambiguityInfo.AmbiguousAlternatives.NextSetBit(alt + 1); } } finally { ((ITokenStream)originalParser.InputStream).Seek(saveTokenInputPosition); } return(trees); }
/// <summary> /// For repeated use of a tree pattern, compile it to a /// <see cref="ParseTreePattern"/> /// using this method. /// </summary> public virtual ParseTreePattern Compile(string pattern, int patternRuleIndex) { IList<IToken> tokenList = Tokenize(pattern); ListTokenSource tokenSrc = new ListTokenSource(tokenList); CommonTokenStream tokens = new CommonTokenStream(tokenSrc); ParserInterpreter parserInterp = new ParserInterpreter(parser.GrammarFileName, Arrays.AsList(parser.TokenNames), Arrays.AsList(parser.RuleNames), parser.GetATNWithBypassAlts(), tokens); IParseTree tree = null; try { parserInterp.ErrorHandler = new BailErrorStrategy(); tree = parserInterp.Parse(patternRuleIndex); } catch (ParseCanceledException e) { // System.out.println("pattern tree = "+tree.toStringTree(parserInterp)); throw (RecognitionException)e.InnerException; } catch (RecognitionException) { throw; } catch (Exception e) { throw new ParseTreePatternMatcher.CannotInvokeStartRule(e); } // Make sure tree pattern compilation checks for a complete parse if (tokens.La(1) != TokenConstants.Eof) { throw new ParseTreePatternMatcher.StartRuleDoesNotConsumeFullPattern(); } return new ParseTreePattern(this, pattern, patternRuleIndex, tree); }
/** Derive a new parser from an old one that has knowledge of the grammar. * The Grammar object is used to correctly compute outer alternative * numbers for parse tree nodes. A parser of the same type is created * for subclasses of {@link ParserInterpreter}. */ public static ParserInterpreter DeriveTempParserInterpreter(Grammar g, Parser originalParser, ITokenStream tokens) { ParserInterpreter parser; if (originalParser is ParserInterpreter) { Type c = originalParser.GetType(); try { parser = (ParserInterpreter)Activator.CreateInstance(originalParser.GetType(), g, originalParser.Atn, originalParser.InputStream); } catch (Exception e) { throw new ArgumentException("can't create parser to match incoming " + c.Name, e); } } else { // must've been a generated parser char[] serializedAtn = ATNSerializer.GetSerializedAsChars(originalParser.Atn, originalParser.RuleNames); ATN deserialized = new ATNDeserializer().Deserialize(serializedAtn); parser = new ParserInterpreter(originalParser.GrammarFileName, originalParser.Vocabulary, originalParser.RuleNames, deserialized, tokens); } parser.SetInputStream(tokens); // Make sure that we don't get any error messages from using this temporary parser parser.ErrorHandler = new BailErrorStrategy(); parser.RemoveErrorListeners(); parser.RemoveParseListeners(); parser.Interpreter.PredictionMode = PredictionMode.LlExactAmbigDetection; return parser; }
/** Return a list of parse trees, one for each alternative in a decision * given the same input. * * Very similar to {@link #getAllPossibleParseTrees} except * that it re-parses the input for every alternative in a decision, * not just the ambiguous ones (there is no alts parameter here). * This method also tries to reduce the size of the parse trees * by stripping away children of the tree that are completely out of range * of startIndex..stopIndex. Also, because errors are expected, we * use a specialized error handler that more or less bails out * but that also consumes the first erroneous token at least. This * ensures that an error node will be in the parse tree for display. * * NOTES: // we must parse the entire input now with decision overrides // we cannot parse a subset because it could be that a decision // above our decision of interest needs to read way past // lookaheadInfo.stopIndex. It seems like there is no escaping // the use of a full and complete token stream if we are // resetting to token index 0 and re-parsing from the start symbol. // It's not easy to restart parsing somewhere in the middle like a // continuation because our call stack does not match the // tree stack because of left recursive rule rewriting. grrrr! * * @since 4.5.1 */ public static IList<ParserRuleContext> GetLookaheadParseTrees(Grammar g, ParserInterpreter originalParser, ITokenStream tokens, int startRuleIndex, int decision, int startIndex, int stopIndex) { IList<ParserRuleContext> trees = new List<ParserRuleContext>(); // Create a new parser interpreter to parse the ambiguous subphrase ParserInterpreter parser = DeriveTempParserInterpreter(g, originalParser, tokens); DecisionState decisionState = originalParser.Atn.decisionToState[decision]; for (int alt = 1; alt <= decisionState.Transitions.Length; alt++) { // re-parse entire input for all ambiguous alternatives // (don't have to do first as it's been parsed, but do again for simplicity // using this temp parser.) BailButConsumeErrorStrategy errorHandler = new BailButConsumeErrorStrategy(); parser.ErrorHandler = errorHandler; parser.Reset(); parser.AddDecisionOverride(decision, startIndex, alt); ParserRuleContext tt = parser.Parse(startRuleIndex); int stopTreeAt = stopIndex; if (errorHandler.firstErrorTokenIndex >= 0) { stopTreeAt = errorHandler.firstErrorTokenIndex; // cut off rest at first error } Interval overallRange = tt.SourceInterval; if (stopTreeAt > overallRange.b) { // If we try to look beyond range of tree, stopTreeAt must be EOF // for which there is no EOF ref in grammar. That means tree // will not have node for stopTreeAt; limit to overallRange.b stopTreeAt = overallRange.b; } ParserRuleContext subtree = Trees.GetRootOfSubtreeEnclosingRegion(tt, startIndex, stopTreeAt); // Use higher of overridden decision tree or tree enclosing all tokens if (Trees.IsAncestorOf(parser.OverrideDecisionRoot, subtree)) { subtree = parser.OverrideDecisionRoot; } Trees.StripChildrenOutOfRange(subtree, parser.OverrideDecisionRoot, startIndex, stopTreeAt); trees.Add(subtree); } return trees; }
static void Main(string[] args) { Antlr4.Runtime.Parser p = new ParserInterpreter("ECMAScript.g4", new List<string>(), new List<string>(), new ATN(ATNType.Lexer, 100), null); Console.WriteLine(p.ToString()); }