use strict; use warnings; use Data::Dumper; use Parse::RecDescent; $RD_HINT = 1; use vars qw( %item @item $return %symbol %axis @code $curr %label ); @axis{'X','Y','Z'} = (0,0,1); @code = (); my $parser = Parse::RecDescent->new(q( startrule : opcode | label opcode label: /[a-z]\w*/i { print "got label: $item[1]\n"; $main::label{$item[1]} = $#main::code; } opcode: IF | YMOVE | XMOVE | DOWN | UP | PRINTLOC | GOTO | SET | ADD | SUB | HALT YMOVE: /YMOVE/i int_or_var { push @main::code, [ sub { $main::axis{Y} += $_[0] }, [$item{int_or_var}], ]; } XMOVE: /XMOVE/i int_or_var { push @main::code, [ sub { $main::axis{X} += $_[0] }, [$item{int_or_var}], ]; } DOWN: /DOWN/i { push @main::code, [ sub { $main::axis{Z}-- },[]]; } UP: /UP/i { push @main::code, [ sub { $main::axis{Z}++ },[]]; } PRINTLOC: /PRINTLOC/i { push @main::code, [ sub { print "@{[map $main::axis{$_},sort keys %main::axis]}\n" }, [], ]; } IF: /IF/i int_or_var relop int_or_var label_name { print "got if: @item\n"; } GOTO: /GOTO/i label_name { push @main::code, [ sub { $main::curr = $main::label{$item{label_name}} },[] ]; } SET: /SET/i var_name int_or_var { $main::symbol{$item{var_name}} = $item{int_or_var}; push @main::code, [ sub { $main::symbol{$_[0]} = $_[1] }, [$item{var_name}, $item{int_or_var}], ]; } ADD: /ADD/i var_name int_or_var { $main::symbol{$item{var_name}} += $item{int_or_var}; push @main::code, [ sub { $main::symbol{$_[0]} += $_[1] }, [$item{var_name}, $item{int_or_var}], ]; } SUB: /SUB/i var_name int_or_var { $main::symbol{$item{var_name}} -= $item{int_or_var}; push @main::code, [ sub { $main::symbol{$_[0]} -= $_[1] }, [$item{var_name}, $item{int_or_var}], ]; } HALT: /HALT/i { push @main::code, [ sub { exit(0); },[]]; } label_name: /[a-z]\w*/i int_or_var: var_value | int var_name: /[a-z]\w*/i var_value: /[a-z]\w*/i { $return = $main::symbol{$item[1]}; } int: /-*\d+/ relop: '<' | '>' | '==' | '!=' | '>=' | '<=' )); $parser->startrule($_) while ; for ($curr = 0; $curr < @code; $curr++) { my ($sub,$args) = @{$code[$curr]}; $sub->(@$args); } __DATA__ YMOVE 10 # along y-axis SET RMOVE 0 # sets RMOVE to 0 L1 ADD RMOVE 1 # adds 1 to RMOVE xmove 1 # along x-axis IF rmove < 8 L1 IF 9 < 8 L1 YMOVE -3 down # along z-axis (lower gripper) PRINTLOC HALT