use Test;
class port {
has $.dir;
has $.name;
has $.type;
method toStruct {
return { :dir(self.dir), :name(self.name), :type(self.type) };
}
};
class ports {
has @.ports ;
method toStruct { @.ports».toStruct }
};
grammar l8 {
rule ports { '[' ~ ']' <ports_> }
rule ports_ { <port> * %% \; }
rule port { <pnamelist> <portdir> ':' <porttype> }
proto token portdir {*};
token portdir:sym<»|> { <sym> }
token portdir:sym<«|> { <sym> }
token portdir:sym<«»|> { <sym> }
proto token pnamelist {*};
token pnamelist:sym<ident> { <pnamelist_ident> }
token pnamelist:sym<identlist> { <pnamelist_identlist> }
rule pnamelist_ident { <ident> }
rule pnamelist_identlist { '(' ~ ')' <pnamelist_identlist_> }
rule pnamelist_identlist_ { <ident> * % \, }
token ident { \w+ }
token porttype { \w+ }
token num { \d+ }
}
class l8Actions {
method ports ($/) { make $<ports_>.made }
method ports_ ($/) { my @a =();
for $<port> -> $e {
@a.push( $e.made[0] );
$e.map( -> $f {
#say $f;
@a.push($f)
})
};
make ports.new(:ports(@a)); }
method port ($/) { make $<pnamelist>.made.map( -> $e { port.new( :name($e), :dir($<portdir>.Str) :type($<porttype>.made) ) }) };
method pnamelist:sym<ident> ($/) { make [ $<pnamelist_ident>.made ] }
method pnamelist:sym<identlist> ($/) { make $<pnamelist_identlist>.made }
method pnamelist_ident ($/) { make $<ident>.made }
method pnamelist_identlist ($/) { make $<pnamelist_identlist_>.made }
method pnamelist_identlist_ ($/) { make $<ident>.map( -> $e { $e.made }) }
method ident ($/) { make $/.Str }
method porttype ($/) { make $/.Str }
}
sub l8parse_ports(Str $m) { my $n = l8.parse($m, :rule('ports'), :actions(l8Actions) ).made;
say $n;
my @r = $n.toStruct;
return @r; }
#say $p.toStruct;
#say (l8parse_ports('[ a»|:b;]'));
is-deeply( l8parse_ports('[ a»|:b;]'), [ { :dir<»|>, :name<a>, :type<b> }, ], "test: a»|:b" );