forked from icsharpcode/ILSpy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Pattern Matching.html
115 lines (115 loc) · 7.89 KB
/
Pattern Matching.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<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>