#!/usr/bin/perl

use strict;

# estrae dai file parsati le relazioni di dipendenza per ogni verbo, nome e aggettivo
# input: file parsato a dipendenze da DeSR parser - tagset TANL:
# (http://medialab.di.unipi.it/wiki/Tanl_Dependency_Tagset)

#usage estraiDep.desr.pl < input_file > output_file

my %sentence;   # hash di una frase
my @nouns;	# array dei nomi di ogni frase
my @verbs;      # array dei verbi di ogni frase
my @adjectives; # array degli aggettivi di ogni frase



# leggo il file di input parsato riga per riga.
# carico ogni frase in un hash di array. Ogni token e' un array e la sua key e' il token id



while (<STDIN>) {

	chomp;
		
	ANALYZE: {
		
# i tag di apertura e chiusura dei documenti (<text>) sono saltati
			
		if (/<text\s/ || /<\/text>/ ) {last ANALYZE}
		
# all'inizio di una frase, si inizializzano il suo hash e gli array che contengono i suoi verbi, nomi e aggettivi
			
		if (/^<s/) { %sentence = (); @verbs = (); @nouns = (); @adjectives = (); last ANALYZE}
			
			
# Alla fine di ogni frase

		if (/<\/s>/) {
			
		# preprocessing della frase
		
			%sentence = preprocessing (\%sentence);

		# estraggo i frames di ogni verbo della frase

			#extractVframes(\%sentence);
		
		# estraggo i frames di ogni nome della frase

			#extractNframes(\%sentence);
		
		# estraggo i frames di ogni aggettivo della frase

			extractAframes(\%sentence);
						
			last ANALYZE

		} 

# ogni riga e' divisa è trasformata in un array

		my @line = split;

# postag e dipendenze sono trasformate in minuscole

		$line[3] =~ tr/A-Z/a-z/;
		
		$line[4] =~ tr/A-Z/a-z/;
		
		$line[7] =~ tr/A-Z/a-z/;

# ogni array di riga e' assegnato all'hash della frase. Lo hash key e' il token id
		
		$sentence{$line[0]} = [@line];
		
# l'id di ogni V, N o A in una frase e' estratto e aggiunto all'array corrispondente

		if ($line[4] =~ /^v$/ && $line[2] =~ /^[a-zA-Z]/) {

			push(@verbs, "$line[0]")
			
		} elsif ($line[4] =~ /^s$/ && $line[2] =~ /^[a-zA-Z]/) {
			
			push(@nouns, "$line[0]")
			
		} elsif ($line[4] =~ /^a$/ && $line[2] =~ /^[a-zA-Z]/) {
			
			push(@adjectives, "$line[0]")
			
		}
	}
}



###############################################################
# preprocessing sub
# input: sentence hash
# ouput: sentence hash
# la sub aggiunge a ogni verbo informazione sulla presenza di ausiliari, e clitici
# i pronomi relativi sono sostituiti con il loro antecedente (testa)
# i nomi congiunti (es. cane e gatto) vengono identificati e il secondo congiunto
# viene aggiunto al lemma del primo (es. cane gatto)
################################################################



