@@ -312,6 +312,53 @@ provided by parse methods:
312
312
# OUTPUT: «12»
313
313
= end code
314
314
315
+ = head2 Dynamic Variables in Grammars
316
+
317
+ Variables can be defined in tokens by prefixing the lines of code defining them
318
+ with C < : > . Arbitrary code can be embedded anywhere in a token by surrounding it
319
+ with curly braces. This is useful for keeping state between tokens, which can be
320
+ used to alter how the grammar will parse text. Using dynamic variables
321
+ (variables with C < $* > , C < @* > , C < &* > , C < %* > twigils) in tokens cascades down
322
+ through I < all > tokens defined thereafter within the one where it's defined,
323
+ avoiding having to pass them from token to token as arguments.
324
+
325
+ One use for dynamic variables is guards for matches. This example uses guards to
326
+ explain which regex classes parse whitespace literally:
327
+
328
+ grammar GrammarAdvice {
329
+ rule TOP {
330
+ :my Int $*USE-WS;
331
+ "use" <type> "for" <significance> "whitespace by default"
332
+ }
333
+ token type {
334
+ | "rules" { $*USE-WS = 1 }
335
+ | "tokens" { $*USE-WS = 0 }
336
+ | "regexes" { $*USE-WS = 0 }
337
+ }
338
+ token significance {
339
+ | <?{ $*USE-WS == 1 }> "significant"
340
+ | <?{ $*USE-WS == 0 }> "insignificant"
341
+ }
342
+ }
343
+
344
+ Here, text such as "use rules for significant whitespace by default" will only
345
+ match if the state assigned by whether rules, tokens, or regexes are mentioned
346
+ matches with the correct guard:
347
+
348
+ = begin code :preamble<grammar GrammarAdvice{};>
349
+ say GrammarAdvice.subparse("use rules for significant whitespace by default");
350
+ # OUTPUT: «use rules for significant whitespace by default»
351
+
352
+ say GrammarAdvice.subparse("use tokens for insignificant whitespace by default");
353
+ # OUTPUT: «use tokens for insignificant whitespace by default»
354
+
355
+ say GrammarAdvice.subparse("use regexes for insignificant whitespace by default");
356
+ # OUTPUT: «use regexes for insignificant whitespace by default»
357
+
358
+ say GrammarAdvice.subparse("use regexes for significant whitespace by default")
359
+ # OUTPUT: #<failed match>
360
+ = end code
361
+
315
362
= head1 X < Action Objects|Actions >
316
363
317
364
A successful grammar match gives you a parse tree of L < Match|/type/Match >
0 commit comments