// New string operand (string literal
void newStringOperand(char* value) {
    
    Operand operand;
    operand.type = opdtString;
    
    if (strcmp(value, "\"\\n\"") == 0) operand.value = -1;
    else operand.value = generateStringLiteral(value);
    
    pushOperandToStack(&operandStack, operand);
    
}
frac* expressionSolver::solveExpression()
{
	std::stack<frac*>	postFixExprStack;
	std::stringstream exprstream(postFixedExpression);
	std::string currToken;
	while(exprstream>>currToken)
	{
		if(isOperator(currToken))
			useOperator(currToken, postFixExprStack);
		else
			pushOperandToStack(currToken, postFixExprStack);
	}
	frac *result = postFixExprStack.top()->clone();
	postFixExprStack.pop();
	return result;
}
// Push an operand to the stack
void newOperand(OperandType type, int value) {
    
    Operand operand;
    operand.type = type;
    
    if (type == opdtVariable) {
        SymbolTableRow* symbol = getSymbol(value, symbolTableStack->integer);
        operand.value = symbol->address;
        operand.operandSymbolType = symbol->type;
        operandSymbolIndex = value;
        operandSymbolTable = symbolTableStack->integer;
        operandDimensionAccessCount = 0;
    } else {
        operand.value = value;
        operand.operandSymbolType = -1;
    }
    
    pushOperandToStack(&operandStack, operand);
    
}
void evaluateNextOperation() {
    
    Operator operator = popOperatorFromStack(&operatorStack, &operatorFunctionIndex);
    
    if (operator != oprOpenParenthesis && operator != oprComma) {
        
        // Function call
        if (operator == oprFunctionCall) {
            
            SymbolTableRow* functionSymbol = getSymbol(operatorFunctionIndex, 0);
            SymbolTableId functionSymbolTable = functionSymbol->symbolTable;
            
            int parameterCount = functionSymbol->dimensionSizes->Integer;
            
            OperandStack* parameters = NULL;
            
            // Reverse parameters order
            for (int i = 0; i < parameterCount; i++) {
                pushOperandToStack(&parameters, popOperandFromStack(&operandStack));
            }
            
            int parameterId = 0;
            SymbolTableRow* parameterSymbol = getSymbol(parameterId, functionSymbolTable);
            
            while (parameterSymbol->category == scParameter) {
                Operand parameter = popOperandFromStack(&parameters);
                generatePassingParameter(parameter, parameterSymbol->address, parameterSymbol->totalSize);
                parameterId++;
                parameterSymbol = getSymbol(parameterId, functionSymbolTable);
            }
            
            temporaryVariablesCounter++;
            
            generateFunctionCall(functionSymbol->address, cumulativeAddress + temporaryVariablesCounter, functionSymbol->totalSize);
            
            generateNewTemporaryVariable();
            
            Operand result = { opdtTemporary, functionSymbol->type, cumulativeAddress + temporaryVariablesCounter };
            pushOperandToStack(&operandStack, result);

        }
        // Scan
        else if (operator == oprScan) {
        
            OperandStack* inputVariables = NULL;
        
            while (operandStack != NULL) pushOperandToStack(&inputVariables, popOperandFromStack(&operandStack));
            
            while (inputVariables != NULL) {
                Operand input = popOperandFromStack(&inputVariables);
                if (input.operandSymbolType == stString) {
                    generateStringScan(input.value);
                } else if (input.operandSymbolType == stInt) {
                    generateIntScan(input.value);
                } else if (input.operandSymbolType == stBoolean) {
                    generateBooleanScan(input.value);
                }
                else {
                    // Error: invalid type
                }
            }
            
        }
        // Print
        else if (operator == oprPrint) {
            
            OperandStack* outputOperands = NULL;
            
            while (operandStack != NULL) pushOperandToStack(&outputOperands, popOperandFromStack(&operandStack));
            
            while (outputOperands != NULL) {
                Operand output = popOperandFromStack(&outputOperands);
                if (output.type == opdtString || output.operandSymbolType == stString) generateStringPrint(output);
                else if (output.type == opdtInteger || output.operandSymbolType == stInt) generateIntPrint(output);
                else if (output.type == opdtBoolean || output.operandSymbolType == stBoolean) generateBooleanPrint(output);
            }
            
        }
        // Operations
        else {
            
            Operand leftOperand;
            Operand rightOperand = popOperandFromStack(&operandStack);
            
            // Attribution
            if (operator == oprEqualSign) {
                
                // Pop left operand
                leftOperand = popOperandFromStack(&operandStack);
                
                if (leftOperand.type == opdtVariable) generateAttribution(leftOperand, rightOperand);
                else {
                    // Error: invalid operation
                }
                
            } else {
                
                int resultType = -1;
                
                // Binary operators
                if (operator > oprMinus) {
                    
                    // Pop left operand
                    leftOperand = popOperandFromStack(&operandStack);
                    
                    // If both operands are not temporary variables, create a new temporary variable
                    temporaryVariablesCounter++;
                    if (leftOperand.type != opdtTemporary && rightOperand.type != opdtTemporary) generateNewTemporaryVariable();
                    else temporaryVariablesCounter --;
                    
                    // Generate code
                    switch (operator) {
                            
                        case oprAdd:
                        case oprSubtract:
                        case oprMultiply:
                        case oprDivide:
                            generateArithmeticOperation(operator, leftOperand, rightOperand,  cumulativeAddress + temporaryVariablesCounter);
                            resultType = stInt;
                            break;
                            
                            
                        case oprSmallerThan:
                        case oprSmallerOrEqualThan:
                        case oprBiggerThan:
                        case oprBiggerOrEqualThan:
                            generateRelationalComparison(operator, leftOperand, rightOperand, cumulativeAddress + temporaryVariablesCounter);
                            resultType = stBoolean;
                            break;
                            
                        case oprLogicAnd:
                        case oprLogicOr:
                            generateLogicalOperation(operator, leftOperand, rightOperand, cumulativeAddress + temporaryVariablesCounter);
                            resultType = stBoolean;
                            break;
                            
                        default:
                            // Error: invalid operator
                            break;
                            
                    }
                    
                }
                // Unary operators
                else {
                    
                    // If operand is not a temporary variable, create a new temporary variable.
                    temporaryVariablesCounter++;
                    if (rightOperand.type != opdtTemporary) generateNewTemporaryVariable();
                    else temporaryVariablesCounter --;
                    
                    // Generate code
                    switch (operator) {
                            
                        default:
                            // Error: invalid operator
                            break;
                            
                    }
                    
                }
                
                // Push result operand to stack
                Operand result = { opdtTemporary, resultType, cumulativeAddress + temporaryVariablesCounter };
                pushOperandToStack(&operandStack, result);
                
            }
            
        }
        
    }

}