shakespeare-parrot / src / parser / actions.pm

class shakespeare::Grammar::Actions;

method TOP($/) {
  my $past := PAST::Block.new();
  for $<chardef> {
    $past.push(mkcall('declare', mkstr($_<character>)));
  }
  for $<act> {
    $past.push($_.ast);
  }
  make $past;
}

sub mkstr($arg) {
  return PAST::Val.new(:value('' ~ $arg));
}
sub mkcall($name, $arg) {
  return PAST::Op.new($arg, :name($name), :pasttype('call'));
}
sub mkcall0($name) {
  return PAST::Op.new(:name($name), :pasttype('call'));
}

method assignment($/) {
  make mkcall('assign', $<value>.ast);
}

method events($/, $k) {
  make $/{$k}.ast;
}

method act($/, $k) {
    my $past := PAST::Stmts.new();
    if $k eq 'open' {
      #fugly
      our $?ACT := '' ~ $<roman>;
      $past.push(PAST::Op.new(:inline('act_' ~ $?ACT ~ ':')));
    }
    else {
      for $<scene> {
        $past.push($_.ast);
      }
    }
    make $past;
}
method scene($/) {
    our $?ACT;
    my $past := PAST::Stmts.new(:name($<roman>));
    $past.push(PAST::Op.new(:inline('scene_' ~ $?ACT ~ '_' ~ $<roman> ~ ':')));
    for $<events> {
      $past.push($_.ast);
    }
    make $past;
}

method branch($/) {
  our $?ACT;
  make PAST::Op.new(:inline('goto ' ~ 'scene_' ~ $?ACT ~ '_' ~ $<roman>));
}

method io($/,$k) {
  make mkcall0($k);
}


method line($/) {
    my $past := PAST::Stmts.new();
    $past.push(
      PAST::Op.new(
        PAST::Var.new(:name('the_speaker'), :scope('package')),
        mkstr($<character>),
        :pasttype('bind')
      )
    );
    for $<sentence> {
      $past.push($_.ast);
    }
    make $past;
}

method sentence($/, $key) {
  make $/{$key}.ast;
}


method value($/, $key) {
  make $/{$key}.ast;
}

method question($/) {
  my  $res := $<comparison>.ast;
  for $<value> {
    $res.push($_.ast);
  }
  make $res;
}

method comparison($/,$k) {
    make mkcall0($k);
}

method reference($/, $k) {
  if $k eq 'named_ref' {
    make mkcall('valueof', mkstr($<character>));
  }
  elsif $k eq 'you_ref' {
    make mkcall('valueof', mkcall0('find_other_name'));
  }
  else {
    make mkcall('valueof', mkcall0('get_speaker_name'));
  }
}

method move($/, $k) {
  my $past := PAST::Stmts.new();
  if $<character> {
    for $<character> {
      $past.push(mkcall($k, mkstr($_)));
    }
  }
  else {
    $past.push(mkcall0('exeunt_omnes'));
  }
  make $past;
}

method immediate($/) {
  my $value := 1;
  if $<noun><negative_noun> {
    $value := -1;
  }
  elsif $<noun><nothing> {
    $value := 0;
  }
  for $<adjective> {
    unless $_<first_person_possessive> || $_<second_person_possessive> || $_<third_person_possessive> {
      $value := $value * 2;
    }
  }
  make PAST::Val.new(:value($value));
}


method tap($/) {
  make mkcall('tap', $<value>.ast);
}

method memorize($/) {
  make mkcall('push', $<value>.ast);
}

method recall($/) {
  make mkcall0('pop');
}

method plan($/) {
  make mkcall('plan', $<value>.ast);
}

method test($/, $k) {
  my $test := PAST::Var.new(:name('the_condition'), :scope('package'));
  make PAST::Op.new( $test, $<sentence>.ast, :pasttype($k));
}

method computation($/, $key) {
  make $/{$key}.ast;
}

method unary($/, $k) {
  make mkcall($k, $<value>.ast);
}

method binary($/, $key) {
  my $res := PAST::Op.new(:pirop($key));
  for $<value> {
    $res.push($_.ast)
  }
  make $res;
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.