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

In reply to Re^3: Parsing syntax trees by GrandFather
in thread Parsing syntax trees by betacentauri

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.