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(); } }