Repository URL to install this package:
|
Version:
2023.12.1 ▾
|
/* 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 + '}';
}
}
}