Reinventing the wheel as a learning exercise is a fine thing. Reinventing a major wheel as part of getting some other primary task done is generally unproductive and a "bad thing"™. In this case I think "learning exercise" applies so go for it.
Providing a succinct version of the back story always helps guide any coding decisions that need to be made. Trying to "keep the question short" almost always ends up with a series of questions to elicit the "unimportant details" that were left out meaning much more work for everyone and a lot longer until you get the help you were looking for.
You could almost as easily use Tree::Simple instead to get an n-ary tree. So, taking something like your example and using Tree::Simple:
#!/usr/bin/perl
use warnings;
use strict;
use Marpa::R2;
use Tree::Simple;
package Construct;
sub doMap {
my @params = @_;
my $child = 'ARRAY' eq ref $params[3] ? $params[3][1] : $params[3]
+;
return $params[1]->addChild($child) if $child->getNodeValue() ne '
+root';
my @children = $child->getAllChildren();
return $params[1]->addChildren(@children);
}
sub doMapSib {
my @params = @_;
my ($lhs, $rhs) = map {'ARRAY' eq ref $_ ? $_->[1] : $_} @params[1
+, 3];
my $root;
if ($lhs->getNodeValue() eq 'root') {
$root = $lhs;
$lhs = undef;
} elsif ($rhs->getNodeValue() eq 'root') {
$root = $rhs;
$rhs = undef;
} else {
$root = Tree::Simple->new('root');
}
$root->addChild($lhs) if $lhs;
$root->addChild($rhs) if $rhs;
return $root;
}
my $tail = '';
sub doTail {
my @params = @_;
$tail = $params[1];
return;
}
sub doCode {
my @params = @_;
my $node = Tree::Simple->new("$params[1]$tail");
$tail = '';
return $node;
}
package main;
my $syntax = <<'SYNTAX';
lexeme default = latm => 1
network ::= ident ';' subnet action => doMap
| subnet action => ::first
subnet ::= sibling ',' subnet action => doMapSib
| sibling action => ::first
sibling ::= '(' network ')' action => [values]
| ident action => ::first
ident ::= letter tail action => doCode
| letter action => doCode
tail ::= digits action => doTail
letter ~ [A-Z]+
digits ~ [\d]+
:discard ~ spaces
spaces ~ [\s]+
SYNTAX
my $grammar = Marpa::R2::Scanless::G->new({source => \$syntax});
my $input = 'R;(S1;(H1,H2,H4,H5)),(S2;H3)';
my $tree = ${$grammar->parse(\$input, 'Construct')};
my $root = Tree::Simple->new('root')->addChild($tree);
my $depth = $root->getHeight();
($root)->traverse(
sub {
print " " x ($depth - $_[0]->getHeight()), $_[0]->getNodeValu
+e(), "\n";
}
);
Prints:
R
S1
H4
H5
H2
H1
S2
H3
Premature optimization is the root of all job security
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.