Please forgive me if this an FAQ. I am new to the world of RecDescent
and grammars in general. I'm assisting on a project for which the
original grammar was developed by someone else; making my own
additions, learning (sometimes) as I go. Not a pro, just dabbling.

I've tried to distill the grammar down for this post, but again, I
apologize if it is too long to digest. If you don't like it, you can
say, in our full grammar: ex R3 up.

I can't for the life of me figure out how to ensure that the tokens
are separated by whitespace, so that, eg 
   5 pu 2n mu 3 
would not be confused with
   5 pu 2nm 

I tried setting $Parse::RecDescent::skip = '[ \t]+' and every line was
bad. Is this separation something that needs to be dealt with in the
rules, and if so how?

TIA,
Scott Swanson

<code>
package SFNParse;

use Parse::RecDescent;

# Note: the grammar is stripped down, so a lot of these don't appear in it.
our %abbrevs = (
        # Hands (X-axis)
        'L'=>'left','R'=>'right','M'=>'middle', 
        # z-axis
        'n'=>'near','f'=>'far', 'a'=>'axial',
        # x-axis
        'o'=>'outer', 'i'=>'inner', 'm'=>'middle',
        # y-axis
        't'=>'top', 'c'=>'center','b'=>'bottom',        
        # Directions
        'dx'=>'distally','px'=>'proximally','lr'=>'from left to 
right','rl'=>'from right to left','nf'=>'near to far', 'fn'=>'far to near',
        'up'=>'upwards', 'dn'=>'downwards',
        'da'=>'down and away from you','ua'=>'up and away from you','dt'=>'down 
and towards you','ut'=>'up and towards you',
        'tw'=>'towards you','aw'=>'away from you','io'=>'from centre 
out','oi'=>'from outside to centre',
        'lor'=>'left over right', 'rol'=>'right over left', 
        # Twists
        '>'=>"a half turn away from you",'>>'=>"a full turn away from 
you",'<'=>"a half turn towards you",'<<'=>"a full turn towards you",
        # 'Descriptor' strings (added VS, changed text of CS, anticipating 
'mid')
        
'DS'=>'diagonal','SS'=>'straight','XS'=>'crossed','CS'=>'centre','TV'=>'transverse',
                'VS'=>'vertical','DM'=>'diamond',
        # Bodyparts (. means 'in the figure')
        '1'=>'thumb', '2'=>'forefinger', '3'=>'middle finger','4'=>'ring 
finger','5'=>'little finger',
        'P'=>'palm','H'=>'hand','W'=>'wrist','O'=>'mouth','.'=>' ','B'=>'back 
of hand',
                'T'=>'toe or etc', 'F'=>'fingers', 
        # Commands (added hu,hd)
        'pu'=>'pick up','gr'=>'grasp','hu'=>'hook up','hd'=>'hook down',
        'kl'=>'keep loose','ls'=>'let slip','ht'=>'hold 
tight','ex'=>'extend',','=>'then..',
        'na'=>'navaho','tr'=>'transfer','fl'=>'flip','<=>'=>'exchange',
        'mo'=>'over','mu'=>'under','mt'=>'through',
        'mb'=>'between',
        'rep'=>'repeat', 
'rot'=>'rotate','rel'=>'release','ret'=>'return','pnt'=>'point',
        );

my $grammar = q {
move: (rel_move | take ) stringdesc     {"$item[1] $item[2]";}
take: ("pu" | "gr" | "hu" | "hd") direction(?) {$SFNParse::abbrevs{$item[1]}." 
".$item[2][0];}
rel_move: ("mo" | "mu" | "mt") direction(?) {"move" . "$item[2][0] 
".$SFNParse::abbrevs{$item[1]};}
stringdesc: strings {$item[1];}
strings: string(s) {join(" / ", @{$item[1]});}
string:         ( mnoose | mstring )            
mnoose:  manipulator "N" height(?){"$item[3][0] $item[1]  noose";}
mstring: manipulator height(?) side(?) lat(?) descriptor(?){join(" ", 
@{$item[2]},@{$item[3]},@{$item[4]},$item[1],@{$item[5]}," string");}
side:   ("n" | "f" | "a") {$SFNParse::abbrevs{$item[1]};}
lat:    ("i" | "o" | "m") {$SFNParse::abbrevs{$item[1]};}
height: ("t" | "c" | "b") {$SFNParse::abbrevs{$item[1]};}
descriptor: ("DS" | "XS" | "CS" | "SS" | "TV" | "VS" | "DM") 
{$SFNParse::abbrevs{$item[1]};}
direction:("px" | "dx" | "lr" | "rl" | "nf" | "fn") 
{$SFNParse::abbrevs{$item[1]};}
manipulator: hand(?) bodypart(s) {"$item[1][0] ".join("/", @{$item[2]});}
hand: ("L" | "R" | "M") {$SFNParse::abbrevs{$item[1]};}
bodypart:("1" | "2" | "3" | "4" | "5" | "P" | "H") 
{$SFNParse::abbrevs{$item[1]};}
action: manipulator move(s) {$item[1] . " " . join (", ", @{$item[2]});}
fullmove:  action modifier(?) {$item[1].(($item[2][0]) ? " and ". $item[2][0] : 
"");}
modifier: ("ex" | "ret" | "si" | "kl" | ",")    {$SFNParse::abbrevs{$item[1]};}
validstep: code_ref | repeat | fullmove | voice
stepline: /\\\{?/ validstep /\\\}?/ comment(?)  {"$item[1] $item[2] $item[3] 
$item[4][0]";}
comment: "#" /.+/ {"($item[2])";}
code_ref: "[" /\w+/ "]" { "perform $item[2]";}
voice:  "v" /.+/ {'"'.$item[2].'"';}
repeat: "rep" stepnumber "-" stepnumber {"repeat steps $item[2] to $item[4] "}
stepnumber: /\d+/

};

my $parser = new Parse::RecDescent ($grammar) or die "Bad grammar!\n";

while (<DATA>) {
  my $text = $parser->stepline($_) || "Error: $_";
  print "$text\n";
}
__DATA__
1 pu 5f
1 pu 5tfo
1 mu 2n pu 5cni
1 pu 2n mu 5cni # this is wrong
1mu2npu5cni     # Yucch! But it parses....

</code>


Reply via email to