sub preprocessing {
		
	my ($ref) = @_;

#parameter hash is dereferenced
	
	my %sentence = %$ref;
	my @ids = sort{$a <=> $b}(keys %sentence);

	my $verbHead;  #variabile dove viene salvata l'id della testa verbale
	my $relHead;   #variabile dove viene salvato il lemma della testa della frase relativa
	my $relHeadId; #variabile dove viene salvata l'id della testa della frase relativa
	my $headID;    #variabile che contiene la id della testa di una dipendenza	

#aggiungo a ogni lemma (tranne le preposizioni e le congiunzioni) la sua PoS

	foreach my $id (@ids) {

		unless($sentence{$id}[3]=~/^(e|c)$/){$sentence{$id}[2]= $sentence{$id}[2]."-".$sentence{$id}[3]}

	}

	
#aggiungo una dimensione al vettore per l'ausiliare (posizione 10) e per la presenza di un clitico (si) (posizione 11)

	foreach my $verbId (@verbs) {
		push @{ $sentence{$verbId} }, "0"; 
		push @{ $sentence{$verbId} }, "0";
	}

#se il verbo ha un clitico si, questo viene aggiunto al suo array (posizione 11)

	foreach my $id (@ids) {
		if ($sentence{$id}[7] =~ /^clit$/ && $sentence{$id}[2] =~ /^(si|se|ci|ce)-/) { 
				
			#se il si dipende da un verbo modale, il "si" viene aggiunto alla testa verable e non al modale
				
			if ($sentence{$sentence{$id}[6]}[7] =~ /^modal$/) {
				$verbHead = $sentence{$sentence{$id}[6]}[6];
				$sentence{$verbHead}[11] = "si";
			} else {
				$verbHead = $sentence{$id}[6];
				$sentence{$verbHead}[11] = "si";
			}
		}
	}


#il pronome relativo viene sostituito dalla sua testa nominale

	foreach my $verbId (@verbs) {
				
		if ($sentence{$verbId}[7] =~ /^mod_rel$/) {
			
			#l'id e il lemma della testa della frase relativa sono solvati in due variabili
			
			$relHead = $sentence{$sentence{$verbId}[6]}[2];
			$relHeadId = $sentence{$sentence{$verbId}[6]}[0];

			for(my $i = $relHeadId+1; $i <= $relHeadId+4; $i++) {
				if ($sentence{$i}[2] =~ /^(che|quale|cui)-/ && $sentence{$i}[4] =~ /^pr$/) {
					$sentence{$i}[2] = $relHead;
					last;
				} else {
					next
				}
			}	
		}
	}


#a ogni nome viene attaccato l'aggettivo che lo modifica (se ce n'e' uno)

	foreach my $id (@adjectives) {
					
		#seleziono la testa del dipendente

			$headID = $sentence{$id}[6];
			
			if ($sentence{$id}[7] =~ /^mod$/) {
				
				$sentence{$headID}[2] =~ s/^(.+)$/\1::$sentence{$id}[2]/;

			}
			
	}


#i nomi congiunti (es. cane e gatto) vengono identificati e il secondo congiunto
# viene aggiunto al lemma del primo (es. cane;gatto)

	foreach my $id (@ids) {

		if 
			($sentence{$id}[7] =~ /^conj$/ && $sentence{$id}[4] =~ /^s$/) {
			
			$headID = $sentence{$id}[6];
			
			if ($sentence{$headID}[4] =~ /^s$/) {
			
				$sentence{$headID}[2] =~ s/^(.+)$/\1;$sentence{$id}[2]/;
			}
		}

#gestisce i congiunti all'interno di complementi preposizionali

		elsif ($sentence{$id}[7] =~ /^conj$/ && $sentence{$id}[3] =~ /^e$/) {

				my $n = $id+1;
				
				while ($n < $id+5) {
		
					if ($sentence{$n}[7] =~ /^prep$/) {

						last
					}

					$n++;
				}

				my $headPrep = $sentence{$id}[6];

				my $m = $headPrep+1;

				while ($m < $headPrep+5) {

					if ($sentence{$m}[7] =~ /^prep$/) {

						$sentence{$m}[2] =~ s/^(.+)$/\1;$sentence{$n}[2]/;

						last
					}

					$m++;
				}
		}

	}




# a ogni verbo viene aggiunta informazione sulla presenza di ausiliari (posizione 10). I nomi propri sono sostituiti
# con l'etichetta generica "sp"
	
	foreach my $id (@ids) {

		if ($sentence{$id}[7] =~ /^aux$/) {
			
			#se c'e' un doppio ausiliare (es. essere stato) viene aggiunto alla testa verbale "2_essere"
			
			if ($sentence{$sentence{$id}[6]}[7] =~ /^aux$/) {
				$verbHead = $sentence{$sentence{$id}[6]}[6];
				$sentence{$verbHead}[10] = "2_essere";
				$sentence{$sentence{$id}[6]}[7] =~ s/^aux$//;
			} else {
				$sentence{$id}[2]=~s/-v$//;
				$verbHead = $sentence{$id}[6];
				$sentence{$verbHead}[10] = $sentence{$id}[2];
			}
		
		#caso di venire come ausiliario
			
		} elsif ($sentence{$id}[7] =~ /^modal$/ && $sentence{$id}[2] =~ /^venire-v$/){ 
			$verbHead = $sentence{$id}[6];
			$sentence{$verbHead}[10] = "venire";
		
		
		# i nomi propri sono sostituiti dall'etichetta generica "sp"
		
		} elsif ($sentence{$id}[4]=~/^sp$/) {
			
			$sentence{$id}[2] = "sp"
		}
	}			

	return %sentence
	
}



###############################################################
# extractVframes sub
# input: sentence hash
# ouput: sentence hash
# la sub estrae per ogni verbo tutte le sue dipendenze sintattiche nella frase
################################################################



