void send_all(const ID& client_id)
  {
    update_packet msg;
    msg.type = update_packet::complete;
    msg.num_entries = list_.size();
    msg.start_index = 0;
    msg.end_index = state_index_;

    outbound_data<serializer::boost_serializer, update_packet> o_msg(msg);
    outbound_data<serializer::boost_serializer, list_type> o_list(list_);
    outbound_pair o_pair(o_msg, o_list);

    send_to_instance(client_id, header_packet::update, o_pair);
  }
  void send_updates(const ID& client_id)
  {
    update_packet msg;
    msg.type = update_packet::partial;
    msg.num_entries = list_.size();
    msg.start_index = last_update_sent_;
    msg.end_index = state_index_;

    outbound_data<serializer::boost_serializer, update_packet> o_msg(msg);
    outbound_data<serializer::boost_serializer, list_type> o_list1(added_list_);
    outbound_data<serializer::boost_serializer, list_type> o_list2(removed_list_);
    outbound_pair o_list(o_list1, o_list2);
    outbound_pair o_pair(o_msg, o_list);

    send_to_instance(client_id, header_packet::update, o_pair);
  }
/**
 * Function representing the <st_factor_ident> prods
 */
void RecursiveDescentParser::st_factor_ident(TableEntry* te) {
	if(errorCondition) return;
	if(token == TK_LEFT_PARENTHESES) 
	{
#if DEBUG_PARSER
		std::cout << "<st_factor_ident> --> (<o_list>);\n";
#endif
		Token leftParen = token;
		token = scanner->getToken();
		ParamList* pList = o_list();
		
		if(te) {
			if(te->getEntryType()!=TableEntry::FUNCTION) {
				std::stringstream errorMsg;
				errorMsg << "'" << te->getName() << "' is not a function";
				errorHandler(errorMsg.str(), leftParen);
			} else {
				// now makes sure the lists match
				FunctionEntry* fe = (FunctionEntry*)te;
				if(pList) matchParameters(fe, pList, leftParen);
				
				iCode.threeAddressCode(TAC_PARAM, pList);
				iCode.threeAddressCode( 
						symTab.getNextAddress(), // throw away temporary
						TAC_CALL, 
						fe->getLabel(), 
						fe->getParamCount()
					);
			}
		} else {
			std::stringstream errorMsg;
			errorMsg << "Undeclared function";
			errorHandler(errorMsg.str(), leftParen);
		}
		
		match(TK_RIGHT_PARENTHESES);
		match(TK_SEMICOLON);
	} 
	else if(token == TK_LEFT_BRACKET || 
			token == TK_ASSIGNMENT) 
	{
#if DEBUG_PARSER		
		std::cout << "<st_factor_ident> --> <var_prime>=<exp>;\n";
#endif
		VariableEntry* vEntry = (VariableEntry*)te;
		Token startToken = token;
		
		attr varAttr  = var_prime(vEntry);
		match(TK_ASSIGNMENT);
		attr expAttr = exp();
		
		if(expAttr.type != varAttr.type) {
			std::stringstream errorMsg;
			errorMsg << "Type mismatch variable '" << vEntry->getName() << "'";
			errorHandler(errorMsg.str(), startToken);
		}
		
		if(varAttr.attrib == VA_ARRAY) {
			std::stringstream errorMsg;
			errorMsg << "Assignment error, array '" << vEntry->getName() << "' must be indexed.";
			errorHandler( errorMsg.str(), startToken );
		}
		
		if(vEntry->getAttribute() == VA_ARRAY) {
			//                       array addr                           value to assign   index
			iCode.threeAddressCode(vEntry->getAttr(), TAC_ASSIGN_TO_ADDRESS_AT, expAttr, varAttr);
		} else {
			iCode.threeAddressCode(vEntry->getAttr(), TAC_ASSIGN, expAttr);
		}
		
		match(TK_SEMICOLON);
	} 
	else 
	{
		errorHandler();
	}
}
/**
 * Functions representing the <st> productions
 */
void RecursiveDescentParser::st() {
	if(token == TK_SEMICOLON) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> ;\n";
#endif
		token = scanner->getToken();
	} 
	else if(token == TK_LEFT_BRACE) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> <comp_st>\n";
#endif
		comp_st();
	}
	else if(token == TK_IF) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> if<log_exp><st>else<st>\n";
#endif
		token = scanner->getToken();
		
		attr logExp = log_exp();
		
		std::string lbl1 = iCode.getNextLabel();
		iCode.threeAddressCode(TAC_IF_FALSE, logExp, lbl1);

		st();
		
		std::string lbl2 = iCode.getNextLabel();
		iCode.threeAddressCode(TAC_GOTO, lbl2);
		
		match(TK_ELSE);
		
		iCode.threeAddressCode(lbl1);
		
		st();
		
		iCode.threeAddressCode(lbl2);
	} 
	else if(token == TK_WHILE) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> while<log_exp><st>\n";
#endif
		token = scanner->getToken();
		
		std::string lbl1 = iCode.getNextLabel();
		iCode.threeAddressCode(lbl1);
		std::string lbl2 = iCode.getNextLabel();
		
		attr cond = log_exp();
		
		iCode.threeAddressCode(TAC_IF_FALSE, cond, lbl2);
		
		st();
		
		iCode.threeAddressCode(TAC_GOTO, lbl1);
		iCode.threeAddressCode(lbl2);
	}
	else if(token == TK_RETURN) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> return(<exp>);\n";
