I have been working on this one for several hours now and need a little help. :) I need to parse 'robot instructions' and execute them. The format of my language is:

label  opcode  operand operand ... operand
where the label is optional. So far i have implemented all 'opcodes' except 'IF', and that is what is giving me trouble. But first, let me explain the code.

My idea is to parse each line and add a sub reference (plus the args to the sub via an array ref) to some global array. After the parsing has completed, i then run a loop over that array and call each element as a subroutine. The reason for using two passes is to be able to implement a 'GOTO' command. The 'robot command language' also branches when an 'IF' command is encountered.

Back to the problem. My grammar works except in this one example case:

IF int_or_var relop int_or_var label_name
when P::RD sees that the first 'int_or_var' is a 'var' and not an 'int', it mistakes 'IF' for a label. In other words, the first line below matches correctly to 'IF', but the second matches "incorrectly" to 'label':

IF 9 > 8 L1       # matches IF
IF rmove < 8 L1   # matches label
My question is, how do i specify my grammar to get the second line above to match to 'label' and not 'if'? Here is my code, it should run without any errors and it's display should be self-explanatory. Also, any suggestions or improvements are very welcome. Thanks in advance. :)
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 <DATA>; 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

jeffa

L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)

In reply to Help with tweaking Parse::RecDescent grammar by jeffa

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.