New paste Repaste Download
# use Grammar::Tracer;
grammar Vixen {
    token id       { <[A..Za..z*]>+ <![:]> }
    token selector { <[A..Za..z*]>+ \: }
    token string   { \" <[A..Za..z*]>* \" }
    token param    { \: <id> }
    token ass      { \:\= }
    proto rule obj             {*}
          rule obj:sym<block>  { <block> }
          rule obj:sym<paren>  { '(' <call> ')' }
          rule obj:sym<string> { <string> }
          rule obj:sym<name>   { <id> }
    proto rule unary {*}
          rule unary:sym<chain> { <obj> (<id>* % <ws>) }
    proto rule message {*}
          rule message:sym<key>  { (<selector> <unary>)+ }
    proto rule call {*}
          rule call:sym<cascade> { <unary> (<message>* % ';') }
    proto rule assign {*}
          rule assign:sym<assign> { <id> <ass> <call> }
          rule assign:sym<call>   { <call> }
    proto rule exprs {*}
          rule exprs:sym<rv>  { (<assign> '.')* '^' <call> }
          rule exprs:sym<nil> { (<assign> '.')* <call> }
    rule block { '[' <param>* '|' <exprs> ']' }
    rule TOP { <block> }
}
class MakeBlocks {
    has Int $!syms;
    method gensym { $!syms += 1; "gs" ~ $!syms; }
    method callTo($name, @row) {
        say "callTo $name ", @row;
        my $args = @row.join;
        say "backtick -E $name \{ \$\{V\}/call: $args \}";
        $name;
    }
    method callAnon(@row) { self.callTo: self.gensym, @row; }
    method obj:sym<block>($/)  { make $<block>.Str; }
    method obj:sym<paren>($/)  { make $<call>.made; }
    method obj:sym<string>($/) { make $<string>.Str; }
    method obj:sym<name>($/)   { make $<id>.Str; }
    method unary:sym<chain>($/) {
        my Str $rv = $<obj>.made;
        for $<id> {
            my @row = @_.map: *.made;
            @row.prepend: $rv;
            say "my unary row: ", @row;
            my ($name, $line) = self.callAnon(@row);
            $rv = $name;
            say $line;
        }
        make $rv;
    }
    method message:sym<key>($/) {
        my $verb = $/[0, 2 ... *].join;
        say "my verb: $verb";
        make $[1, 3 ... *].map(*.made).prepend: $verb;
    }
    method call:sym<cascade>($/) {
        my Str $target = $<unary>.made;
        my Str $rv = $target;
        for $<message> {
            my @row = @_.map: *.target;
            @row.prepend: $target;
            say "my cascade row: ", @row;
            my ($name, $line) = self.callAnon(@row);
            $rv = $name;
            say $line;
        }
        make $rv;
    }
    method assign:sym<assign>($/) { make self.callTo($<id>.made, $<call>.made); }
    method assign:sym<call>($/) { make self.callAnon($<call>.made); }
    method exprs:sym<rv>($/) { make $<call>.made; }
    method exprs:sym<nil>($/) {
        say "importas -iS Nil \$Nil";
        make $<call>.made;
    }
    method block($/) {
        say "#!/usr/bin/env -S execlineb -s", $<param>.elems + 1;
        say "importas -iS V";
        say "export self \$1";
        for $<param>.kv -> $i, $n {
            say "export ", substr($n, 1), " \$", $i + 2;
        }
        make $<exprs>.made;
    }
    method TOP($/) { say "top"; make $<block>.made; }
}
my $actions = MakeBlocks.new();
my $parsed = Vixen.parse: slurp $*IN, :$actions;
say "Parse tree: ", $parsed;
say "Made: ", $parsed.made;
Filename: vixen.raku. Size: 3kb. View raw, , hex, or download this file.

This paste expires on 2025-12-30 19:09:56.232608+00:00. Pasted through web.