| /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. |
| * Use of this file is governed by the BSD 3-clause license that |
| * can be found in the LICENSE.txt file in the project root. |
| */ |
| using System; |
| using System.Collections.Generic; |
| using Antlr4.Runtime; |
| using Antlr4.Runtime.Misc; |
| using Antlr4.Runtime.Sharpen; |
| using Antlr4.Runtime.Tree; |
| |
| namespace Antlr4.Runtime |
| { |
| /// <summary>A rule invocation record for parsing.</summary> |
| /// <remarks> |
| /// A rule invocation record for parsing. |
| /// Contains all of the information about the current rule not stored in the |
| /// RuleContext. It handles parse tree children list, Any ATN state |
| /// tracing, and the default values available for rule indications: |
| /// start, stop, rule index, current alt number, current |
| /// ATN state. |
| /// Subclasses made for each rule and grammar track the parameters, |
| /// return values, locals, and labels specific to that rule. These |
| /// are the objects that are returned from rules. |
| /// Note text is not an actual field of a rule return value; it is computed |
| /// from start and stop using the input stream's toString() method. I |
| /// could add a ctor to this so that we can pass in and store the input |
| /// stream, but I'm not sure we want to do that. It would seem to be undefined |
| /// to get the .text property anyway if the rule matches tokens from multiple |
| /// input streams. |
| /// I do not use getters for fields of objects that are used simply to |
| /// group values such as this aggregate. The getters/setters are there to |
| /// satisfy the superclass interface. |
| /// </remarks> |
| public class ParserRuleContext : RuleContext |
| { |
| public static readonly Antlr4.Runtime.ParserRuleContext EMPTY = new Antlr4.Runtime.ParserRuleContext(); |
| |
| /// <summary> |
| /// If we are debugging or building a parse tree for a visitor, |
| /// we need to track all of the tokens and rule invocations associated |
| /// with this rule's context. |
| /// </summary> |
| /// <remarks> |
| /// If we are debugging or building a parse tree for a visitor, |
| /// we need to track all of the tokens and rule invocations associated |
| /// with this rule's context. This is empty for parsing w/o tree constr. |
| /// operation because we don't the need to track the details about |
| /// how we parse this rule. |
| /// </remarks> |
| public IList<IParseTree> children; |
| |
| /// <summary> |
| /// For debugging/tracing purposes, we want to track all of the nodes in |
| /// the ATN traversed by the parser for a particular rule. |
| /// </summary> |
| /// <remarks> |
| /// For debugging/tracing purposes, we want to track all of the nodes in |
| /// the ATN traversed by the parser for a particular rule. |
| /// This list indicates the sequence of ATN nodes used to match |
| /// the elements of the children list. This list does not include |
| /// ATN nodes and other rules used to match rule invocations. It |
| /// traces the rule invocation node itself but nothing inside that |
| /// other rule's ATN submachine. |
| /// There is NOT a one-to-one correspondence between the children and |
| /// states list. There are typically many nodes in the ATN traversed |
| /// for each element in the children list. For example, for a rule |
| /// invocation there is the invoking state and the following state. |
| /// The parser setState() method updates field s and adds it to this list |
| /// if we are debugging/tracing. |
| /// This does not trace states visited during prediction. |
| /// </remarks> |
| private IToken _start; |
| |
| /// <summary> |
| /// For debugging/tracing purposes, we want to track all of the nodes in |
| /// the ATN traversed by the parser for a particular rule. |
| /// </summary> |
| /// <remarks> |
| /// For debugging/tracing purposes, we want to track all of the nodes in |
| /// the ATN traversed by the parser for a particular rule. |
| /// This list indicates the sequence of ATN nodes used to match |
| /// the elements of the children list. This list does not include |
| /// ATN nodes and other rules used to match rule invocations. It |
| /// traces the rule invocation node itself but nothing inside that |
| /// other rule's ATN submachine. |
| /// There is NOT a one-to-one correspondence between the children and |
| /// states list. There are typically many nodes in the ATN traversed |
| /// for each element in the children list. For example, for a rule |
| /// invocation there is the invoking state and the following state. |
| /// The parser setState() method updates field s and adds it to this list |
| /// if we are debugging/tracing. |
| /// This does not trace states visited during prediction. |
| /// </remarks> |
| private IToken _stop; |
| |
| /// <summary>The exception that forced this rule to return.</summary> |
| /// <remarks> |
| /// The exception that forced this rule to return. If the rule successfully |
| /// completed, this is |
| /// <see langword="null"/> |
| /// . |
| /// </remarks> |
| public RecognitionException exception; |
| |
| public ParserRuleContext() |
| { |
| } |
| |
| public static Antlr4.Runtime.ParserRuleContext EmptyContext |
| { |
| get |
| { |
| // public List<Integer> states; |
| return EMPTY; |
| } |
| } |
| |
| /// <summary> |
| /// COPY a ctx (I'm deliberately not using copy constructor) to avoid |
| /// confusion with creating node with parent. Does not copy children. |
| /// |
| /// This is used in the generated parser code to flip a generic XContext |
| /// node for rule X to a YContext for alt label Y. In that sense, it is |
| /// not really a generic copy function. |
| /// |
| /// If we do an error sync() at start of a rule, we might add error nodes |
| /// to the generic XContext so this function must copy those nodes to |
| /// the YContext as well else they are lost! |
| /// </summary> |
| public virtual void CopyFrom(Antlr4.Runtime.ParserRuleContext ctx) |
| { |
| // from RuleContext |
| this.Parent = ctx.Parent; |
| this.invokingState = ctx.invokingState; |
| this._start = ctx._start; |
| this._stop = ctx._stop; |
| |
| // copy any error nodes to alt label node |
| if (ctx.children != null) |
| { |
| children = new List<IParseTree>(); |
| // reset parent pointer for any error nodes |
| foreach (var child in ctx.children) |
| { |
| var errorChildNode = child as ErrorNodeImpl; |
| if (errorChildNode != null) |
| { |
| children.Add(errorChildNode); |
| errorChildNode.Parent = this; |
| } |
| } |
| } |
| } |
| |
| public ParserRuleContext(Antlr4.Runtime.ParserRuleContext parent, int invokingStateNumber) |
| : base(parent, invokingStateNumber) |
| { |
| } |
| |
| // Double dispatch methods for listeners |
| public virtual void EnterRule(IParseTreeListener listener) |
| { |
| } |
| |
| public virtual void ExitRule(IParseTreeListener listener) |
| { |
| } |
| |
| /// <summary>Does not set parent link; other add methods do that</summary> |
| public virtual void AddChild(ITerminalNode t) |
| { |
| if (children == null) |
| { |
| children = new List<IParseTree>(); |
| } |
| |
| children.Add(t); |
| } |
| |
| public virtual void AddChild(RuleContext ruleInvocation) |
| { |
| if (children == null) |
| { |
| children = new List<IParseTree>(); |
| } |
| |
| children.Add(ruleInvocation); |
| } |
| |
| /// <summary> |
| /// Used by enterOuterAlt to toss out a RuleContext previously added as |
| /// we entered a rule. |
| /// </summary> |
| /// <remarks> |
| /// Used by enterOuterAlt to toss out a RuleContext previously added as |
| /// we entered a rule. If we have # label, we will need to remove |
| /// generic ruleContext object. |
| /// </remarks> |
| public virtual void RemoveLastChild() |
| { |
| if (children != null) |
| { |
| children.RemoveAt(children.Count - 1); |
| } |
| } |
| |
| // public void trace(int s) { |
| // if ( states==null ) states = new ArrayList<Integer>(); |
| // states.add(s); |
| // } |
| public virtual ITerminalNode AddChild(IToken matchedToken) |
| { |
| TerminalNodeImpl t = new TerminalNodeImpl(matchedToken); |
| AddChild(t); |
| t.Parent = this; |
| return t; |
| } |
| |
| public virtual IErrorNode AddErrorNode(IToken badToken) |
| { |
| ErrorNodeImpl t = new ErrorNodeImpl(badToken); |
| AddChild(t); |
| t.Parent = this; |
| return t; |
| } |
| |
| |
| public override IParseTree GetChild(int i) |
| { |
| return children != null && i >= 0 && i < children.Count ? children[i] : null; |
| } |
| |
| public virtual T GetChild<T>(int i) |
| where T : IParseTree |
| { |
| if (children == null || i < 0 || i >= children.Count) |
| { |
| return default(T); |
| } |
| |
| int j = -1; |
| // what element have we found with ctxType? |
| foreach (IParseTree o in children) |
| { |
| if (o is T) |
| { |
| j++; |
| if (j == i) |
| { |
| return (T) o; |
| } |
| } |
| } |
| |
| return default(T); |
| } |
| |
| public virtual ITerminalNode GetToken(int ttype, int i) |
| { |
| if (children == null || i < 0 || i >= children.Count) |
| { |
| return null; |
| } |
| |
| int j = -1; |
| // what token with ttype have we found? |
| foreach (IParseTree o in children) |
| { |
| if (o is ITerminalNode) |
| { |
| ITerminalNode tnode = (ITerminalNode) o; |
| IToken symbol = tnode.Symbol; |
| if (symbol.Type == ttype) |
| { |
| j++; |
| if (j == i) |
| { |
| return tnode; |
| } |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| public virtual ITerminalNode[] GetTokens(int ttype) |
| { |
| if (children == null) |
| { |
| return Collections.EmptyList<ITerminalNode>(); |
| } |
| |
| List<ITerminalNode> tokens = null; |
| foreach (IParseTree o in children) |
| { |
| if (o is ITerminalNode) |
| { |
| ITerminalNode tnode = (ITerminalNode) o; |
| IToken symbol = tnode.Symbol; |
| if (symbol.Type == ttype) |
| { |
| if (tokens == null) |
| { |
| tokens = new List<ITerminalNode>(); |
| } |
| |
| tokens.Add(tnode); |
| } |
| } |
| } |
| |
| if (tokens == null) |
| { |
| return Collections.EmptyList<ITerminalNode>(); |
| } |
| |
| return tokens.ToArray(); |
| } |
| |
| public virtual T GetRuleContext<T>(int i) |
| where T : Antlr4.Runtime.ParserRuleContext |
| { |
| return GetChild<T>(i); |
| } |
| |
| public virtual T[] GetRuleContexts<T>() |
| where T : Antlr4.Runtime.ParserRuleContext |
| { |
| if (children == null) |
| { |
| return Collections.EmptyList<T>(); |
| } |
| |
| List<T> contexts = null; |
| foreach (IParseTree o in children) |
| { |
| if (o is T) |
| { |
| if (contexts == null) |
| { |
| contexts = new List<T>(); |
| } |
| |
| contexts.Add((T) o); |
| } |
| } |
| |
| if (contexts == null) |
| { |
| return Collections.EmptyList<T>(); |
| } |
| |
| return contexts.ToArray(); |
| } |
| |
| public override int ChildCount |
| { |
| get { return children != null ? children.Count : 0; } |
| } |
| |
| public override Interval SourceInterval |
| { |
| get |
| { |
| if (_start == null || _stop == null) |
| { |
| return Interval.Invalid; |
| } |
| |
| return Interval.Of(_start.TokenIndex, _stop.TokenIndex); |
| } |
| } |
| |
| public virtual IToken Start |
| { |
| get { return _start; } |
| set { _start = value; } |
| } |
| |
| public virtual IToken Stop |
| { |
| get { return _stop; } |
| set { _stop = value; } |
| } |
| |
| /// <summary>Used for rule context info debugging during parse-time, not so much for ATN debugging</summary> |
| public virtual string ToInfoString(Parser recognizer) |
| { |
| List<string> rules = new List<string>(recognizer.GetRuleInvocationStack(this)); |
| rules.Reverse(); |
| return "ParserRuleContext" + rules + "{" + "start=" + _start + ", stop=" + _stop + '}'; |
| } |
| } |
| } |