package logo.lang;

import java.util.StringTokenizer;
import java.util.Stack;
import logo.lang.rLogoException;

public class LogoList {
//LogoList is used to parse one or more user commands and push
//them onto a stack for later processing. Commands and arguments
//are expected to be separated by spaces. If a ' is encountered,
//everything following it is ignored, until a newline is reached.

   Stack stack = new Stack();

   public LogoList(String command) throws rLogoException {

      StringTokenizer st = new StringTokenizer(command,"' []()\n\t",true);
      Stack tempStack = new Stack(); //a temporary stack is employed,
      String nextItem = new String();

      while ( st.hasMoreTokens() ) {
         String nextToken=st.nextToken();
         if ( nextToken.equals("'") ) { //ignore anything following a ' until a newline is reached.
            while ( st.hasMoreTokens() && !nextToken.equals("\n") ) {
              nextToken=st.nextToken();
            }
            nextToken=""; //Force nextToken to be empty, in case we ran out of tokens.
         }
         if ( nextToken.equals("]") ) throw(new rLogoException("Syntax error: Got ']' before '['"));
         if ( nextToken.equals(")") ) throw(new rLogoException("Syntax error: Got ')' before '('"));
         if ( nextToken.equals("[") ) {
            nextToken=findClosingSymbol(st,"[","]");
         } else if ( nextToken.equals("(") ) {
                    nextToken=findClosingSymbol(st,"(",")");
                }
         if ( nextToken.trim().length()==0 ) { //
           if ( nextItem.trim().length()>0 ) {
              tempStack.push(nextItem);
              nextItem="";
           }
         } else nextItem=nextItem+nextToken;
      }
      //push the final item:
      if ( nextItem.trim().length()>0 ) {
        tempStack.push(nextItem);
        nextItem=null;
      }

      //reverse the stack:
      while ( !tempStack.empty() ) {
         stack.push(tempStack.pop());
      }
  }

  private final String findClosingSymbol(StringTokenizer st, String openSymbol, String closeSymbol) throws rLogoException {
  //If the next token begins with a openSymbol (e.g. '(' or '[' ), then concatenate all
  //of the remaining tokens until the closingSymbol (e.g. ')' or ']') is found:

  //Note: if closeSymbol==openSymbol, then nesting is not allowed.

    String result=new String(openSymbol);
    int listCount=1; //tracks how many openSymbols have been encountered
    String subToken;
    while ( listCount>0 && st.hasMoreTokens() ) {
        subToken=st.nextToken();
        result=result+subToken;
        if ( subToken.equals(closeSymbol) ) listCount--;
        else if ( subToken.equals(openSymbol) ) listCount++;
    }
    if ( listCount>0 ) throw(new rLogoException("Syntax error: '"+closeSymbol+"' not found"));
    return result;
  }


  public final String pop() {
    String result=null;
    if (!stack.empty()) {
        result = (String)stack.pop();
    }
    return result;
  }

   public boolean empty() {
      return stack.empty();
   }

}
