| /* 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.Misc; |
| using Antlr4.Runtime.Sharpen; |
| using Antlr4.Runtime.Tree; |
| using Antlr4.Runtime.Tree.Pattern; |
| |
| namespace Antlr4.Runtime.Tree.Pattern |
| { |
| /// <summary> |
| /// Represents the result of matching a |
| /// <see cref="Antlr4.Runtime.Tree.IParseTree"/> |
| /// against a tree pattern. |
| /// </summary> |
| public class ParseTreeMatch |
| { |
| /// <summary> |
| /// This is the backing field for |
| /// <see cref="Tree()"/> |
| /// . |
| /// </summary> |
| private readonly IParseTree tree; |
| |
| /// <summary> |
| /// This is the backing field for |
| /// <see cref="Pattern()"/> |
| /// . |
| /// </summary> |
| private readonly ParseTreePattern pattern; |
| |
| /// <summary> |
| /// This is the backing field for |
| /// <see cref="Labels()"/> |
| /// . |
| /// </summary> |
| private readonly MultiMap<string, IParseTree> labels; |
| |
| /// <summary> |
| /// This is the backing field for |
| /// <see cref="MismatchedNode()"/> |
| /// . |
| /// </summary> |
| private readonly IParseTree mismatchedNode; |
| |
| /// <summary> |
| /// Constructs a new instance of |
| /// <see cref="ParseTreeMatch"/> |
| /// from the specified |
| /// parse tree and pattern. |
| /// </summary> |
| /// <param name="tree">The parse tree to match against the pattern.</param> |
| /// <param name="pattern">The parse tree pattern.</param> |
| /// <param name="labels"> |
| /// A mapping from label names to collections of |
| /// <see cref="Antlr4.Runtime.Tree.IParseTree"/> |
| /// objects located by the tree pattern matching process. |
| /// </param> |
| /// <param name="mismatchedNode"> |
| /// The first node which failed to match the tree |
| /// pattern during the matching process. |
| /// </param> |
| /// <exception> |
| /// IllegalArgumentException |
| /// if |
| /// <paramref name="tree"/> |
| /// is |
| /// <see langword="null"/> |
| /// </exception> |
| /// <exception> |
| /// IllegalArgumentException |
| /// if |
| /// <paramref name="pattern"/> |
| /// is |
| /// <see langword="null"/> |
| /// </exception> |
| /// <exception> |
| /// IllegalArgumentException |
| /// if |
| /// <paramref name="labels"/> |
| /// is |
| /// <see langword="null"/> |
| /// </exception> |
| public ParseTreeMatch(IParseTree tree, ParseTreePattern pattern, MultiMap<string, IParseTree> labels, IParseTree mismatchedNode) |
| { |
| if (tree == null) |
| { |
| throw new ArgumentException("tree cannot be null"); |
| } |
| if (pattern == null) |
| { |
| throw new ArgumentException("pattern cannot be null"); |
| } |
| if (labels == null) |
| { |
| throw new ArgumentException("labels cannot be null"); |
| } |
| this.tree = tree; |
| this.pattern = pattern; |
| this.labels = labels; |
| this.mismatchedNode = mismatchedNode; |
| } |
| |
| /// <summary> |
| /// Get the last node associated with a specific |
| /// <paramref name="label"/> |
| /// . |
| /// <p>For example, for pattern |
| /// <c><id:ID></c> |
| /// , |
| /// <c>get("id")</c> |
| /// returns the |
| /// node matched for that |
| /// <c>ID</c> |
| /// . If more than one node |
| /// matched the specified label, only the last is returned. If there is |
| /// no node associated with the label, this returns |
| /// <see langword="null"/> |
| /// .</p> |
| /// <p>Pattern tags like |
| /// <c><ID></c> |
| /// and |
| /// <c><expr></c> |
| /// without labels are |
| /// considered to be labeled with |
| /// <c>ID</c> |
| /// and |
| /// <c>expr</c> |
| /// , respectively.</p> |
| /// </summary> |
| /// <param name="label">The label to check.</param> |
| /// <returns> |
| /// The last |
| /// <see cref="Antlr4.Runtime.Tree.IParseTree"/> |
| /// to match a tag with the specified |
| /// label, or |
| /// <see langword="null"/> |
| /// if no parse tree matched a tag with the label. |
| /// </returns> |
| [return: Nullable] |
| public virtual IParseTree Get(string label) |
| { |
| IList<IParseTree> parseTrees = labels.Get(label); |
| if (parseTrees == null || parseTrees.Count == 0) |
| { |
| return null; |
| } |
| return parseTrees[parseTrees.Count - 1]; |
| } |
| |
| // return last if multiple |
| /// <summary>Return all nodes matching a rule or token tag with the specified label.</summary> |
| /// <remarks> |
| /// Return all nodes matching a rule or token tag with the specified label. |
| /// <p>If the |
| /// <paramref name="label"/> |
| /// is the name of a parser rule or token in the |
| /// grammar, the resulting list will contain both the parse trees matching |
| /// rule or tags explicitly labeled with the label and the complete set of |
| /// parse trees matching the labeled and unlabeled tags in the pattern for |
| /// the parser rule or token. For example, if |
| /// <paramref name="label"/> |
| /// is |
| /// <c>"foo"</c> |
| /// , |
| /// the result will contain <em>all</em> of the following.</p> |
| /// <ul> |
| /// <li>Parse tree nodes matching tags of the form |
| /// <c><foo:anyRuleName></c> |
| /// and |
| /// <c><foo:AnyTokenName></c> |
| /// .</li> |
| /// <li>Parse tree nodes matching tags of the form |
| /// <c><anyLabel:foo></c> |
| /// .</li> |
| /// <li>Parse tree nodes matching tags of the form |
| /// <c><foo></c> |
| /// .</li> |
| /// </ul> |
| /// </remarks> |
| /// <param name="label">The label.</param> |
| /// <returns> |
| /// A collection of all |
| /// <see cref="Antlr4.Runtime.Tree.IParseTree"/> |
| /// nodes matching tags with |
| /// the specified |
| /// <paramref name="label"/> |
| /// . If no nodes matched the label, an empty list |
| /// is returned. |
| /// </returns> |
| [return: NotNull] |
| public virtual IList<IParseTree> GetAll(string label) |
| { |
| IList<IParseTree> nodes = labels.Get(label); |
| if (nodes == null) |
| { |
| return Sharpen.Collections.EmptyList<IParseTree>(); |
| } |
| return nodes; |
| } |
| |
| /// <summary>Return a mapping from label → [list of nodes].</summary> |
| /// <remarks> |
| /// Return a mapping from label → [list of nodes]. |
| /// <p>The map includes special entries corresponding to the names of rules and |
| /// tokens referenced in tags in the original pattern. For additional |
| /// information, see the description of |
| /// <see cref="GetAll(string)"/> |
| /// .</p> |
| /// </remarks> |
| /// <returns> |
| /// A mapping from labels to parse tree nodes. If the parse tree |
| /// pattern did not contain any rule or token tags, this map will be empty. |
| /// </returns> |
| [NotNull] |
| public virtual MultiMap<string, IParseTree> Labels |
| { |
| get |
| { |
| return labels; |
| } |
| } |
| |
| /// <summary>Get the node at which we first detected a mismatch.</summary> |
| /// <remarks>Get the node at which we first detected a mismatch.</remarks> |
| /// <returns> |
| /// the node at which we first detected a mismatch, or |
| /// <see langword="null"/> |
| /// if the match was successful. |
| /// </returns> |
| [Nullable] |
| public virtual IParseTree MismatchedNode |
| { |
| get |
| { |
| return mismatchedNode; |
| } |
| } |
| |
| /// <summary>Gets a value indicating whether the match operation succeeded.</summary> |
| /// <remarks>Gets a value indicating whether the match operation succeeded.</remarks> |
| /// <returns> |
| /// |
| /// <see langword="true"/> |
| /// if the match operation succeeded; otherwise, |
| /// <see langword="false"/> |
| /// . |
| /// </returns> |
| public virtual bool Succeeded |
| { |
| get |
| { |
| return mismatchedNode == null; |
| } |
| } |
| |
| /// <summary>Get the tree pattern we are matching against.</summary> |
| /// <remarks>Get the tree pattern we are matching against.</remarks> |
| /// <returns>The tree pattern we are matching against.</returns> |
| [NotNull] |
| public virtual ParseTreePattern Pattern |
| { |
| get |
| { |
| return pattern; |
| } |
| } |
| |
| /// <summary>Get the parse tree we are trying to match to a pattern.</summary> |
| /// <remarks>Get the parse tree we are trying to match to a pattern.</remarks> |
| /// <returns> |
| /// The |
| /// <see cref="Antlr4.Runtime.Tree.IParseTree"/> |
| /// we are trying to match to a pattern. |
| /// </returns> |
| [NotNull] |
| public virtual IParseTree Tree |
| { |
| get |
| { |
| return tree; |
| } |
| } |
| |
| /// <summary><inheritDoc/></summary> |
| public override string ToString() |
| { |
| return string.Format("Match {0}; found {1} labels", Succeeded ? "succeeded" : "failed", Labels.Count); |
| } |
| } |
| } |