@@ -120,50 +120,61 @@ $Order = 2,
120
120
$Variable = @ {}
121
121
)
122
122
123
+ # First, let us expand our axiom
123
124
$currentState = " $Axiom "
125
+ # (at least, as long as we're supposed to)
124
126
if ($Order -ge 1 ) {
125
127
$combinedPattern = " (?>$ ( $Rule.Keys -join ' |' ) )"
126
128
foreach ($iteration in 1 .. $Order ) {
129
+ # To expand each iteration, we replace any matching characters
127
130
$currentState = $currentState -replace $combinedPattern , {
128
131
$match = $_
129
132
$matchingRule = $rule [" $match " ]
133
+ # a matching rule could be dynamically specified with a script block
130
134
if ($matchingRule -is [ScriptBlock ]) {
131
135
return " $ ( . $matchingRule $match ) "
132
136
} else {
137
+ # but is often statically expanded with a string.
133
138
return $matchingRule
134
139
}
135
140
}
136
141
}
137
142
}
138
143
139
- $localReplacement = [Ordered ]@ {}
140
- foreach ($key in $variable.Keys ) {
141
- $localReplacement [$key ] =
142
- if ($variable [$key ] -is [ScriptBlock ]) {
143
- [ScriptBlock ]::Create($variable [$key ])
144
- } else {
145
- $variable [$key ]
146
- }
147
- }
148
-
144
+ # Now we know our final state
149
145
$finalState = $currentState
150
146
147
+ # and can add the appropriate data attributes.
151
148
$this.PathAttribute = [Ordered ]@ {
152
149
" data-l-order" = $Order
153
150
" data-l-axiom" = $Axiom
154
151
" data-l-rules" = ConvertTo-Json $Rule
155
152
" data-l-expanded" = $finalState
156
153
}
157
154
155
+ # Next, prepare our replacements.
156
+ # The provided script block will almost always be scoped differently
157
+ # so we need to recreate it.
158
+ $localReplacement = [Ordered ]@ {}
159
+ foreach ($key in $variable.Keys ) {
160
+ $localReplacement [$key ] =
161
+ if ($variable [$key ] -is [ScriptBlock ]) {
162
+ [ScriptBlock ]::Create($variable [$key ])
163
+ } else {
164
+ $variable [$key ]
165
+ }
166
+ }
167
+
168
+ # Now we need to find all potential matches
158
169
$MatchesAny = " (?>$ ( $variable.Keys -join ' |' ) )"
159
170
$allMatches = @ ([Regex ]::Matches($finalState , $MatchesAny , ' IgnoreCase,IgnorePatternWhitespace' ))
171
+ # we want to minimize rematching, so create a temporary cache.
160
172
$matchCache = @ {}
161
173
:nextMatch foreach ($match in $allMatches ) {
162
174
$m = " $match "
163
175
if (-not $matchCache [$m ]) {
164
176
foreach ($key in $Variable.Keys ) {
165
- if (-not ($match -match $key )) { continue }
166
- # if ($variable[$key] -isnot [ScriptBlock]) { continue }
177
+ if (-not ($match -match $key )) { continue }
167
178
$matchCache [$m ] = $localReplacement [$key ]
168
179
break
169
180
}
0 commit comments