Subject:
space-separated tokens (FAQ?)
From:
Scott <[EMAIL PROTECTED]>
Date:
Sun, 26 Jun 2005 12:28:05 -0600
To:
recdescent@perl.org
To:
recdescent@perl.org
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....