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