mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
7.9 KiB
115 lines
7.9 KiB
<html> |
|
<head><title>NRefactory Pattern Matching</title></head> |
|
<body> |
|
The pattern matching API for the C# AST is similar to how regular |
|
expressions work in .NET, except that it's working with AstNodes |
|
instead of characters.<br> |
|
First you declare a pattern, for example: "X a = new X(...);".<br> |
|
<span style="color: #000080; ">var</span> pattern = <span |
|
style="color: #008b8b; font-weight: bold; ">new</span> VariableDeclarationStatement <span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">{</span><br> |
|
Type = <span style="color: #008b8b; font-weight: bold; ">new</span> <span |
|
style="color: #191970; font-weight: bold; ">AnyNode</span><span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">(</span><span |
|
style="color: #0000ff; ">"type"</span><span style="color: #235100; |
|
font-weight: normal; font-style: normal; ">),</span><br> |
|
Variables = <span style="color: #235100; font-weight: normal; |
|
font-style: normal; ">{</span><br> |
|
<span style="color: #008b8b; font-weight: bold; ">new</span> VariableInitializer <span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">{</span><br> |
|
Name = Pattern<span style="color: #235100; font-weight: |
|
normal; font-style: normal; ">.</span>AnyString<span style="color: |
|
#235100; font-weight: normal; font-style: normal; ">,</span><br> |
|
Initializer = <span style="color: #008b8b; font-weight: |
|
bold; ">new</span> ObjectCreateExpression <span style="color: |
|
#235100; font-weight: normal; font-style: normal; ">{</span><br> |
|
Type = <span style="color: #008b8b; font-weight: |
|
bold; ">new</span> <span style="color: #191970; font-weight: bold; |
|
">Backreference</span><span style="color: #235100; font-weight: |
|
normal; font-style: normal; ">(</span><span style="color: #0000ff; |
|
">"type"</span><span style="color: #235100; font-weight: normal; |
|
font-style: normal; ">),</span><br> |
|
Arguments = <span style="color: #235100; |
|
font-weight: normal; font-style: normal; ">{</span> <span |
|
style="color: #008b8b; font-weight: bold; ">new</span> <span |
|
style="color: #191970; font-weight: bold; ">Repeat</span><span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">(</span><span |
|
style="color: #008b8b; font-weight: bold; ">new</span> <span |
|
style="color: #191970; font-weight: bold; ">AnyNode</span><span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">())</span> <span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">}</span><br> |
|
Initializer = <span style="color: #008b8b; |
|
font-weight: bold; ">new</span> <span style="color: #191970; |
|
font-weight: bold; ">OptionalNode</span><span style="color: |
|
#235100; font-weight: normal; font-style: normal; ">(</span><span |
|
style="color: #008b8b; font-weight: bold; ">new</span> <span |
|
style="color: #191970; font-weight: bold; ">AnyNode</span><span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">())</span><br> |
|
<span style="color: #235100; font-weight: normal; |
|
font-style: normal; ">}</span><br> |
|
<span style="color: #235100; font-weight: normal; |
|
font-style: normal; ">}</span><br> |
|
<span style="color: #235100; font-weight: normal; font-style: |
|
normal; ">}};</span><br> |
|
<br> |
|
This is a <b>pattern AST</b> - it is a C# AST using the normal C# |
|
AST classes, but also contains special <b>pattern nodes</b> |
|
(AnyNode, Repeat, OptionalNode, Backreference, NamedNode, Choice, |
|
...).<br> |
|
If you call<br> |
|
Match m = pattern<span style="color: #235100; font-weight: normal; |
|
font-style: normal; ">.</span><span style="color: #191970; |
|
font-weight: bold; ">Match</span><span style="color: #235100; |
|
font-weight: normal; font-style: normal; ">(</span>someNode<span |
|
style="color: rgb(35, 81, 0); font-weight: normal; font-style: |
|
normal;">);<br> |
|
</span>then m.Success will be true if someNode is a |
|
VariableDeclarationStatement that declares a single variable, which |
|
is initialized to a new object of the variable type.<br> |
|
Basically, Match performs a comparison of the pattern AST with |
|
someNode. If the pattern AST does not contain any pattern nodes, the |
|
match will be successful if the ASTs are syntactically identical |
|
(whitespace/comments are not compared).<br> |
|
AnyNode will match any non-null node, and optionally store the |
|
node it was matched against in a named <b>capture group</b>.<br> |
|
Backreference will match any node that is syntactically identical |
|
to the node that was previously stored in the named capture group.<br> |
|
Repeat can be used only in AstNodeCollections and will try to |
|
match its child pattern against any number of nodes - this is |
|
equivalent to * (Kleene star) in regular expressions.<br> |
|
OptionalNode will match null nodes, or will try to match its child |
|
pattern against the node. OptionalNode can also be used in |
|
AstNodeCollections, where it is equivalent to a Repeat with |
|
MinCount=0 and MaxCount=1.<br> |
|
<br> |
|
The resulting match object can also be used to retrieve the nodes |
|
stored in the capture groups:<br> |
|
<span style="color: #0000ff; font-weight: bold; ">if</span> <span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">(</span>m<span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">.</span>Success<span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">)</span> <span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">{</span><br> |
|
m<span style="color: #235100; font-weight: normal; font-style: |
|
normal; ">.</span>Get<span style="color: #235100; font-weight: |
|
normal; font-style: normal; "><</span>AstType<span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">>(</span><span |
|
style="color: #0000ff; ">"type"</span><span style="color: #235100; |
|
font-weight: normal; font-style: normal; ">).</span><span |
|
style="color: #191970; font-weight: bold; ">Single</span><span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">().</span><span |
|
style="color: #191970; font-weight: bold; ">ReplaceWith</span><span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">(</span><span |
|
style="color: #008b8b; font-weight: bold; ">new</span> <span |
|
style="color: #191970; font-weight: bold; ">SimpleType</span><span |
|
style="color: #235100; font-weight: normal; font-style: normal; ">(</span><span |
|
style="color: #0000ff; ">"var"</span><span style="color: #235100; |
|
font-weight: normal; font-style: normal; ">));</span><br> |
|
<span style="color: #235100; font-weight: normal; font-style: |
|
normal; ">}</span><br> |
|
<br> |
|
This feature was originally written for the decompiler in ILSpy, but |
|
it is also very useful for refactorings. You can also implement |
|
custom pattern nodes (derive from the Pattern base class) with |
|
custom match logic - for example if you want to check the semantics |
|
of a node.<br> |
|
</body></html> |