I want to learn how to create an abstract syntax tree for nested tuples using a Perl regexp with embedded code execution. I can easily program that using a Perl 6 grammar and I'm aware that using parsing modules would simplify the task in Perl 5, but I think for such simple tasks I should be able to do it without modules by learning how to mechanically translate from grammar definitions. I couldn't find a way to dereference $^R, so I try to undo the involuntary nesting at the end of the TUPLE rule definition, but the output is incorrect, e.g. some substrings appear twice.
use v5.10;
use Data::Dumper;
while (<DATA>) {
chomp;
/(?&TUPLE)(?{$a = $^R})
(?(DEFINE)
(?<TUPLE>
T \s (?&ELEM) \s (?&ELEM)
(?{ [$^R->[0][0],[$^R->[0][1],$^R[1]]] })
)
(?<ELEM>
(?: (a) (?{ [$^R,$^N] }) | \( (?&TUPLE) \) )
)
)/x;
say Dumper $a;
}
__DATA__
T a a
T (T a a) a
T a (T a a)
T (T a a) (T a a)
T (T (T a a) a) (T a (T a a))
Expected output data structure is a nested list:
['a','a'];
['a',['a','a']];
[['a','a'],'a'];
[['a','a'],['a','a']];
[[['a','a'],'a'],['a',['a','a']]]
For reference I'll also share my working Perl 6 code:
grammar Tuple {
token TOP { 'T ' <elem> ' ' <elem> }
token elem { 'a' | '(' <TOP> ')'}
}
class Actions {
method TOP($/) {make ($<elem>[0].made, $<elem>[1].made)}
method elem($/) {make $<TOP> ?? $<TOP>.made !! 'a'}
}