Skip to content

Commit fac770f

Browse files
committed
grammars: document action methods
1 parent b412b25 commit fac770f

File tree

2 files changed

+111
-3
lines changed

2 files changed

+111
-3
lines changed

lib/Language/grammars.pod

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,112 @@ the supplied string.
171171
Parses the contents of the file C<$filename> with the L<parse> method,
172172
passing any named options in C<%opts>.
173173
174-
=head1 Action Classes
174+
=head1 Action Objects
175175
176-
TODO
176+
A successful grammar match gives you a parse tree of L<Match|/type/Match>
177+
objects, and the deeper that match tree gets, and the more branches in the
178+
grammar are, the harder it becomes to navigate the match tree to get the
179+
information you are actually interested in.
180+
181+
To avoid the need for diving deep into a match tree, you can supply an
182+
I<actions> object. After each successful parse of a named rule in your
183+
grammar, it tries to call a method of the same name as the grammar rule,
184+
giving it the newly create L<Match|/type/Match> object as a positional
185+
argument. If no such method exists, it is skipped.
186+
187+
Here is a contrieved example of a grammar and actions in action:
188+
189+
=begin code
190+
use v6;
191+
192+
grammar TestGrammar {
193+
token TOP { ^ \d+ $ }
194+
}
195+
196+
class TestActions {
197+
method TOP($/) {
198+
$/.make(2 + ~$/);
199+
}
200+
}
201+
202+
my $actions = TestActions.new;
203+
my $match = TestGrammar.parse('40', :$actions);
204+
say $match; # 「40」
205+
say $match.made; # 42
206+
=end code
207+
208+
An instance of C<TestActions> is passed as named argument C<actions> to the
209+
L<parse|/type/Grammar|method parse> call, and when token C<TOP> has matched
210+
successfully, it automatically calls method C<TOP>, passing the match object
211+
as an argument.
212+
213+
To make it clear that the argument is a match object, the example uses C<$/>
214+
as a parameter name to the action method, though that's just a handy
215+
convention, notthing intrinsic. C<$match> would have worked too. (Though using
216+
C<$/> does give the advantage of providing C<< $<capture> >>> as a shortcut
217+
for C<< $/<capture> >>).
218+
219+
A slightly more involved example follows:
220+
221+
=begin code
222+
use v6;
223+
224+
grammar KeyValuePairs {
225+
token TOP {
226+
[<pair> \n+]*
227+
}
228+
token ws { \h* }
229+
230+
rule pair {
231+
<key=.identifier> '=' <value=.identifier>
232+
}
233+
token identifier {
234+
\w+
235+
}
236+
}
237+
238+
class KeyValuePairsActions {
239+
method identifier($/) { $/.make: ~$/ }
240+
method pair ($/) { $/.make: $<key>.made => $<value>.made }
241+
method TOP ($/) { $/.make: $<pair>».made }
242+
}
243+
244+
my $res = KeyValuePairs.parse(q:to/EOI/, :actions(KeyValuePairsActions)).made;
245+
second=b
246+
hits=42
247+
perl=6
248+
EOI
249+
250+
for @$res -> $p {
251+
say "Key: $p.key()\tValue: $p.value()";
252+
}
253+
=end code
254+
255+
This produces the following ouput:
256+
257+
=begin code
258+
Key: second Value: b
259+
Key: hits Value: 42
260+
Key: perl Value: 6
261+
=end code
262+
263+
Rule C<pair>, which parsed a pair separated by an equals sign, aliases the two
264+
calls to token C<identifier> to separate capture names to make them available
265+
more easily and intuitively. The corresponding action method constructs a
266+
L<Pair|/type/Pair> object, and uses the C<.made> property of the sub match
267+
objects. So it (like the action method C<TOP> too) exploits the fact that
268+
action methods for submatches are called before those of the calling/outer
269+
regex. So action methods are called in
270+
L<post-order|https://en.wikipedia.org/wiki/Tree_traversal#Post-order>.
271+
272+
The action method C<TOP> simply collects all the objects that were C<.made> by
273+
the multiple matches of the C<pair> rule, and returns them in a list.
274+
275+
Also note that C<KeyValuePairsActions> was passed as a type object to method
276+
C<parse>, which was possible because none of the action methods use attributes
277+
(which would only be available in an instance).
278+
279+
In other cases, action methods might want to keep state in attributes. Then of
280+
course you must pass an instance to method parse.
177281
178282
=end pod

lib/Type/Match.pod

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,13 @@ Returns the index of the starting position of the match.
3131
3232
Returns the index of the end position of the match.
3333
34+
=head2 method made
35+
36+
Returns the payload that was set with L<#method make>.
37+
3438
=head2 method ast
3539
36-
Returns the AST (i.e. payload).
40+
Alias for L<#method made>.
3741
3842
=head2 method Str
3943

0 commit comments

Comments
 (0)