sub extractVframes {
	
	my ($hashRef) = @_;
	
	my %sentence = %$hashRef;
	
	my @ids = sort{$a <=> $b}(keys %sentence);
	
	my %lemmaInfo; #hash di array: per ogni verbo contiene un array con le informazioni relative al lemma: presenza di aux, clitico, ecc.
	my %subj;	   #hash in cui vieme messo il soggetto del verbo
	my %obj;	   #hash in cui vieme messo l'oggetto diretto del verbo
	my %compFrame; #hash di array: per ogni verbo contiene un array con i suoi comp preposizionali
	my %clauFrame; #hash di array: per ogni verbo contiene un array con i suoi comp frasali e predicativi
	my %modFrame;  #hash di array: per ogni verbo contiene un array con i suoi mod verbali e avverbiali
	my $headID;    #variabile che contiene la id della testa di una dipendenza	
	my $depLeng;   #distanza in token tra testa e dipendente
	
	foreach my $verbId (@verbs) {
		
# si seleziona il modo del verbo
		
		$sentence{$verbId}[5] =~ s/^.*?mod=(\w).*$/\1/;
	
# per ogni verbo attivo degli array che rappresentano le parti del suo frame
		
		if ($sentence{$verbId}[0] != 0) {
			
			#aggiungo informazione sulla presenza di ausiliari, clitico si e il modo del verbo
			
			if ($sentence{$verbId}[11] =~ /si/) {
			
				$lemmaInfo{$verbId} = [("lemma=\"$sentence{$verbId}[2]\"","aux=\"$sentence{$verbId}[10]\"",
									"si=\"1\"","mood=\"$sentence{$verbId}[5]\"")];
			
			} else {
				
				$lemmaInfo{$verbId} = [("lemma=\"$sentence{$verbId}[2]\"","aux=\"$sentence{$verbId}[10]\"",
									"si=\"0\"","mood=\"$sentence{$verbId}[5]\"")];
				
			}
				
		}
		
	}
	
	
# percorro l'intero hash della frase ed estraggo le relazioni di dipendenza dei verbi

		
	foreach my $id (@ids) {
			
		VERBDEP: {	

#seleziono la testa del dipendente

			$headID = $sentence{$id}[6];
			
#computo la distanza tra la testa e il dipendente e prendo solo le relazioni che hanno distanza entro una soglia k

			$depLeng = abs($headID-$id);
			
			unless ($depLeng > 10) {
			
#caso 1: soggetti (subj e subj_pass)
			
			
				if ($sentence{$id}[7] =~ /^(subj|subj_pass)$/ && $sentence{$id}[3] =~ /^(s|p)$/) {
					
					$subj{$headID} = "$sentence{$headID}[2]\t$sentence{$id}[7]=\"$sentence{$id}[2]\"";
				
					last VERBDEP
				}

#caso 2: oggetti diretti (obj)
			
				if ($sentence{$id}[7] =~ /^obj$/ && $sentence{$id}[3] =~ /^(s|p)$/) {
						
					$obj{$headID} = "$sentence{$id}[7]=\"$sentence{$id}[2]\"";
				
					last VERBDEP
				}
			
#caso 3: complementi indiretti clitici (comp_ind mi, gli, ecc.)
			
				if ($sentence{$id}[7] =~ /^comp_ind$/ && $sentence{$id}[3] =~ /^p$/) {
			
					push @{ $compFrame{$headID} },"comp_a=\"$sentence{$id}[2]\"";
				
					last VERBDEP
				}


#caso 4: dipendenze nominali / avverbiali introdotte da una preposizione (comp, comp_loc, comp_ind, ecc.) e completive infinitive
#(NB: prendo solo le dipendenze preposizionali post-verbali, eccetto per le relative)
			 
			 
			 	if ($sentence{$id}[7] =~ /^(comp_ind|comp_loc|comp|arg)$/ && $sentence{$id}[3] =~ /^e$/) {
			
					for (my $i = $id+1; $i <= $id+10; $i++) {
			
			#escludo i complementi preposizionali che precedono il verbo
			
						if ($sentence{$i}[7] =~ /^prep$/ && ($sentence{$i}[6] eq $sentence{$id}[0]) && $sentence{$i}[3] =~ /^(s|p|b)$/ &&
							$sentence{$id}[6] > $id) {

							next 
						
						} elsif ($sentence{$i}[7] =~ /^prep$/ && ($sentence{$i}[6] eq $sentence{$id}[0]) && $sentence{$i}[3] =~ /^(s|p|b)$/) {
							
							
							push @{ $compFrame{$headID} },"comp_$sentence{$id}[2]=\"$sentence{$i}[2]\"";
							
							last
							
						} elsif ($sentence{$i}[7] =~ /^prep$/ && ($sentence{$i}[6] eq $sentence{$id}[0]) && $sentence{$i}[3] =~ /^v$/ &&
								$sentence{$i}[5] =~ /^(f|mod=f)$/) {
							
							push @{ $clauFrame{$headID} },"inf_$sentence{$id}[2]=\"$sentence{$i}[2]\"";
						
							last;
					
						} else {
						
							next
						}
					}
				
					last VERBDEP
				}

		 
#caso 5: completive finite (arg)		
			
				if ($sentence{$id}[7] =~ /^arg$/ && $sentence{$id}[3] =~ /^c$/) {
			
					for (my $i = $id+1; $i <= $id+15; $i++) {
						
						if ($sentence{$i}[3] =~ /^v$/ && ($sentence{$i}[6] eq $sentence{$id}[0])) {
							
							push @{ $clauFrame{$headID} },"fin_$sentence{$id}[2]=\"$sentence{$i}[2]\"";
							
							last
						}
					}

					last VERBDEP
				}
			
			
#caso 6: complementi predicativi (pred) introdotti da una preposizione		
			
				if ($sentence{$id}[7] =~ /^(pred|pred_loc)$/ && $sentence{$id}[3] =~ /^e$/) {
							
					for (my $i = $id+1; $i <= $id+10; $i++) {
						
						if ($sentence{$i}[7] =~ /^prep$/ && ($sentence{$i}[6] eq $sentence{$id}[0])) {
							
							push @{ $clauFrame{$headID} },"cpred_$sentence{$id}[2]=\"$sentence{$i}[2]\"";
							
							last
							
						}
					}
				
					last VERBDEP
				}


#caso 7: complementi predicativi (pred) NON introdotti da una preposizione		


				if ($sentence{$id}[7] =~ /^(pred|pred_loc)$/) {
			
					push @{ $clauFrame{$headID} },"cpred=\"$sentence{$id}[2]\"";
							
					last VERBDEP
				}
				
				
#caso 8: modificatori avverbiali e verbali gerundiali NON introdotti da una preposizione (vengono
#(NB: vengono estratti solo i mod postverbali)	


				if ($sentence{$id}[7] =~ /^mod$/ && $sentence{$id}[6] < $id) {
			
					if ($sentence{$id}[3] =~ /^b$/) {

								
						push @{ $modFrame{$headID} },"modadv=\"$sentence{$id}[2]\""
								
					} elsif ($sentence{$id}[3] =~ /^v$/ && $sentence{$id}[5] =~ /^g$/) {
								
						push @{ $modFrame{$headID} },"modver=\"$sentence{$id}[2]\""
							
					}
							
					last VERBDEP
				}

#caso 9: frasi infinitivali NON introdotte da una preposizione (es. vedere correre)              


                                if ($sentence{$id}[7] =~ /^arg$/ && $sentence{$id}[5] =~ /^(f|mod=f)$/) {

                                        push @{ $clauFrame{$headID} },"inf_0=\"$sentence{$id}[2]\"";

                                        last VERBDEP
                                }
			}
		}
	}


#stampo i frames dei verbi nella frase

	foreach my $verbId (@verbs) {

#non stampo i verbi che sono al participio passato e sono modificatori (es. i treni arrivati)

		if ($sentence{$verbId}[7] =~ /^mod$/ && $sentence{$verbId}[5] =~ /^p$/) {
		
			next
		
		} else {

#ordino la lista dei complementi nominali e frasali
			
			print "@{$lemmaInfo{$verbId}}";
			
			if (exists $subj{$verbId}) {print " $subj{$verbId}"}
			if (exists $obj{$verbId}) {print " $obj{$verbId}"}
			
			if (exists $compFrame{$verbId}) {
				
				my @sortedCompFrame = sort @{$compFrame{$verbId}};
		 		
		 		print " @sortedCompFrame"
		 		
			}
		 	
		 	if (exists $clauFrame{$verbId}) {
		 		
		 		my @sortedClauFrame = sort @{$clauFrame{$verbId}};
		 		
		 		print " @sortedClauFrame"
		 		
		 	}
		 	
		 	if (exists $modFrame{$verbId}) {
		 		
		 		my @sortedModFrame = sort @{$modFrame{$verbId}};
		 		
		 		print " @sortedModFrame"
		 		
		 	}
		 	
		 	print "\n";
		}
	}	
}


