/**
 * Function representing the <st_prime> productions
 */
void RecursiveDescentParser::st_prime(Type type) {
	if(errorCondition) return;
	if(token == TK_COMMA) 
	{
		token = scanner->getToken();
#if DEBUG_PARSER
		std::cout << "<st_prime> --> ,i<arr_spec><st_prime>\n";
#endif
		if(token!=TK_IDENTIFIER){
			// error
		}
		
		if(symTab.search(token)) {
			std::stringstream msg;
			msg << "Duplicate variable declaration '" << token.getValue() << "'";
			errorHandler(msg.str(), token);
		}
		
		VariableEntry* entry = new VariableEntry();
		entry->setType(type);
		symTab.insert(token, entry);
		
		token = scanner->getToken();
		VariableAttribute va = arr_spec();
		entry->setAttribute(va);
		st_prime(type);
	} 
	else if(token == TK_SEMICOLON) 
	{
#if DEBUG_PARSER
		std::cout << "<st_prime> --> e\n";
#endif
	}
	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;
			}
		}
	}
}