/*
* Copyright 2010 Jan Schmidt-Reinisch
*
* SoundComp - a sound processing library
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; in version 2.1
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* A helper class that holds a parser state stack (in form of a linked list)
* in a static ThreadLocal so it can always be queried.
*
* The last element in the list is the newest stack element.
*
* The parser state stack is needed to find the most local element for a certain name.
*
* This is entirely for future use and nowhere used yet.
*/
package de.maramuse.soundcomp.parser;
import java.util.LinkedList;
import de.maramuse.soundcomp.parser.SCParser.ParserVal;
public class ParserState {
private static ThreadLocal<ParserState> theState=new ThreadLocal<ParserState>();
LinkedList<ParserStateElement> stack;
/**
* creates a ParserState
*/
private ParserState(){
stack=new LinkedList<ParserStateElement>();
}
/**
* push one element onto the parser state stack
* @param val the ParserVal that represents the state
*/
public void push(ParserVal val){
ParserStateElement elem=new ParserStateElement(val);
stack.addLast(elem);
}
/**
* remove the last element from the parser state stack
*/
public void pop(){
stack.removeLast();
}
/**
* returns the current state stack size
* @return the current state stack size
*/
public static int stackSize(){
ParserState state=getParserState();
return state.stack.size();
}
/**
* remove the current thread from parser state handling
*/
public static void clearState(){
theState.remove();
}
/**
* returns the current thread's parser state
* @return the current thread's parser state
*/
public static ParserState getParserState(){
ParserState state=theState.get();
if(state==null){
state=new ParserState();
theState.set(state);
}
return state;
}
private ParserStateElement getUp(ParserStateElement elem){
int index=stack.indexOf(elem);
if(index<=0)return null;
return stack.get(index-1);
}
/**
* returns the previous parser state element, relative to the given element
* used to "climb up" the stack.
* @param elem the element, relative which we want to "climb up"
* @return the previous element
*/
public static ParserStateElement up(ParserStateElement elem){
ParserState state=getParserState();
return state.getUp(elem);
}
public static ParserStateElement current(){
return getParserState().stack.getLast();
}
/**
* finds the nearest definition of an element with the given name in the parser stack
* @param name the name to search
* @return the symbol that occupies the name
*/
public static ParserVal findElement(String name){
ParserStateElement current=current();
while(current!=null){
ParserVal val=current.getElement(name);
if(val!=null)return val;
current=up(current);
}
return null;
}
/**
* finds the nearest definition of an element with the given name in the parser stack
* @param name the name to search
* @return the container of the symbol that occupies the name
*/
public static ParserVal findContainer(String name){
ParserStateElement current=current();
while(current!=null){
ParserVal val=current.getElement(name);
if(val!=null)return current.val;
current=up(current);
}
return null;
}
}