public Boolean visitShiftAction(ShiftAction action)
	throws CopperException
	{
		for(QScannerMatchData layout : lookahead.getLayouts())
		{
			try
			{
				runSemanticAction(layout.getPositionPreceding(),layout);
			}
			catch(IOException ex)
			{
				reportError("I/O error in semantic action: " + ex.getMessage());
			}
			virtualLocation.defaultUpdateAutomatic(layout.getToken().getLexeme());
		}
		Object newNode = null;
		try
		{
			newNode = runSemanticAction(lookahead.getPositionPreceding(),lookahead);
		}
		catch(IOException ex)
		{
			reportError("I/O error in semantic action: " + ex.getMessage());
		}
		Terminal lookaheadTok;
		InputPosition positionPreceding,positionFollowing;
		if(getSpecialAttributes().latchLocation) lookaheadTok = lookahead.getToken().newLexeme("");
		else lookaheadTok = lookahead.getToken();
		positionPreceding = currentState.getPos();
		if(getSpecialAttributes().latchLocation)
		{
			positionFollowing = InputPosition.copy(currentState.getPos());
		}
		else positionFollowing = lookahead.getPositionFollowing();
		virtualLocation.defaultUpdateAutomatic(lookaheadTok.getLexeme());
		if(newNode != null && newNode.equals("PARSETREE"))
		{
			newNode = parseTree.termNode(lookaheadTok,positionPreceding/*,positionFollowing*/,new VirtualLocation(virtualLocation));
			parseTree.setRoot((ParseTreeNode) newNode);
		}
		parseStack.push(Pair.cons(new ParserState(action.getDestState(),positionFollowing),newNode));
		return true;
	}