in reply to Re^2: Parsing syntax trees
in thread Parsing syntax trees
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
|
---|