package SFNParse;

use Parse::RecDescent;

#$::RD_HINT = 1;
#$::RD_TRACE = 1;

our %abbrevs = (
	# Hands
	'L'=>'sinstra','R'=>'destra',	
	# Sides
	'n'=>'pui vicino','f'=>'pui lontano',		
	# Heights
	't'=>'pui alto', 'c'=>'centro','b'=>'pui basso',	
	# Directions
	'dx'=>'d\'alto a basso','px'=>'da basso ad alto','lr'=>'da sinstra a destra','rl'=>'da destra a sinstra','nf'=>'da pui vicino a pui lontano', 'fn'=>'da pui lontano a pui vicino',
	'up'=>'verso l\'alto', 'dn'=>'in giu',
	'da'=>'in giu e lontano','ua'=>'verso l\'alto e lontano','dt'=>'in giu e a te','ut'=>'verso l\'alto e a te',
	'tw'=>'a te','aw'=>'lontano',
	# Twists
	'>'=>"mezzo giro e lontano",'>>'=>"intero giro e lontano",'<'=>"mezzo giro a te",'<<'=>"intero giro a te",
	# 'Descriptor' strings
	'DS'=>'diagonale','SS'=>'stretto','XS'=>'incrociare','CS'=>'centro','TV'=>'transverse',
	# Bodyparts
	'1'=>'pollice', '2'=>'dito indice', '3'=>'dito di mezzo','4'=>'dito fede','5'=>'dito mignolo',
	'P'=>'palmo','H'=>'mano','W'=>'polso','O'=>'boca','F'=>'piede','B'=>'dorso mano',
	# Commands
	'pu'=>'far salire','gr'=>'presa',
	'kl'=>'lasciare sciolto','ls'=>'far scivolare','ht'=>'tenere fermo','ex'=>'estendersi',','=>'poi..',
	'na'=>'navaho','tr'=>'trasferire','fl'=>'far oscillare',
	'mo'=>'movesti su','mu'=>'movesti sotto','mt'=>'movesti attraverso',
	'rep'=>'riprodurre', 'rot'=>'far girare','rel'=>'rilasciare','ret'=>'ritornare',
	);

our $handed = "(i/e)";

sub new {
	my $grammar = q {

	code_ref:	"[" /\w+/ "]"								{"eseguire $item[2]";}
	comment:	"#" /.+/									{"($item[2])";}
	voice:		"v" /.+/									{'"'.$item[2].'"';}
	hand:		("L" | "R")									{$SFNParse::handed = "";$SFNParse::abbrevs{$item[1]};}
	side:		("n" | "f")									{$SFNParse::abbrevs{$item[1]};}
	height:		("t" | "c" | "b")							{$SFNParse::abbrevs{$item[1]};}
	descriptor: ("DS" | "XS" | "CS" | "SS" | "TV")			{$SFNParse::abbrevs{$item[1]};}
	direction:	("px" | "dx" | "lr" | "rl" | "nf" | "fn" | "up" | "dn" | "ua" | "da" | "ut" | "dt" | "tw" | "aw")	{$SFNParse::abbrevs{$item[1]};}
	bodypart:	("1" | "2" | "3" | "4" | "5" | "P" | "H" | "W" | "B" | "O" | "F")	{$SFNParse::abbrevs{$item[1]};}
	manipulator: hand(?) bodypart(s)						{"$item[1][0] ".join("/", @{$item[2]});}

	snoose:		"SN"										{"spago cappio"}
	mnoose:		manipulator "N" height(?)  					{"$item[3][0] $item[1] cappio" . $SFNParse::handed;}
	mstring:	manipulator height(?) side(?) descriptor(?)	{join(" ", @{$item[2]},@{$item[3]},$item[1],@{$item[4]},"spag".(($SFNParse::handed)?"ghi":"o"));}
	string:		(snoose | mnoose | mstring)		
	strings:	(string(s) | "AS")							{($item[1] eq 'AS') ? "tutti spagi" : join(" / ", @{$item[1]});}
	altstrings: "(" strings ")"								{"($item[2])";}
	stringdesc: strings altstrings(s?)						{$item[1] . " ".join(" ",@{$item[2]});}

	rel_move:	("mo" | "mu")								{$SFNParse::abbrevs{$item[1]};}
	movethrough:"mt" direction(?)							{"movesti $item[2][0] attraverso";}
	take:		("pu" | "gr")								{$SFNParse::abbrevs{$item[1]};}
	move:		(rel_move | take | movethrough) stringdesc	{"$item[1] $item[2]";}
	twist:		("<<" | ">>" | ">" | "<")					{"deformare " . $SFNParse::abbrevs{$item[1]};}
	rotate:		"rot" direction(?)							{"far girare $item[1]";}
	defaultmove: direction									{"movesti $item[1]";}

	action:		manipulator (move | twist | rotate | defaultmove)(s){$item[1] . $SFNParse::handed. " ".join (", ", @{$item[2]});}
	manouvre:	("rel" | "na") stringdesc					{$SFNParse::abbrevs{$item[1]}." ".$item[2];}
	extension:	"ex" manipulator(?) direction(?)			{"estendersi $item[2][0]". (($item[2][0] && $SFNParse::handed)?"s":""). " $item[3][0]";}
	tension:	manipulator(?) ("ls" | "ht") stringdesc		{(($item[1][0])?"$item[1][0] ":"").$SFNParse::abbrevs{$item[2]}." $item[3]";}
	flip:		"fl" stringdesc direction					{"far oscillare $item[2] da $item[3] a mano";}
	transfer:	"tr" mnoose manipulator direction(?)		{"trasferire $item[2] a $item[3] $item[4][0]";}
	modifier:	("ex" | "ret" | "si" | "kl" | ",")			{$SFNParse::abbrevs{$item[1]};}
	fullmove:	(manouvre | action | transfer | tension | extension | flip) modifier(?) {$item[1].(($item[2][0]) ? " e ". $item[2][0] : "");}

	swap:		"sw" hand hand								{"trasferire $item[2] and $item[3]";}
	stepnumber: /\d+/
	repeat:		"rep" stepnumber "-" stepnumber swap(?)		{"riprodurre passi $item[2] a $item[4] $item[5][0]"}
	validstep:	code_ref | repeat | fullmove | voice 
	stepline:	/\\\{?/ validstep /\\\}?/ comment(?)	{$SFNParse::handed = "(i/e)";"$item[1] $item[2] $item[3] $item[4][0]";}

	};

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

1;

