import java.io.*;
import java.util.*;
import asd.*;

/**
   An example application of the ASDParser and an ASDGrammar
   to translate English numeral phrases like <BR>
   <tt><b>two million one hundred and forty three thousand and sixty five"
   </tt></b><BR>to integer numbers.
<BR><BR>
   Command-line usage:
   <BR>In an MS-Windows command-line window:
   <BR><tt><b> java -cp asddigraphs.jar;. Numerals</b></tt>
   <BR>Or under UNIX:
   <BR><tt><b> java -cp asddigraphs.jar:. Numerals</b></tt>
   <BR>OR if asddigraphs.jar has been put in the system classpath:
   <BR><tt><b> java Numerals</b></tt>
   <BR>Add the word "show" to the end of the command to display parse trees:
   <BR><tt><b> java -cp asddigraphs.jar;. Numerals show</b></tt>
   <BR><tt><b> java -cp asddigraphs.jar:. Numerals show</b></tt>
   <BR><tt><b> java Numerals show</b></tt>

   @author James A. Mason
   @version 1.02 2001 August 30; 2002 Jan, Feb
 */
public class Numerals
{
   public static void main(String[] args)
   {  boolean showParseTrees = false;
      if (args.length > 0 && args[0].equalsIgnoreCase("show"))
         showParseTrees = true;
      BufferedReader keyboard = new BufferedReader(
         new InputStreamReader(System.in));
      String phrase = null;
      Numerals numeralInterpreter = new Numerals();
      ASDParser parser = new ASDParser(numeralInterpreter);
         // Use the parser itself as the semantics,
         // and the numeralInterpreter as the application.
      numeralInterpreter.setParser(parser);
      parser.useGrammar("cardinal.grm");
      ArrayList expectedTypes = new ArrayList(10);
      expectedTypes.add("CARDINAL");
      int numberOfSteps = 0;
      while(true)
      {  System.out.println("Phrase to parse? ");
         try
         {  phrase = keyboard.readLine();
         }
         catch(IOException e)
         {  System.out.println(e);
            System.exit(0);
         }
         if (phrase == null || phrase.length() == 0) break;
         parser.initialize(phrase, expectedTypes);
         numberOfSteps = parser.parse(MAXIMUM_STEPS);
         if (numberOfSteps >= 0)
         {
            System.out.println(
               parser.currentNode().nextNode().value());
            if (showParseTrees)
               parser.showTree();
         }
         else
            System.out.println("I don't understand.");
      }
   } // end main

   public void setParser(ASDParser p) { parser = p; }

   public String unit_2_action()
   {  parser.set("V", new Long(longValueOfV() + longNodeValue()));
      return null;
   }
   public long longNodeValue()
   {  return ((Long)nodeValue()).longValue();
   }
   public Object nodeValue()
   {  return parser.currentNode().value();
   }
   public String cardinal_2_action()
   {  if (longNodeValue() >= valueOfM().longValue())
         return parser.NOADVANCE;
      else
         return setV2NodeValue();
   }
   public String setVNodeValue()
   {  parser.set("V", nodeValue()); return null; }
   public String setV2NodeValue()
   {  parser.set("V2", nodeValue()); return null; }
   public Long valueOfM() { return (Long)parser.valueOf("M"); }
   public long longValueOfM() { return valueOfM().longValue(); }
   public long longValueOfV() { return valueOfV().longValue(); }
   public long longValueOfV2() { return valueOfV2().longValue(); }
   public String multiplier_1_action()
   {  if (longValueOfV() >= longNodeValue())
         return parser.NOADVANCE;
      else
      {  parser.set("M", nodeValue()); return null; }
   }
   public Long valueOfV() { return (Long)parser.valueOf("V"); }
   public Long valueOfV2() { return (Long)parser.valueOf("V2"); }
   public Long valueOfVTimesM()
   {  return new Long(longValueOfV() * longValueOfM()); }
   public Long valueOfVTimesMPlusV2()
   {  return new Long(longValueOfV() * longValueOfM() + longValueOfV2()); }

   public String UNKNOWNCARDINAL_action()
   {  String word = parser.currentNode().subphrase().word();
      if (word.indexOf('-') < 0) // not a hyphenated word
         return parser.NOADVANCE;
      else // try to parse the hyphenated word separately as a numeral:
      {  Numerals numeralInterpreter2 = new Numerals();
         ASDParser parser2 = new ASDParser(numeralInterpreter2);
         numeralInterpreter2.setParser(parser2);
         parser2.setSPECIALCHARS(parser.SPECIALCHARS + "-");
            // Have parser2 break the word at the hyphen.
         parser2.useGrammar(parser.lexicon());
         parser2.initialize(word, parser.expectedTypes());
         int numberOfSteps = parser2.parse(MAXIMUM_STEPS);
         if (numberOfSteps < 0)
            return parser.NOADVANCE;
         parser.set("V", parser2.currentNode().nextNode().value());
         return null;
      }
   } // end UNKNOWNCARDINAL_action

   private static final int MAXIMUM_STEPS = 200;
   private ASDParser parser;
} // end class Numerals