###############################################################
# extractAframes sub
# input: sentence hash
# ouput: sentence hash
# la sub estrae per ogni aggettivo tutte le sue dipendenze sintattiche nella frase
################################################################



sub extractAframes {
	
	my ($hashRef) = @_;
	
	my %sentence = %$hashRef;
	
	my @ids = sort{$a <=> $b}(keys %sentence);
	
	my %pos;       #hash in cui vieme messo il nome modificato dall'aggettivo o il verbo di cui e' predicato
	my %compFrame; #hash di array: per ogni aggettivo contiene un array con i suoi comp preposizionali
	my %clauFrame; #hash di array: per ogni aggettivo contiene un array con i suoi comp frasali e predicativi
	my $headID;    #variabile che contiene la id della testa di una dipendenza	
	my $depLeng;   #distanza in token tra testa e dipendente
		
# percorro l'intero hash della frase ed estraggo le relazioni di dipendenza degli aggettivi
		
	foreach my $id (@ids) {
			
		ADJDEP: {
			
		#seleziono la testa del dipendente

			$headID = $sentence{$id}[6];
			
#computo la distanza tra la testa e il dipendente e prendo solo le relazioni che hanno distanza entro una soglia k

			$depLeng = abs($headID-$id);
			
			unless ($depLeng > 10) {

#caso 1: gestione dei congiunti nei modificatori prenominali o postnominali e negli aggettivi in posizione predicativa. Cattura dipendenze come "un collegamento diretto e costante" o "è giusto e doveroso".
			
			if ($sentence{$id}[3] =~ /^a$/ && $sentence{$id}[7] =~ /^(conj|disj)$/) {

					if ( ($sentence{$headID}[3] =~ /^a$/) || 
						($sentence{$headID}[3] =~ /^s$/ && $sentence{$headID}[7] =~ /^pred$/ ) ) {
						
						my $head_conj = $sentence{$headID}[6]; 

						if ($sentence{$head_conj}[3] =~ /^s$/) {

							if ($head_conj > $id) {
	
								$pos{$id} = "mod-post=\"$sentence{$head_conj}[2]\"";
		
							} elsif ($head_conj < $id) {
					
								$pos{$id} = "mod-pre=\"$sentence{$head_conj}[2]\""

							}
						}

						elsif ($sentence{$headID}[7] =~ /^pred$/) {

							$pos{$id} = "pred=\"$sentence{$head_conj}[2]\"";
		
						}

					}
			
					last ADJDEP

				}			

#caso 2: modificatori prenominali (abile calciatore) e postnominali (calciatore abile)

				if ($sentence{$id}[3] =~ /^a$/ && $sentence{$id}[7] =~ /^mod$/) {

#caso 2.1: modificatori prenominali
					
					if ($headID > $id && $sentence{$headID}[3] =~ /^s$/) {

	# poiché nella fase di preprocessing i sostantivi congiunti vengono uniti alla loro testa, si controlla se l'aggettivo corrente risulta erroneamente modificatore di più 		sostantivi (p.e. lemma="economico-a" mod-post="sviluppo-s;patria-s", dove "patria" era sostantivo congiunto a "sviluppo").
			
						if ($sentence{$headID}[2] =~ /^(.+?);(.+?)+$/) {

		# i sostantivi congiunti vengono eliminati se l'aggettivo è singolare oppure se l'aggettivo e il sostantivo da cui dipende sono al plurale, mentre il sostantivo 			congiunto è al singolare			

							if ( ($sentence{$id}[5] =~ /^num=s/) || ($sentence{$id}[5] =~ /^num=p/ && $sentence{$headID}[5] =~ /^num=p/) ) {

								my $noun = $sentence{$headID}[2];
								$noun =~ s/(.+?);(.+?)+$/\1/;

								$pos{$id} = "mod-post=\"$noun\"";	

							}

				
						}

		# un aggettivo che modifica due nomi congiunti viene associato a entrambi. Es. "lo spazio e il benessere comuni": "comune" dipende da "benessere", che è 			congiunto a "spazio" --> "comune" verrà registrato anche come modificatore di "spazio".

						elsif ($sentence{$id}[5] =~ /^num=p/ && $sentence{$headID}[7] =~ /^conj$/) {
						
							my $headNoun = $sentence{$headID}[6];							
							
							$pos{$id} = "mod-post=\"$sentence{$headNoun}[2]\"";
				
						}

		#caso semplice, senza congiunti

						else {
		
							$pos{$id} = "mod-post=\"$sentence{$headID}[2]\""
						
						}
			
#caso 2.2: modificatori post-nominali
	
					} elsif ($headID < $id && $sentence{$headID}[3] =~ /^s$/) {

				# identico procedimento dei modificatori prenominali: i sostantivi congiunti vengono eliminati se l'aggettivo è singolare oppure se l'aggettivo 				e il sostantivo da cui dipende sono al plurale, mentre il sostantivo congiunto è al singolare			


						
						if ($sentence{$headID}[2] =~ /^(.+?);(.+?)+$/) {

							if ( ($sentence{$id}[5] =~ /^num=s/) || ($sentence{$id}[5] =~ /^num=p/ && $sentence{$headID}[5] =~ /^num=p/) ) {
						
								my $noun = $sentence{$headID}[2];
								$noun =~ s/(.+?);(.+?)+$/\1/;
							
								$pos{$id} = "mod-pre=\"$noun\"";
				
							}

				# come sopra: un aggettivo che modifica due nomi congiunti viene associato a entrambi. Es. "lo spazio e il benessere comuni": "comune" dipende 					da "benessere", che è congiunto a "spazio" --> "comune" verrà registrato anche come modificatore di "spazio".

						} elsif ($sentence{$id}[5] =~ /^num=p/ && $sentence{$headID}[7] =~ /^conj$/) {
						
							my $headNoun = $sentence{$headID}[6];							
							
							$pos{$id} = "mod-pre=\"$sentence{$headNoun}[2]\"";
				
						}

				# caso semplice, senza congiunti

						else {
		
							$pos{$id} = "mod-pre=\"$sentence{$headID}[2]\""
						
						}
					
					}
				
					last ADJDEP
				}


#caso 2: aggettivo in posizione predicativa (pred) (essere fatale, sono contento...)

				if ($sentence{$id}[3] =~ /^a$/ && $sentence{$id}[7] =~ /^pred$/) {
				
					$pos{$id} = "pred=\"$sentence{$headID}[2]\""			
				}


#caso 3: dipendenze dell'aggettivo introdotte da una preposizione (comp, comp_temp, comp_loc, comp_ind, ecc.) e completive infinitive
			 
			 
				 if ($sentence{$id}[7] =~ /^(comp_ind|comp_loc|comp_temp|comp|arg)$/ && $sentence{$id}[3] =~ /^e$/) {
			
			
					for (my $i = $id+1; $i <= $id+10; $i++) {


						if ($sentence{$i}[7] =~ /^prep$/ && ($sentence{$i}[6] eq $sentence{$id}[0]) && $sentence{$i}[3] =~ /^(s|p)$/) {
							
							if ($sentence{$i}[7] =~ /^prep$/ && ($sentence{$i}[6] eq $sentence{$id}[0]) && $sentence{$i}[3] =~ /^(s|p|b)$/ && $sentence{$id}[6] > $id) {

								next 
						
							} else { #$sentence{$id}[6] < $id
							
								if ($sentence{$id}[7] =~ /^comp_ind$/) {
								
									push @{ $compFrame{$headID} },"comp-ind_$sentence{$id}[2]=\"$sentence{$i}[2]\""
								
								} elsif ($sentence{$id}[7] =~ /^comp_loc$/) {
								
									push @{ $compFrame{$headID} },"comp-loc_$sentence{$id}[2]=\"$sentence{$i}[2]\""
								
								} elsif ($sentence{$id}[7] =~ /^comp_temp$/) {
								
									push @{ $compFrame{$headID} },"comp-temp_$sentence{$id}[2]=\"$sentence{$i}[2]\""
							
								} else {
							
									push @{ $compFrame{$headID} },"comp_$sentence{$id}[2]=\"$sentence{$i}[2]\""
								}
							}
							
							last
							
						} elsif ($sentence{$i}[7] =~ /^prep$/ && ($sentence{$i}[6] eq $sentence{$id}[0]) && $sentence{$i}[3] =~ /^v$/ && $sentence{$i}[5] =~ /^(f|mod=f)$/) {


							push @{ $clauFrame{$headID} },"inf_$sentence{$id}[2]=\"$sentence{$i}[2]\"";
						
							last;
					
						} else {
						
							next
						}
					}
				
					last ADJDEP
				}

		 
#caso 5: completive finite (arg)		
			
				if ($sentence{$id}[7] =~ /^arg$/ && $sentence{$id}[3] =~ /^c$/) {
			
					$headID = $sentence{$id}[6];

					for (my $i = $id+1; $i <= $id+15; $i++) {
						
						if ($sentence{$i}[3] =~ /^v$/ && ($sentence{$i}[6] eq $sentence{$id}[0])) {
							
							push @{ $clauFrame{$headID} },"fin_$sentence{$id}[2]=\"$sentence{$i}[2]\"";
							
							last
						}
					}

					last ADJDEP
				}
			}
		}
	}


#stampo i frames degli aggettivi nella frase

	foreach my $adjId (@adjectives) {


#ordino la lista dei complementi
			
		if (exists $pos{$adjId}) {
			
			print "lemma=\"$sentence{$adjId}[2]\" $pos{$adjId}";
			
			if (exists $compFrame{$adjId}) {
				
				my @sortedCompFrame = sort @{$compFrame{$adjId}};
		 		
		 		print " @sortedCompFrame"
		 		
			}
		 	
			if (exists $clauFrame{$adjId}) {
		 		
		 		my @sortedClauFrame = sort @{$clauFrame{$adjId}};
		 		
		 		print " @sortedClauFrame"
		 		
			}	
		 	
		 	print "\n";
		 	
		}
	}		
}


