/** TranslationScanner
Anton Dubrau, comp202, summer2010

This class is similar to a Scanner - it reads a String, and will return tokens and delimiters
from it. It is different in that the delimiters can be returned just like the tokens.
It uses letters and numbers (and apostrophes enclosed by them) as tokens -- basically any
word and or number, including contractions are tokens.
Delimters are anything else. See the main method for an example how it works.
*/
  
import java.util.Scanner;


public class TranslationScanner{
  private String text; //the String we are scanning through
  private int i = 0; // the current position in the text
  
  //the constructor simply takes a String to be scanned
  public TranslationScanner(String text){
    this.text = text;
  }

  //returns true if the next characters form a word
  //returns false otherwise, or if ther are no more characters
  public boolean hasNextWord(){
    //there is a word if the next character is a letter or digit (and there are characters left)
    return (i < text.length()) && Character.isLetterOrDigit(text.charAt(i));
  }

  //returns true if the next characters do not form a word
  //returns false otherwise, or if ther are no more characters
  public boolean hasNextDelimiter(){
    //as above, but the other way round
    return (i < text.length()) && !Character.isLetterOrDigit(text.charAt(i));
  }

  //returns true if we are not at the end of the string
  public boolean hasNext(){
    return i < text.length();
  }

  
  //returns the next word as a String, or null if there are no more characters, or if the
  //the next characters do not form a word
  public String nextWord(){
    if (!hasNextWord()) return null;

    String s = "";
    while(i < text.length() && //go through while we are not at the end..
          (Character.isLetterOrDigit(text.charAt(i)) //..a character that is not part of a word..
           || (text.charAt(i) == '\'' //..or we have a contraction (apostrophe enclosed by letters/digits
               && s.length() > 0 
               && (i+1 < text.length() && Character.isLetterOrDigit(text.charAt(i+1)))))){
      s += text.charAt(i++);
    }
    return s;
  }

  //returns the next delimiter as a String, or null if there are no more characters,
  //or if the next characters form a word
  public String nextDelimiter(){
    if (!hasNextDelimiter()) return null;
    String s = "";
    while(i < text.length() && !Character.isLetterOrDigit(text.charAt(i))){
      s += text.charAt(i++);
    }
    return s;
  }


  //testing code
  //this will read text from System.in and for every line spit back the tokens and delimiters
  public static void main(String[] args){
    Scanner scan = new Scanner(System.in); //create scanner from system input
    while (scan.hasNext()){
      TranslationScanner s = new TranslationScanner(scan.nextLine()); //create translation scanner from next line
      while (s.hasNext()){
        if (s.hasNextWord()){ //case token
          System.out.println("word:  <"+s.nextWord()+">");
        } else { //case delimiter
          System.out.println("delim: <"+s.nextDelimiter()+">");
        }
      }
    }
  }

}

