A parser simulator that mimics what ANTLR's generated parser code does.
A parser simulator that mimics what ANTLR's generated parser code does. A ParserATNSimulator is used to make predictions via adaptivePredict but this class moves a pointer through the ATN to simulate parsing. ParserATNSimulator just makes us efficient rather than having to backtrack, for example. This properly creates parse trees even for left recursive rules. We rely on the left recursive rule invocation and special predicate transitions to make left recursive rules work. See TestParserInterpreter for examples.
Inheritance: Parser
Exemplo n.º 1
0
 /// <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);
 }
Exemplo n.º 2
0
        /// <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);
 }
Exemplo n.º 4
0
        /** 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;
        }
Exemplo n.º 5
0
        /** 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;
        }
Exemplo n.º 6
0
 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());
 }