#endif
		Token sToken = token;
		token = scanner->getToken();
		
		match(TK_LEFT_PARENTHESES);
		attr expAttr = exp(); 

		const FunctionEntry* fe = symTab.getCurrentFunction();
		if(expAttr.type != fe->getReturnType() && fe->getReturnType() != T_VOID) {
			std::stringstream ss;
			ss << "Type Mismatch, function '" << fe->getName() << "' must return ";
			if(fe->getReturnType() == T_INT) ss << "an integer";
			if(fe->getReturnType() == T_CHAR) ss << "a character";
			errorHandler(ss.str(), sToken);
		}
		
		match(TK_RIGHT_PARENTHESES);
		match(TK_SEMICOLON);
		iCode.threeAddressCode(TAC_SAVE_RET_VAL, expAttr);
		iCode.threeAddressCode(TAC_GOTO, currentReturnLabel);
	}
	else if(token == TK_SCANF) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> scanf<i_list>;\n";
#endif

		token = scanner->getToken();
		ParamList* pList = i_list();
		match(TK_SEMICOLON);
		
		iCode.threeAddressCode(TAC_READ, pList);
	}
	else if(token == TK_PRINTF) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> printf<o_list>;\n";
#endif

		token = scanner->getToken();
		ParamList* pList = o_list();
		match(TK_SEMICOLON);
		
		iCode.threeAddressCode(TAC_WRITE, pList);
	}
	else if(token == TK_IDENTIFIER) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> i<st_factor_ident>\n";
#endif
		TableEntry* te=NULL;
		if(!symTab.search(token, te)) {
			errorHandler("Undefined identifier", token);
		}
		token = scanner->getToken();
		st_factor_ident(te);
	}
	else if(token == TK_INT)  
	{
#if DEBUG_PARSER
		std::cout << "<st> --> int i <st_factor_type>\n";
#endif
		token = scanner->getToken();
		if(token!=TK_IDENTIFIER) {
			errorHandler();
		}		
		if(symTab.search(token) ) {
			std::stringstream msg;
			msg << "Duplicate variable declaration '" << token.getValue() << "'";
			errorHandler(msg.str(), token);
		} 
		
		VariableEntry* vEntry = new VariableEntry();
		vEntry->setType(T_INT);
		vEntry->setName( token.getValue() );
		//std::string varName = token.getValue();
		
		
		token = scanner->getToken();
		st_factor_type(vEntry);
		
		//symTab.insert(varName, vEntry);
	}
	else if(token == TK_CHAR) 
	{
#if DEBUG_PARSER
		std::cout << "<st> --> char i <st_factor_type>\n";
#endif
		token = scanner->getToken();
		if(token!=TK_IDENTIFIER) {
			errorHandler();
		}

		if(symTab.search(token)) {
			// aready declared in this scope
			std::stringstream msg;
			msg << "Duplicate variable declaration '" << token.getValue() << "'";
			errorHandler(msg.str(), token);
		}

		VariableEntry* vEntry = new VariableEntry();
		vEntry->setType(T_CHAR);
		vEntry->setName( token.getValue() );
		//std::string varName = token.getValue();
		
		token = scanner->getToken();
		st_factor_type(vEntry);
		
		//symTab.insert(varName, vEntry);
	}
	else 
	{
		errorHandler();
	}
	
	if(errorCondition) {
		while(token!=TK_EOF) {
			token = scanner->getToken();
			if(token==TK_RIGHT_BRACE) {
				errorCondition=false;
				break;
			}
			if(token==TK_SEMICOLON) {
				errorCondition=false;
				token = scanner->getToken();
				break;
			}
		}
	}
}
/**
 * Function representing the <prim_prime> productions
 */
attr RecursiveDescentParser::prim_prime(TableEntry* pTabEntry) {
	attr retval;
	retval.type = T_ERROR;
	
	if(errorCondition) return retval;
	if(token == TK_LEFT_BRACKET) 
	{
#if DEBUG_PARSER
		std::cout << "<prim_prime> --> [<exp>]\n";
#endif
		token = scanner->getToken();
		
		retval = exp();
		retval.attrib = VA_SIMPLE;
		
		match(TK_RIGHT_BRACKET);
	}
	else if(token == TK_LEFT_PARENTHESES)
	{
#if DEBUG_PARSER
		std::cout << "<prim_prime> --> (<o_list>)\n";
#endif
		Token sToken = token;
		token = scanner->getToken();
		ParamList* pList = o_list();
		match(TK_RIGHT_PARENTHESES);

		if(pTabEntry && pTabEntry->getEntryType()==TableEntry::FUNCTION) {
			FunctionEntry* fe = (FunctionEntry*)pTabEntry;
			if(pList) {
				matchParameters(fe, pList, sToken);
			}
			retval.type = fe->getReturnType();
			retval.addr = symTab.getNextAddress();

			iCode.threeAddressCode(TAC_PARAM, pList);
			iCode.threeAddressCode(retval, TAC_CALL, fe->getLabel(), fe->getParamCount());
		}
		else {
			std::stringstream errorMsg;
			errorMsg << "'" << pTabEntry->getName() << "' is not a function";
			errorHandler(errorMsg.str(), sToken);
		}
	}
	else if( token == TK_ASTERISK || 
			token == TK_SLASH || 
			token == TK_PERCENT || 
			token == TK_PLUS ||
			token == TK_MINUS || 
			token == TK_RIGHT_PARENTHESES || 
			token == TK_RIGHT_BRACKET || 
			token == TK_SEMICOLON || 
			token == TK_LT || 
			token == TK_GT || 
			token == TK_LTE || 
			token == TK_GTE || 
			token == TK_EQUAL || 
			token == TK_NOT_EQ ) 
	{		
#if DEBUG_PARSER
		std::cout << "<prim_prime> --> e\n";
#endif
		retval = pTabEntry->getAttr();
	}
	else {
		errorHandler();
	}
	
	return retval;
}