import java.util.*;
import java.io.*;

//Input: A sequence of words
//Output: All possible analyses of each word written in a lisp-like structure

public class AvenueMorphologyServer {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//final int MaxTokenLength = 256;
		
		try {
			// lookup table for feature names
			String [][] Features = {
					{"\\+Noun","    (POS Noun)"},
					{"\\+Adj","    (POS Adj)"},
					{"\\+Verb","    (POS Verb)"},
					{"\\+Adverb","    (POS Adverb)"},
					{"\\+Det","    (POS Det)"},
					{"\\+Conj","    (POS Conj)"},
					{"\\+Num","    (POS Num)"},
					{"\\+Pron","    (POS Pron)"},
					{"\\+Interj","    (POS Interj)"},
					{"\\+Postp","    (POS Postp)"},
					{"\\+Dup","    (POS Dup)"},
					{"\\+A1sg","    (AGR-PERSON 1)    (AGR-NUMBER Sg)"},
					{"\\+A2sg","    (AGR-PERSON 2)    (AGR-NUMBER Sg)"},
					{"\\+A3sg","    (AGR-PERSON 3)    (AGR-NUMBER Sg)"},
					{"\\+A1pl","    (AGR-PERSON 1)    (AGR-NUMBER Pl)"},
					{"\\+A2pl","    (AGR-PERSON 2)    (AGR-NUMBER Pl)"},
					{"\\+A3pl","    (AGR-PERSON 3)    (AGR-NUMBER Pl)"},
					{"\\+P1sg","    (POSS-PERSON 1)    (POSS-NUMBER Sg)"},
					{"\\+P2sg","    (POSS-PERSON 2)    (POSS-NUMBER Sg)"},
					{"\\+P3sg","    (POSS-PERSON 3)    (POSS-NUMBER Sg)"},
					{"\\+P1pl","    (POSS-PERSON 1)    (POSS-NUMBER Pl)"},
					{"\\+P2pl","    (POSS-PERSON 2)    (POSS-NUMBER Pl)"},
					{"\\+P3pl","    (POSS-PERSON 3)    (POSS-NUMBER Pl)"},
					{"\\+Pnon","    (POSS-PERSON None)    (POSS-NUMBER None)"},
					{"\\+Nom","    (CASE Nom)"},
					{"\\+Acc","    (CASE Acc)"},
					{"\\+Dat","    (CASE Dat)"},
					{"\\+Able","    (TYPE Able)"},
					{"\\+Abl","    (CASE Abl)"},
					{"\\+Loc","    (CASE Loc)"},
					{"\\+Gen","    (CASE Gen)"},
					{"\\+Ins","    (CASE Ins)"},
					{"\\+Equ","    (CASE Equ)"},
					{"\\+Zero","    (TYPE Zero)"},
					{"\\+Rel","    (TYPE Rel)"},
					{"\\+Prop","    (TYPE Proper)"},
					{"\\+Become","    (TYPE Become)"},
					{"\\+Pers","    (TYPE Personal)"},
					{"\\+Demons","    (TYPE Demonstrative)"},
					{"\\+Quant","    (TYPE Quantifying)"},
					{"\\+Ques","    (TYPE Question)"},
					{"\\+Reflex","    (TYPE Reflexive)"},
					{"\\+Recip","    (TYPE Reciprocal)"},
					{"\\+Caus","    (TYPE Causative)"},
					{"\\+Pass","    (TYPE Passive)"},
					{"\\+PastPart","    (TYPE PastPart)"},
					{"\\+Past","    (TENSE-ASPECT-MOOD Past)"},
					{"\\+Narr","    (TENSE-ASPECT-MOOD Narrative)"},
					{"\\+FutPart","    (TYPE FutPart)"},
					{"\\+Fut","    (TENSE-ASPECT-MOOD Future)"},
					{"\\+PresPart","    (TYPE PresPart)"},
					{"\\+Pres","    (TENSE-ASPECT-MOOD Present)"},
					{"\\+Aor","    (TENSE-ASPECT-MOOD Aorist)"},
					{"\\+Imp","    (TENSE-ASPECT-MOOD Imperative)"},
					{"\\+Opt","    (TENSE-ASPECT-MOOD Optative)"},
					{"\\+Cond","    (TENSE-ASPECT-MOOD Conditional)"},
					{"\\+Desr","    (TENSE-ASPECT-MOOD Desiderative)"},
					{"\\+Prog1","    (TENSE-ASPECT-MOOD Progressive1)"},
					{"\\+Prog2","    (TENSE-ASPECT-MOOD Progressive2)"},
					{"\\+Neces","    (TENSE-ASPECT-MOOD Necessitative)"},
					{"\\+Pos","    (POLARITY Positive)"},
					{"\\+Neg","    (POLARITY Negative)"},
					{"\\+Agt","    (TYPE Agent)"},
					{"\\+Acquire","    (TYPE Acquire)"},
					{"\\+ActOf","    (TYPE ActOf)"},
					{"\\+Adamantly","    (TYPE Adamantly)"},
					{"\\+AfterDoingSo","    (TYPE AfterDoingSo)"},
					{"\\+Almost","    (TYPE Almost)"},
					{"\\+AsIf","    (TYPE AsIf)"},
					{"\\+AsLongAs","    (TYPE AsLongAs)"},
					{"\\+ByDoingSo","    (TYPE ByDoingSo)"},
					{"\\+Card","    (TYPE Cardinal)"},
					{"\\+Ord","    (TYPE Ordinal)"},
					{"\\+Continue","    (TYPE Continue)"},
					{"\\+Cop","    (COPULA Yes)"},
					{"\\+Dim","    (TYPE Diminutive)"},
					{"\\+Dist","    (TYPE Distributive)"},
					{"\\+EverSince","    (TYPE EverSince)"},
					{"\\+FeelLike","    (TYPE FeelLike)"},
					{"\\+FitFor","    (TYPE FitFor)"},
					{"\\+InBetween","    (TYPE InBetween)"},
					{"\\+Inf1","    (TYPE Infinitive1)"},
					{"\\+Inf2","    (TYPE Infinitive2)"},
					{"\\+Inf3","    (TYPE Infinitive3)"},
					{"\\+JustLike","    (TYPE JustLike)"},
					{"\\+Ly","    (TYPE Ly)"},
					{"\\+Ness","    (TYPE Ness)"},
					{"\\+NotAbleState","    (TYPE NotAbleState)"},
					{"\\+NotState","    (TYPE NotState)"},
					{"\\+PCAbl","    (SUBCAT Abl)"},
					{"\\+PCNom","    (SUBCAT Nom)"},
					{"\\+PCAcc","    (SUBCAT Acc)"},
					{"\\+PCDat","    (SUBCAT Dat)"},
					{"\\+PCGen","    (SUBCAT Gen)"},
					{"\\+PCIns","    (SUBCAT Ins)"},
					{"\\+Related","    (TYPE Related)"},
					{"\\+Since","    (TYPE Since)"},
					{"\\+SinceDoingSo","    (TYPE SinceDoingSo)"},
					{"\\+Start","    (TYPE Start)"},
					{"\\+Stay","    (TYPE Stay)"},
					{"\\+When","    (TYPE When)"},
					{"\\+While","    (TYPE While)"},
					{"\\+Without","    (TYPE Without)"},
					{"\\+With","    (TYPE With)"},
					{"\\++WithoutBeingAbleToHaveDoneSo","    (TYPE +WithoutBeingAbleToHaveDoneSo)"},
					{"\\++WithoutHavingDoneSo","    (TYPE +WithoutHavingDoneSo)"},
					
			};
			
			BufferedReader stdin =
				new BufferedReader(
						new InputStreamReader(System.in)); 
			FSTransducer MATransducer = new FSTransducer("ldb/tfeatures.bin");
			// Transducer is now loaded 
			/* We now have an infinite lookup where we read a word from the standard in
			 * and morphologically analyze it and convert it to a nested feature structure
			 * as a character string
			 */
			
			String  InputToken = "",InputLine="";
			String[] InputTokens,IGs;		
			String  MorphAnalysis = "", Output="";
			int globSpan=0;		//counter for span number of words
			LinkedList LookupResults;
			ListIterator Analysis;
			
			while(true){
				{System.out.println("Waiting for Input");}
				InputLine=stdin.readLine();
				//InputLine=AvenueMorphologyServer.convEnc(InputLine);
				InputTokens = InputLine.split(" ");
				//System.out.print("(");
				for(int i=0;i<InputTokens.length;i++){
					//Current word of the sentence that we are analysing is InputToken
					InputToken=InputTokens[i];
					LookupResults= MATransducer.Look(InputToken,1,true);
					Analysis= LookupResults.listIterator();
					int maxIG=0,curIG=0;	//the number of max IG's in an analysis
					
					
					ListIterator AnalysisCopy = LookupResults.listIterator();
					if(!Analysis.hasNext()){
						String UnknownAnalysis="";
						UnknownAnalysis += "(((LEX  \""+InputToken+")";
						UnknownAnalysis += "(POS Noun)(TYPE **UNKNOWN**)";
						UnknownAnalysis +="(AGR-PERSON 3)(AGR-NUMBER Sg)";
						UnknownAnalysis +="(POSS-PERSON None)(POSS-NUMBER None)";
						UnknownAnalysis +="(CASE Nom))";
						System.out.print(UnknownAnalysis+")");
						
					}
					else
						//loop to find the analysis with maximum number of IG's, and store that number
						while(AnalysisCopy.hasNext()){
							MorphAnalysis = (String)(AnalysisCopy.next());
							curIG=MorphAnalysis.split("\\^DB").length;
							if(curIG > maxIG){
								maxIG=curIG;
							}					
						}
						while(Analysis.hasNext()){
								//MorphAnalysis.replaceAll("\\^DB", "**Derivation Boundary**");
							MorphAnalysis = (String)(Analysis.next());
								//System.out.println(MorphAnalysis);
							//separate analysis into IG's
							IGs=MorphAnalysis.split("\\^DB");
							//set starting point for span counter
							int locSpan=globSpan;		//counter for span number of parses
							
							for(int j=0;j<IGs.length;j++){	
								Output=IGs[j];
								if(j==0){	//if first IG, therefore contains root
									Output=Output.replaceFirst("^([^+]+)", "    (LEX \"$1\")");
								}
								
								for(int i1=0;  i1 < Features.length;i1++){
									Output=Output.replaceAll(Features[i1][0],Features[i1][1]);
								}
								//determine the SPANSTART and SPANEND of this IG
								int startOfIG,endOfIG;
								startOfIG=locSpan;
								//if this IG is short, we just jump to the end
								if(j==IGs.length-1)
									endOfIG=globSpan+maxIG;
								else
									endOfIG=locSpan+1;
								//increment the local span counter for next IG
								locSpan++;
								//Add the features
								Output="(    (SPANSTART "+ startOfIG +")    (SPANEND "+ endOfIG +")"+Output+")";
								System.out.print(Output);
							}						
						}
					
					//increment the global span counter for next word
					globSpan=globSpan+maxIG;
				}
				System.out.println("");
			} 
		}
		catch (Exception e) {System.out.println("Exception");}
		
		
	}
}


