77 changed files with 880 additions and 87 deletions
@ -1,44 +0,0 @@ |
|||||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
|
||||||
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
|
||||||
|
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
|
|
||||||
namespace ICSharpCode.NRefactory.CSharp |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Compares whether two ASTs are structurally identical.
|
|
||||||
/// </summary>
|
|
||||||
public static class AstComparer |
|
||||||
{ |
|
||||||
static HashSet<Type> nodeTypesWithoutExtraInfo = new HashSet<Type> { |
|
||||||
typeof(IdentifierExpression) |
|
||||||
}; |
|
||||||
|
|
||||||
public static bool? AreEqual(AstNode node1, AstNode node2) |
|
||||||
{ |
|
||||||
if (node1 == node2) |
|
||||||
return true; |
|
||||||
if (node1 == null || node1.IsNull || node2 == null || node2.IsNull) |
|
||||||
return false; |
|
||||||
Type nodeType = node1.GetType(); |
|
||||||
if (nodeType != node2.GetType()) |
|
||||||
return false; |
|
||||||
if (node1.Role != node2.Role) |
|
||||||
return false; |
|
||||||
AstNode child1 = node1.FirstChild; |
|
||||||
AstNode child2 = node2.FirstChild; |
|
||||||
bool? result = true; |
|
||||||
while (result != false && (child1 != null || child2 != null)) { |
|
||||||
result &= AreEqual(child1, child2); |
|
||||||
child1 = child1.NextSibling; |
|
||||||
child2 = child2.NextSibling; |
|
||||||
} |
|
||||||
if (nodeTypesWithoutExtraInfo.Contains(nodeType)) |
|
||||||
return result; |
|
||||||
if (nodeType == typeof(Identifier)) |
|
||||||
return ((Identifier)node1).Name == ((Identifier)node2).Name; |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -0,0 +1,26 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.NRefactory.CSharp.PatternMatching |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Matches any node.
|
||||||
|
/// </summary>
|
||||||
|
public class AnyNode : Pattern |
||||||
|
{ |
||||||
|
readonly string groupName; |
||||||
|
|
||||||
|
public AnyNode(string groupName = null) |
||||||
|
{ |
||||||
|
this.groupName = groupName; |
||||||
|
} |
||||||
|
|
||||||
|
protected internal override bool DoMatch(AstNode other, Match match) |
||||||
|
{ |
||||||
|
match.Add(this.groupName, other); |
||||||
|
return other != null && !other.IsNull; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,28 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Linq; |
||||||
|
|
||||||
|
namespace ICSharpCode.NRefactory.CSharp.PatternMatching |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Matches the last entry in the specified named group.
|
||||||
|
/// </summary>
|
||||||
|
public class Backreference : Pattern |
||||||
|
{ |
||||||
|
readonly string referencedGroupName; |
||||||
|
|
||||||
|
public Backreference(string referencedGroupName) |
||||||
|
{ |
||||||
|
if (referencedGroupName == null) |
||||||
|
throw new ArgumentNullException("referencedGroupName"); |
||||||
|
this.referencedGroupName = referencedGroupName; |
||||||
|
} |
||||||
|
|
||||||
|
protected internal override bool DoMatch(AstNode other, Match match) |
||||||
|
{ |
||||||
|
return match[referencedGroupName].Last().Match(other) != null; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,33 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.NRefactory.CSharp.PatternMatching |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Matches one of several alternatives.
|
||||||
|
/// </summary>
|
||||||
|
public class Choice : Pattern |
||||||
|
{ |
||||||
|
public static readonly Role<AstNode> AlternativeRole = new Role<AstNode>("Alternative", AstNode.Null); |
||||||
|
|
||||||
|
public Choice(params AstNode[] alternatives) |
||||||
|
{ |
||||||
|
foreach (AstNode node in alternatives) |
||||||
|
AddChild(node, AlternativeRole); |
||||||
|
} |
||||||
|
|
||||||
|
protected internal override bool DoMatch(AstNode other, Match match) |
||||||
|
{ |
||||||
|
var checkPoint = match.CheckPoint(); |
||||||
|
foreach (AstNode alt in GetChildrenByRole(AlternativeRole)) { |
||||||
|
if (alt.DoMatch(other, match)) |
||||||
|
return true; |
||||||
|
else |
||||||
|
match.RestoreCheckPoint(checkPoint); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,43 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
|
||||||
|
namespace ICSharpCode.NRefactory.CSharp.PatternMatching |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Represents the result of a pattern matching operation.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class Match |
||||||
|
{ |
||||||
|
List<KeyValuePair<string, AstNode>> results = new List<KeyValuePair<string, AstNode>>(); |
||||||
|
|
||||||
|
internal int CheckPoint() |
||||||
|
{ |
||||||
|
return results.Count; |
||||||
|
} |
||||||
|
|
||||||
|
internal void RestoreCheckPoint(int checkPoint) |
||||||
|
{ |
||||||
|
results.RemoveRange(checkPoint, results.Count - checkPoint); |
||||||
|
} |
||||||
|
|
||||||
|
public IEnumerable<AstNode> this[string groupName] { |
||||||
|
get { |
||||||
|
foreach (var pair in results) { |
||||||
|
if (pair.Key == groupName) |
||||||
|
yield return pair.Value; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void Add(string groupName, AstNode node) |
||||||
|
{ |
||||||
|
if (groupName != null && node != null) { |
||||||
|
results.Add(new KeyValuePair<string, AstNode>(groupName, node)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,29 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.NRefactory.CSharp.PatternMatching |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Represents a named node within a pattern.
|
||||||
|
/// </summary>
|
||||||
|
public class NamedNode : Pattern |
||||||
|
{ |
||||||
|
public static readonly Role<AstNode> ElementRole = new Role<AstNode>("Element", AstNode.Null); |
||||||
|
|
||||||
|
readonly string groupName; |
||||||
|
|
||||||
|
public NamedNode(string groupName, AstNode childNode) |
||||||
|
{ |
||||||
|
this.groupName = groupName; |
||||||
|
AddChild(childNode, ElementRole); |
||||||
|
} |
||||||
|
|
||||||
|
protected internal override bool DoMatch(AstNode other, Match match) |
||||||
|
{ |
||||||
|
match.Add(this.groupName, other); |
||||||
|
return GetChildByRole(ElementRole).DoMatch(other, match); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,42 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.NRefactory.CSharp.PatternMatching |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Base class for all patterns.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Pattern : AstNode |
||||||
|
{ |
||||||
|
public override NodeType NodeType { |
||||||
|
get { return NodeType.Pattern; } |
||||||
|
} |
||||||
|
|
||||||
|
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data) |
||||||
|
{ |
||||||
|
return default(S); |
||||||
|
} |
||||||
|
|
||||||
|
public AstType ToType() |
||||||
|
{ |
||||||
|
return new TypePlaceholder(this); |
||||||
|
} |
||||||
|
|
||||||
|
public Expression ToExpression() |
||||||
|
{ |
||||||
|
return new ExpressionPlaceholder(this); |
||||||
|
} |
||||||
|
|
||||||
|
public BlockStatement ToBlock() |
||||||
|
{ |
||||||
|
return new BlockStatementPlaceholder(this); |
||||||
|
} |
||||||
|
|
||||||
|
public VariableInitializer ToVariable() |
||||||
|
{ |
||||||
|
return new VariablePlaceholder(this); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,119 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace ICSharpCode.NRefactory.CSharp.PatternMatching |
||||||
|
{ |
||||||
|
sealed class TypePlaceholder : AstType |
||||||
|
{ |
||||||
|
public static readonly Role<Pattern> PatternRole = new Role<Pattern>("Pattern"); |
||||||
|
|
||||||
|
public TypePlaceholder(Pattern pattern) |
||||||
|
{ |
||||||
|
AddChild(pattern, TypePlaceholder.PatternRole); |
||||||
|
} |
||||||
|
|
||||||
|
public override NodeType NodeType { |
||||||
|
get { return NodeType.Pattern; } |
||||||
|
} |
||||||
|
|
||||||
|
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data) |
||||||
|
{ |
||||||
|
return default(S); |
||||||
|
} |
||||||
|
|
||||||
|
protected internal override bool DoMatch(AstNode other, Match match) |
||||||
|
{ |
||||||
|
return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
sealed class ExpressionPlaceholder : Expression |
||||||
|
{ |
||||||
|
public ExpressionPlaceholder(Pattern pattern) |
||||||
|
{ |
||||||
|
AddChild(pattern, TypePlaceholder.PatternRole); |
||||||
|
} |
||||||
|
|
||||||
|
public override NodeType NodeType { |
||||||
|
get { return NodeType.Pattern; } |
||||||
|
} |
||||||
|
|
||||||
|
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data) |
||||||
|
{ |
||||||
|
return default(S); |
||||||
|
} |
||||||
|
|
||||||
|
protected internal override bool DoMatch(AstNode other, Match match) |
||||||
|
{ |
||||||
|
return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
sealed class StatementPlaceholder : Statement |
||||||
|
{ |
||||||
|
public StatementPlaceholder(Pattern pattern) |
||||||
|
{ |
||||||
|
AddChild(pattern, TypePlaceholder.PatternRole); |
||||||
|
} |
||||||
|
|
||||||
|
public override NodeType NodeType { |
||||||
|
get { return NodeType.Pattern; } |
||||||
|
} |
||||||
|
|
||||||
|
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data) |
||||||
|
{ |
||||||
|
return default(S); |
||||||
|
} |
||||||
|
|
||||||
|
protected internal override bool DoMatch(AstNode other, Match match) |
||||||
|
{ |
||||||
|
return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
sealed class BlockStatementPlaceholder : BlockStatement |
||||||
|
{ |
||||||
|
public BlockStatementPlaceholder(Pattern pattern) |
||||||
|
{ |
||||||
|
AddChild(pattern, TypePlaceholder.PatternRole); |
||||||
|
} |
||||||
|
|
||||||
|
public override NodeType NodeType { |
||||||
|
get { return NodeType.Pattern; } |
||||||
|
} |
||||||
|
|
||||||
|
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data) |
||||||
|
{ |
||||||
|
return default(S); |
||||||
|
} |
||||||
|
|
||||||
|
protected internal override bool DoMatch(AstNode other, Match match) |
||||||
|
{ |
||||||
|
return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
sealed class VariablePlaceholder : VariableInitializer |
||||||
|
{ |
||||||
|
public VariablePlaceholder(Pattern pattern) |
||||||
|
{ |
||||||
|
AddChild(pattern, TypePlaceholder.PatternRole); |
||||||
|
} |
||||||
|
|
||||||
|
public override NodeType NodeType { |
||||||
|
get { return NodeType.Pattern; } |
||||||
|
} |
||||||
|
|
||||||
|
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data) |
||||||
|
{ |
||||||
|
return default(S); |
||||||
|
} |
||||||
|
|
||||||
|
protected internal override bool DoMatch(AstNode other, Match match) |
||||||
|
{ |
||||||
|
return GetChildByRole(TypePlaceholder.PatternRole).DoMatch(other, match); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue