blob: 5f91e20f6741c710ee9ab1b0066471f97e69ce2c [file] [log] [blame] [edit]
/* 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.
*/
namespace Antlr4.Runtime.Tree
{
public class ParseTreeWalker
{
public static readonly ParseTreeWalker Default = new ParseTreeWalker();
/// <summary>
/// Performs a walk on the given parse tree starting at the root and going down recursively
/// with depth-first search. On each node,
/// <see cref="ParseTreeWalker.EnterRule(IParseTreeListener, IRuleNode)"/> is called before
/// recursively walking down into child nodes, then
/// <see cref="ParseTreeWalker.ExitRule(IParseTreeListener, IRuleNode)"/>
/// is called after the recursive call to wind up.
/// </summary>
/// <param name="listener">The listener used by the walker to process grammar rules</param>
/// <param name="t">The parse tree to be walked on</param>
public virtual void Walk(IParseTreeListener listener, IParseTree t)
{
if (t is IErrorNode)
{
listener.VisitErrorNode((IErrorNode)t);
return;
}
else
{
if (t is ITerminalNode)
{
listener.VisitTerminal((ITerminalNode)t);
return;
}
}
IRuleNode r = (IRuleNode)t;
EnterRule(listener, r);
int n = r.ChildCount;
for (int i = 0; i < n; i++)
{
Walk(listener, r.GetChild(i));
}
ExitRule(listener, r);
}
/// <summary>
/// Enters a grammar rule by first triggering the generic event
/// <see cref="IParseTreeListener.EnterEveryRule"/>
/// then by triggering the event specific to the given parse tree node
/// </summary>
/// <param name="listener"> The listener responding to the trigger events </param>
/// <param name="r">The grammar rule containing the rule context</param>
protected internal virtual void EnterRule(IParseTreeListener listener, IRuleNode r)
{
ParserRuleContext ctx = (ParserRuleContext)r.RuleContext;
listener.EnterEveryRule(ctx);
ctx.EnterRule(listener);
}
/// <summary>
/// Exits a grammar rule by first triggering the event specific to the given parse tree node
/// then by triggering the generic event
/// <see cref="IParseTreeListener.ExitEveryRule"/>
/// </summary>
/// <param name="listener"> The listener responding to the trigger events </param>
/// <param name="r">The grammar rule containing the rule context</param>
protected internal virtual void ExitRule(IParseTreeListener listener, IRuleNode r)
{
ParserRuleContext ctx = (ParserRuleContext)r.RuleContext;
ctx.ExitRule(listener);
listener.ExitEveryRule(ctx);
}
}
}