###############################################################
# extractNframes sub
# input: sentence hash
# ouput: sentence hash
# la sub estrae per ogni nome tutte le sue dipendenze sintattiche nella frase
################################################################



sub extractNframes {
	
	my ($hashRef) = @_;
	
	my %sentence = %$hashRef;
	
	my @ids = sort{$a <=> $b}(keys %sentence);
	
	my %compFrame; #hash di array: per ogni nome contiene un array con i suoi comp preposizionali
	my %clauFrame; #hash di array: per ogni nome contiene un array con i suoi comp frasali e predicativi
	my %modFrame;  #hash di array: per ogni nome contiene un array con i suoi mod aggettivali
	my %conjFrame; #hash di array: per ogni nome contiene un array con i suoi congiunti nominali
	my $headID;    #variabile che contiene la id della testa di una dipendenza	
	my $depLeng;   #distanza in token tra testa e dipendente
	my @flags = ();#array in cui memorizzo gli id dei sostantivi che fanno parte di preposizioni e di cui quindi non deve essere stampato il lemma (per ora "parte" della preposizione "da parte di")
	my %detInfo;   #analogo a lemmaInfo dei verbi, registra la presenza di determinanti
	my %numInfo;   #registra se il nome prevede un modificatore numerale


# percorro l'intero hash della frase ed estraggo le relazioni di dipendenza dei verbi

		
	foreach my $id (@ids) {
		
			NOUNDEP: {	

#seleziono la testa del dipendente

				$headID = $sentence{$id}[6];
			
#computo la distanza tra la testa e il dipendente e prendo solo le relazioni che hanno distanza entro una soglia k

				$depLeng = abs($headID-$id);
			
				unless ($depLeng > 10) {

#caso 1: dipendenze dell'nome introdotte da una preposizione (comp, comp_temp, comp_loc, comp_ind, ecc.) e completive infinitive
#(NB: prendo solo le dipendenze preposizionali post-verbali, eccetto per le relative)
			 
			 		if ($sentence{$id}[7] =~ /^(comp_ind|comp_loc|comp_temp|comp|arg)$/ && $sentence{$id}[3] =~ /^e$/) {
			
						for (my $i = $id+1; $i <= $id+10; $i++) {
			
							if ($sentence{$i}[7] =~ /^prep$/ && ($sentence{$i}[6] eq $sentence{$id}[0]) && $sentence{$i}[3] =~ /^(s|p|b)$/) {
							
								if ($sentence{$id}[7] =~ /^comp_ind$/) {
								
									push @{ $compFrame{$headID} },"comp-ind_$sentence{$id}[2]=\"$sentence{$i}[2]\""
								
								} elsif ($sentence{$id}[7] =~ /^comp_loc$/) {
								
									push @{ $compFrame{$headID} },"comp-loc_$sentence{$id}[2]=\"$sentence{$i}[2]\""
								
								} elsif ($sentence{$id}[7] =~ /^comp_temp$/) {
								
									push @{ $compFrame{$headID} },"comp-temp_$sentence{$id}[2]=\"$sentence{$i}[2]\""
							
								} 
#gestione della preposizione "da parte di". Se il token corrente è un comp e il token è "da" (controllo il token e non il lemma per aggirare frasi del tipo "dalla parte dei bambini") allora creo una variabile j con cui controllare più comodamente se le parole successive sono "parte di".  

								elsif ($sentence{$id}[7] =~ /^comp$/ && $sentence{$id}[1] =~ /^[Dd]a$/) {

#superfluo controllare  che $sentence{$id}[4] =~ /^e$/, cioè che sia una preposizione semplice e non articolata perché nella condizione si verifica il token e non il lemma

									my $j = $id +1;

									if ($sentence{$j}[2] =~ /parte/ && $sentence{$j}[6] eq $sentence{$id}[0] && 										$sentence{$j+1}[2] =~ /di/) {

#Nel caso si superi il controllo, memorizzo l'id del token "parte" in un array @flags dichiarato all'inizio della procedura. In questo modo mi ricorderò di non stampare l'analisi di parte come sostantivo alla fine dell'analisi.
#Utilizzo un array e non uno scalare vero/falso per gestire i casi in cui compare più volte in una frase "da parte di"
									
										push (@flags,$sentence{$j}[0]);
									
										for (my $l = $j+2; $l <= $j+5; $l++) {

#Il ciclo for controlla le 3 parole successive a "da parte di", nel caso il sostantivo non sia immediatamente consecutivo (casi come "da parte di un misterioso anonimo") e crea un compFrame per il sostantivo (per "decisione da parte del governo" viene prodotto "comp_da_parte_di="governo"", associato all'headId, cioè a "decisione" 

											
										if ($sentence{$l}[3] =~ /^s$/ && $sentence{$l}[6] eq $sentence{$j+1}[0]) {
											
											push @{ $compFrame{$headID} }, "comp_da_parte_di=\"$sentence{$l}[2]\""
										}
										}

									}

#questo else gestisce tutti gli altri casi di complementi introdotti da "da"

									else {
										push @{ $compFrame{$headID} },"comp_$sentence{$id}[2]=\"$sentence{$i}[2]\""
									}
							
								}
#per i complementi rimanenti							
								else {
								
									push @{ $compFrame{$headID} },"comp_$sentence{$id}[2]=\"$sentence{$i}[2]\""
								}
							
								last
							
							} elsif ($sentence{$i}[7] =~ /^prep$/ && ($sentence{$i}[6] eq $sentence{$id}[0]) && $sentence{$i}[3] =~ /^v$/ &&
									$sentence{$i}[5] =~ /^(f|mod=f)$/) {
							
								push @{ $clauFrame{$headID} },"inf_$sentence{$id}[2]=\"$sentence{$i}[2]\"";
						
								last;
					
							} else {
						
								next
							}
						}
				
					last NOUNDEP
				}
					
#caso 2: completive finite (arg)		
			
				if ($sentence{$id}[7] =~ /^arg$/ && $sentence{$id}[3] =~ /^c$/) {
			
					for (my $i = $id+1; $i <= $id+15; $i++) {
						
						if ($sentence{$i}[3] =~ /^v$/ && ($sentence{$i}[6] eq $sentence{$id}[0])) {
							
							push @{ $clauFrame{$headID} },"fin_$sentence{$id}[2]=\"$sentence{$i}[2]\"";
							
							last
						}
					}

					last NOUNDEP
				}
			
#caso 3: modificatori aggettivali: gestisce aggettivi significativi e ignora determinanti, indefiniti ecc., mantenendo però traccia della loro presenza con l'etichetta "det".
	
				if ($sentence{$id}[7] =~ /^(det|mod)$/ && $sentence{$id}[4] =~ /^(pi|di|ri)$/) {		
		
						push @{ $detInfo{$headID} },"det=\"indef\""; 				

				}

				elsif ($sentence{$id}[7] =~ /^(det|mod)$/ && $sentence{$id}[4] =~ /^(pd|dd|rd)$/) {

						push @{ $detInfo{$headID} },"det=\"def\"";
					
				}

#Evita aggettivi possessivi e errori di parser (che riconosce i trattini del dialogo diretto come sostantivi). 
#Registra la presenza di numerali con attributo "modnum".


				if ($sentence{$id}[7] =~ /^mod$/) {
			

					if ($sentence{$id}[4] =~ /^a$/) {

						push @{ $modFrame{$headID} },"modadj=\"$sentence{$id}[2]\"";

					}
		
					elsif ($sentence{$id}[3] =~ /^n$/) {
										
						push  @{ $numInfo{$headID} },"modnum=\"yes\"";				
					}
				}

#caso 4: congiunzioni/disgiunzioni nominali	

				if ($sentence{$id}[7] =~ /^(conj|disj)$/) {
				
#caso 4.1: congiunti di complementi preposizionali. 

					if ($sentence{$id}[3] =~ /^e$/) {
#Esempio:
#1	Il	il	R	RD	num=s|gen=m	2	det
#2	cane	cane	S	S	num=s|gen=m	10	subj
#3	di	di	E	E	_	2	comp
#4	mia	mio	A	AP	num=s|gen=f	5	mod
#5	zia	zia	S	S	num=s|gen=f	3	prep
#6	e	e	C	CC	_	3	con
#7	di	di	E	E	_	3	conj
#8	mio	mio	A	AP	num=s|gen=m	9	mod
#9	cugino	cugino	S	S	num=s|gen=m	7	prep

#Si sta esaminando l'array del token 7.
#Individuo la testa di cong (token 3), che è la preposizione del gruppo preposizionale a cui si congiunge il gruppo corrente. 

						my $headPrep = $sentence{$id}[6];

#Individuo la testa nominale del gruppo preposizionale, a cui voglio associare i complementi e i loro congiunti.

						my $groupHead = $sentence{$headPrep}[6];

#Il ciclo for analizza i token successivi alla preposizione per catturare il nome del complemento preposizionale (ed evitare così i modificatori)

						my $m = $id+1;

						while ($m < $id+5) {

							if ($sentence{$m}[7] =~ /^prep$/) {

#sistema etichette come "conj_comp_loc_in" o "conj_comp_temp_durante" in "conj_comp-loc_in" e "conj_comp-temp_durante", seguendo la convenzione usata per i comp

								$sentence{$headPrep}[7] =~ s/comp_loc/comp-loc/g;
								$sentence{$headPrep}[7] =~ s/comp_loc/comp-temp/g;

								push @{ $conjFrame{$groupHead} }, "$sentence{$id}[7]_$sentence{$headPrep}[7]_$sentence{$id}[2]=\"$sentence{$m}[2]\"";
								

								last
							}

							$m++;
						}
					}
#caso 2: congiunti di nomi

					elsif ($sentence{$id}[3] =~ /^s$/) {

						push @{ $conjFrame{$headID} },"conj=\"$sentence{$id}[2]\"";

					}	
			
					last NOUNDEP
				}
			}
		}
	}


#stampa i frames dei nomi nella frase

	foreach my $nounId (@nouns) {

#Salta l'analisi di sostantivi inclusi in preposizioni, come "parte" in "da parte di". Nel dettaglio, se in extractNFrames ho memorizzato in @flags l'id 20 del token "parte", ora controllo che "20" non sia presente nell'array. Se lo è, con next riavvio il ciclo.
	
	if (  grep ( { $_ == $nounId } @flags)) { next }

	else {

#rimuove i doppi lemmi per il trattamento della congiunzione aggiunti nella fase di preprocessing

		$sentence{$nounId}[2] =~ s/;.+$//g;

		print "lemma=\"$sentence{$nounId}[2]\"";
			
		
		if (exists $detInfo{$nounId}) {	

			print " @{$detInfo{$nounId}}";
		 		
		}	

		if (exists $compFrame{$nounId}) {
				
			my @sortedCompFrame = sort @{$compFrame{$nounId}};
		 		
		 		print " @sortedCompFrame"
		}
		 	
		if (exists $clauFrame{$nounId}) {
		 		
		 	my @sortedClauFrame = sort @{$clauFrame{$nounId}};
		 		
		 		print " @sortedClauFrame"
		 		
		}
		
		if (exists $modFrame{$nounId}) {

		 	my @sortedModFrame = sort @{$modFrame{$nounId}};

#trasforma l'array in stringa e trasforma le sequenze 'modadj="...";modadj="";...' in 'modadj=...;...;...;'

			my $adj = join(';', @sortedModFrame);

			$adj =~ s/modadj=\"(.+?)\"/\1/g;

			print " modadj=\"$adj\"";
		 		
		}

		if (exists $numInfo{$nounId}) {	

			print " @{$numInfo{$nounId}}";
		 		
		}	

		if (exists $conjFrame{$nounId}) {
		 		
		 	my @sortedConjFrame = sort @{$conjFrame{$nounId}};
		 		
		 		print " @sortedConjFrame"
		 		
		}	
		 	
		print "\n";
		 	
	}
	} #parentesi che chiude l'else 
}							

