use v6-alpha;

grammar rpn_data {
   rule key       { <?ident> }
   rule value     { \N* };
   rule statement { <key>\h*=\h*<value>\n* }
   rule config    { [\n*<statement>]* }
}

my $data = "
test1 = 1 2 + 
test2 = 1 2 3 + - 
";

say "Match 1:";
my $config = $data ~~ /<config>/;
say match_describe( $config,0);

for $config<config><statement> -> $o  {
    say "$o<key> == $o<value> == {evaluate("$o<value>")}";
}


sub match_describe (Match $o, Num $indent) {
   my $desc;
   if @$o.elems {
     $desc ~= "[\n" ~ join("" , map { match_describe($_, $indent + 1) }, @$o ) ~ "{"\t" x $indent}],";
   }
   elsif %$o.keys.elems {
      $desc ~= "{"\t" x $indent}\{\n";
      
      for keys %$o {
        $desc ~= "{"\t" x ($indent+1)}'$_' := { match_describe($o.{$_},$indent + 1)}\n";
      }  
      $desc ~= "{"\t" x $indent}\},\n";
   }
   else {
      $desc ~= "'$o'";
   }
   return "$desc";
}

# RPN calc stolen from examples/rpn/p6/RPN.pm

sub evaluate (Str $expr) returns Int {
    my @stack;
    for $expr.split() -> $tok {
        if $tok ~~ /-? \d+/ {
            @stack.push($tok);
            next;
        }
        my $x = @stack.pop() orelse die "Stack underflow\n";
        my $y = @stack.pop() orelse die "Stack underflow\n";

        # given/when is a sexy new P6 construct that can avoid
        # long if/elsif/else chains
        given $tok {
            when '+' { @stack.push($y + $x) }
            when '-' { @stack.push($y - $x) }
            when '*' { @stack.push($y * $x) }
            when '/' { @stack.push(int($y / $x)) }
            default  { die "Invalid token:\"$tok\"\n" }
        }
    }

    @stack.elems == 1 or die "Invalid stack:[@stack[]]\n";
    return @stack[0];
}
