示例#1
0
bool ExprEvaluator::isHigherPriority(oper o1, oper o2){
  if(isBinary(o1) && isBinary(o2))
    if(o1 == oper::DIVIDE || o1 == oper::MULTIPLY || o2 == oper::BPLUS || o2 == oper::BMINUS)
      return true;
    else
      return false;
  if(isUnary(o1) && isBinary(o2))
    return true;
  if(isUnary(o2))
    return false;
  if(o1 == oper::SANTINEL && o2 != oper::SANTINEL)
    return false;
  if(o2 == oper::SANTINEL)
    return true;
  throw new Error(tokenizer.getExpr(), tokenizer.getTokPos(), ":Error comparing operator priorities");

}
示例#2
0
unsigned CExpression::operatorCount(sintElem* op)
{

    unsigned k = 1;
    signed j = 0;
    while(k)//проверку на достижение начала массива ставить не нужно, если мы предпологаем нотацию разрешаемой
    {//Ну пошутил. . . Если это оператор, добавить 1 если он бинарный, если не оператор (число) вычесть 1.
        k += isOperation(op[-++j].lexeme) ?  !isUnary(op[-j].lexeme) : -1;//по моему это приведёт нас ко второму операнду
    }
    return j;
}
示例#3
0
int error2(const struct command_t* command){
	/*if((isNum(command->token[0]) && isUnary(command->token[1]) && isNum(command->token[2]) && strcmp(command->token[3], "") == 0) ||
		(isNum(command->token[0]) && isBinary(command->token[1]) && strcmp(command->token[2], "") == 0))*/
    if(isNum(command->token[0]))
        if(isUnary(command->token[1]))
            if(isNum(command->token[2]))
                if(strcmp(command->token[3], "") == 0)
                    return 1;
    if(isNum(command->token[0]))
        if(isBinary(command->token[1]))
            if(strcmp(command->token[2], "") == 0)
                return 1;
	return 0;
}
示例#4
0
文件: core.cpp 项目: sp4r74n-117/mC
	std::ostream& AssignInsn::printTo(std::ostream& stream) const {
		getLhs()->printTo(stream);
		stream << " = ";
		if (isAssign()) {
			getRhs1()->printTo(stream);
		} else if (isUnary()) {
			stream << op;
			getRhs1()->printTo(stream);
		} else {
			getRhs1()->printTo(stream);
			stream << op;
			getRhs2()->printTo(stream);
		}
		return stream;
	}
示例#5
0
CExpression& CExpression::rebild(const char* CExpression)
{
    delete[] walkthroughArray;
    delete[] numArray;
    walkthroughArray = 0;
    numArray = 0;
    fine = true;
    if (!isExp(CExpression))
    {
        fine = false;
        return *this;
    }
    int len = static_cast<int>(strlen(CExpression));
    char* sourseString = new char[len * 3 + 1];
    for (int i = 0, j = 0; i < len; ++i)
        sourseString[j++] = CExpression[i];
    sourseString[len] = 0;

    sintAdaptation(sourseString);//Делает строку регистронезависимой, удаляет пробелы/'\t'/'\n', приводит скобочки к однообразию
    addCode(sourseString);//Заменяет ссылки на функции символами от -128 для удобства дальнейшего анализа
    std::cout << sourseString << std::endl;
    for (int i(0); sourseString[i]; ++i) {
        if (sourseString[i] == 't')
            sourseString[i] = 'y';
    }
    std::cout << sourseString << std::endl;
    if (expForm) {
        toExpForm(sourseString);//Преобразовывает записи типа -3.0e-2 так,
    }//чтобы они вычислялись как экспоненциальная форма числа.
    addMult(sourseString);//Добавляет * и 0 для реализации унарного минуса. Функции объеденены по историческим причинам.
    sortPoland(setArray(sourseString));/*При вызове преобразует строку в массив sintElem и высылает его для
                                       сортировки в польскую нотацию*/

    short i = 0,
          numbersCount = 0,
          opCount = 1;
    while (walkthroughArray[i].lexeme != 127)
    {
        if (walkthroughArray[i].lexeme == 'x' ||
            walkthroughArray[i].lexeme == 'y' ||
           !walkthroughArray[i].lexeme) {
            ++numbersCount;//Посчитать максимально возможное количество чисел в стеке(тоесть все числа вобще)
        } else {
            opCount += !isUnary(walkthroughArray[i].lexeme);
        }
        ++i;
    }
    //qDebug() << opCount << '<' << numbersCount;
    if (opCount > numbersCount)
    {
        delete[] walkthroughArray;
        delete[] numArray;
        walkthroughArray = 0;
        numArray = 0;
        fine = false;
        return *this;
    }

    numArray = new double[numbersCount + 1];//1 лишний элемент нужен для оптимизации алгаритма вычисления
    //std::cout << "объект создан.\n";
    return *this;
}
示例#6
0
CExpression& CExpression::optimization()
{
/*
Проводит беглый предрасчёт выражения. Не учитывает комутативность операци.
*/
    if (!fine)
    {
        return *this;
    }
    unsigned counter = 0;
    while(walkthroughArray[counter].lexeme != 127)
        ++counter;
    sintElem* temp = new sintElem[counter + 1];

    unsigned i = 0, j = 0;
    while(walkthroughArray[i].lexeme != 127)
    {
        if(!walkthroughArray[i].lexeme || walkthroughArray[i].lexeme == 'x' || walkthroughArray[i].lexeme == 'y')
            temp[j++] = walkthroughArray[i];
        else
            if(isUnary(walkthroughArray[i].lexeme))
                if( !temp[j - 1].lexeme )
                    temp[j - 1] = doIt(walkthroughArray[i].lexeme, temp[j - 1]);
                else
                    temp[j++] = walkthroughArray[i];
            else
                if( !temp[j - 1].lexeme && !temp[j - 2].lexeme ) {
                    --j;
                    temp[j - 1] = doIt(walkthroughArray[i].lexeme, temp[j - 1], temp[j]);
                } else
                    temp[j++] = walkthroughArray[i];
        ++i;
    }
    temp[j].lexeme = 127;
    /*Безсмысленные операции:
* 1, 0
+ 0
/ 1
- 0
^ 1

я вижу *, как я ищу операнды? все возможные операции находящиеся перед ним уже выполнены, т. е. может быть 1 x 3 ^ * это же 1*х^3, что должно быть x^3,
что значит что я должен собирать какой-то стек из переменных пока не найду в обоих сторонах x или не соберу все, тогда с одной из сторон должен остатся
только безсмысленный операнд, проверить обе стороны на его наличие, удалить требуемое.
*/

    i = j = 0;
    if(temp[1].lexeme != 127)
        ++(++i);//речь о бинарных операциях, нет смысла изучать что там раньше третьего знака.
    while(temp[i].lexeme != 127)
    {
        switch(temp[i].lexeme)
        {
        case '*':
            if(!temp[i - 1].lexeme && temp[i - 1].number == 1)//правый операнд мы можем проверить сразу
            {
                delElements(temp + i - 1, 2);//убираем 1 и *
                --(--i);
            }
            else if(!temp[i - 1].lexeme && temp[i - 1].number == 0)
            {
                temp[i].lexeme = 0;
                temp[i].number = 0;//Чтобы не вызывать два удаления записываем 0 вместо *
                j = operatorCount(temp + i - 1);//собираем второй операнд, удаляем его и *.
                delElements(temp + i - j - 1, j + 1);
                i -= j + 1;
            }
            else//иначе просто собираем всё что попадает в правый операнд
            {
                j = operatorCount(temp + i);
                if(!temp[i - j - 1].lexeme && temp[i - j - 1].number == 1)
                {//удаляем 1 и само умножение.
                    delElements(temp + i, 1);
                    delElements(temp + i - j - 1, 1);
                    --(--i);
                }
                else if(!temp[i - j - 1].lexeme && temp[i - j - 1].number == 0)
                {
                    delElements(temp + i - j, j + 1);//удаляем всё кроме нуля
                    i -= j + 1;
                }
            }
            break;
        case '+': case '-':
            if(!temp[i - 1].lexeme && temp[i - 1].number == 0)
            {
                delElements(temp + i - 1, 2);
                --(--i);
            }
            else
            {
                j = operatorCount(temp + i);
                if(!temp[i - j - 1].lexeme && temp[i - j - 1].number == 0)
                {
                    delElements(temp + i, 1);
                    delElements(temp + i - j - 1, 1);
                    --(--i);
                }
            }
            break;
        case '/':
            if(!temp[i - 1].lexeme && temp[i - 1].number == 1)
            {
                delElements(temp + i - 1, 2);
                --(--i);
            }
            if(!temp[i - 1].lexeme && temp[i - 1].number == 0)
            {
                temp[i].lexeme = 0;
                temp[i].number = 1;
                j = operatorCount(temp + i - 1);
                delElements(temp + i - j - 1, j + 1);
                i -= j + 1;
            }
            else
            {
                j = operatorCount(temp + i);
                if(!temp[i - j - 1].lexeme && temp[i - j - 1].number == 0)
                {
                    delElements(temp + i - j, j + 1);
                    i -= j + 1;
                }
            }
            break;
        case '^': case -121:
            if(!temp[i - 1].lexeme && temp[i - 1].number == 1)
            {
                delElements(temp + i - 1, 2);
                --(--i);
            }
            else
            {
                j = operatorCount(temp + i);
                if(!temp[i - j - 1].lexeme && ( temp[i - j - 1].number == 0 || temp[i - j - 1].number == 1 ) )
                {
                    delElements(temp + i - j, j + 1);
                    i -= j + 1;
                }
            }
            break;
        }
        ++i;
    }

    delete[] walkthroughArray;
    walkthroughArray = temp;

    /*
    std::cout << "Оптимизированная нотация:\n";
    for(i = 0; walkthroughArray[i].lexeme != 127; ++i)
        if(walkthroughArray[i].lexeme)
            std::cout << walkthroughArray[i].lexeme << std::endl;
        else
            std::cout << walkthroughArray[i].number << std::endl;
    //*/

    return *this;
}
示例#7
0
Value *OperatorExpression::evaluate(Evaluator &evaluator) const
{
    //qDebug() << "OperatorExpression:" << operatorToText(_op);

    // Get the operands.
    Value *rightValue = (_op == MEMBER || _op == AND || _op == OR? nullptr : evaluator.popResult());
    Value *leftScopePtr = nullptr;
    Value *leftValue = (_leftOperand? evaluator.popResult(&leftScopePtr) : nullptr);
    Value *result = (leftValue? leftValue : rightValue);

    QScopedPointer<Value> leftScope(leftScopePtr); // will be deleted if not needed

    DENG2_ASSERT(_op == MEMBER || _op == AND || _op == OR ||
                 (!isUnary(_op) && leftValue && rightValue) ||
                 ( isUnary(_op) && rightValue));

    try
    {
        switch (_op)
        {
        case PLUS:
            if (leftValue)
            {
                leftValue->sum(*rightValue);
            }
            else
            {
                // Unary plus is a no-op.
            }
            break;

        case PLUS_ASSIGN:
            verifyAssignable(leftValue);
            leftValue->sum(*rightValue);
            break;

        case MINUS:
            if (leftValue)
            {
                leftValue->subtract(*rightValue);
            }
            else
            {
                // Negation.
                rightValue->negate();
            }
            break;

        case MINUS_ASSIGN:
            verifyAssignable(leftValue);
            leftValue->subtract(*rightValue);
            break;

        case DIVIDE:
            leftValue->divide(*rightValue);
            break;

        case DIVIDE_ASSIGN:
            verifyAssignable(leftValue);
            leftValue->divide(*rightValue);
            break;

        case MULTIPLY:
            leftValue->multiply(*rightValue);
            break;

        case MULTIPLY_ASSIGN:
            verifyAssignable(leftValue);
            leftValue->multiply(*rightValue);
            break;

        case MODULO:
            leftValue->modulo(*rightValue);
            break;

        case MODULO_ASSIGN:
            verifyAssignable(leftValue);
            leftValue->modulo(*rightValue);
            break;

        case NOT:
            result = newBooleanValue(rightValue->isFalse());
            break;

        case RESULT_TRUE:
            result = newBooleanValue(rightValue->isTrue());
            break;

        case AND:
            if (!leftValue->isTrue())
            {
                // Early termination.
                result = newBooleanValue(false);
            }
            else
            {
                isResultTrue.push(evaluator);
                _rightOperand->push(evaluator);
                result = nullptr;
            }
            break;

        case OR:
            if (leftValue->isTrue())
            {
                // Early termination.
                result = newBooleanValue(true);
            }
            else
            {
                isResultTrue.push(evaluator);
                _rightOperand->push(evaluator);
                result = nullptr;
            }
            break;

        case EQUAL:
            result = newBooleanValue(!leftValue->compare(*rightValue));
            break;

        case NOT_EQUAL:
            result = newBooleanValue(leftValue->compare(*rightValue) != 0);
            break;

        case LESS:
            result = newBooleanValue(leftValue->compare(*rightValue) < 0);
            break;

        case GREATER:
            result = newBooleanValue(leftValue->compare(*rightValue) > 0);
            break;

        case LEQUAL:
            result = newBooleanValue(leftValue->compare(*rightValue) <= 0);
            break;

        case GEQUAL:
            result = newBooleanValue(leftValue->compare(*rightValue) >= 0);
            break;

        case IN:
            result = newBooleanValue(rightValue->contains(*leftValue));
            break;

        case CALL:
            leftValue->call(evaluator.process(), *rightValue, leftScope.take());
            // Result comes from whatever is being called.
            result = 0;
            break;

        case INDEX:
        {
            /*
            LOG_DEV_TRACE_DEBUGONLY("INDEX: types %s [ %s ] byref:%b",
                          DENG2_TYPE_NAME(*leftValue) << DENG2_TYPE_NAME(*rightValue)
                          << flags().testFlag(ByReference));
                          */

            // As a special case, records can be indexed also by reference.
            RecordValue *recValue = dynamic_cast<RecordValue *>(leftValue);
            if (flags().testFlag(ByReference) && recValue)
            {
                result = new RefValue(&recValue->dereference()[rightValue->asText()]);
            }
            else
            {
                // Index by value.
                result = leftValue->duplicateElement(*rightValue);
            }
            break;
        }

        case SLICE:
            result = performSlice(*leftValue, *rightValue);
            break;

        case MEMBER:
        {
            Record *scope = (leftValue? leftValue->memberScope() : 0);
            if (!scope)
            {
                throw ScopeError("OperatorExpression::evaluate",
                    "Left side of " + operatorToText(_op) + " does not have members [" +
                                 DENG2_TYPE_NAME(*leftValue) + "]");
            }

            // Now that we know what the scope is, push the rest of the expression
            // for evaluation (in this specific scope).
            _rightOperand->push(evaluator, leftValue);

            // Cleanup.
            //delete leftValue;
            DENG2_ASSERT(rightValue == NULL);

            // The MEMBER operator does not evaluate to any result.
            // Whatever is on the right side will be the result.
            return nullptr;
        }

        default:
            throw Error("OperatorExpression::evaluate",
                "Operator " + operatorToText(_op) + " not implemented");
        }
    }
    catch (Error const &)
    {
        delete rightValue;
        delete leftValue;
        throw;
    }

    // Delete the unnecessary values.
    if (result != rightValue) delete rightValue;
    if (result != leftValue)  delete leftValue;

    return result;
}
//Takes an expression in a string and evalutates in, boolean or arithmentic
double evaluate_expression(string& input)
{
	SyntaxChecker check; //Here's our checker object
	double rhs, lhs, result; //Some doubles we will need
	syntax_status oper; //this is for passing into the function process
	stack<double> operands; //Operand stack
	stack<syntax_status> operators; //Operator stack
	list<exprToken> expression; //Here's the list we need to pass into syntax_check

	//Here we pass in the expression to see if it passes the test
	if (check.syntax_check(input, expression) != 0) //this also populates the list of tokens
	{
		return numeric_limits<double>::quiet_NaN(); //if the input is invalid, return NaN
	}
	if (expression.size() == 0)
	{
		return numeric_limits<double>::quiet_NaN();
	}

	//Iterate through the list of tokens
	for (list<exprToken>::iterator itr = expression.begin(); itr != expression.end(); ++itr)
	{
		//If it's a number push it on the operand stack
		if (itr->isANumber)
		{
			operands.push(itr->number);
			//If there is a negative or not on top of the stack, process it now
			while (!operators.empty() && isUnary(operators.top()))
			{
				if (isNot(operators.top()))
					result = !operands.top();
				else if (isNegative(operators.top()))
					result = -operands.top();
				operands.pop();
				operators.pop();
				operands.push(result);
			}
		}
		//If it's an operator
		else if (isOperator(itr->token))
		{
			//if there are none, push it onto the stack
			if (operators.empty())
			{
				operators.push(itr->token);
			}
			//if it's precedence is lower or equal to what's on top, process the last one
			else if (precedence(itr->token) <= precedence(operators.top()))
			{
				rhs = operands.top();
				operands.pop();
				lhs = operands.top();
				operands.pop();
				oper = operators.top();
				operators.pop();
				result = process(lhs, rhs, oper);
				operands.push(result);
				operators.push(itr->token);
			}
			//if it's of higher precedence, push it on to be processed later
			else if (precedence(itr->token) > precedence(operators.top()))
			{
				operators.push(itr->token);
			}
		}
		//it's an opening parenthesis, put it in operator stack
		else if (isOpen(itr->token))
		{
			operators.push(itr->token);
		}
		//It's a closing parenthesis, process until the last opening parenthesis
		else if (isClose(itr->token))
		{
			while (!isOpen(operators.top()))
			{
				rhs = operands.top();
				operands.pop();
				lhs = operands.top();
				operands.pop();
				oper = operators.top();
				operators.pop();
				operands.push(process(lhs, rhs, oper));
			}
			operators.pop(); //dump the last opening parenthesis, we're done with it
			
			//Now if there is a ! or - on top of the operator stack we need to evaluate it
			//for the expression that was inside the parenthesis
			while (!operators.empty() && isUnary(operators.top()))
			{
				if (isNot(operators.top()))
					result = !operands.top();
				else if (isNegative(operators.top()))
					result = -operands.top();
				operands.pop();
				operators.pop();
				operands.push(result);
			}
		}
		//If we have a - or ! we need to put it in the operand stack regardless of any precedence
		else if (isUnary(itr->token))
		{
			operators.push(itr->token);
		}

	}
	//After we finish going through the list, we need to evaluate any remaining operators
	while (!operators.empty())
	{
		rhs = operands.top();
		operands.pop();
		lhs = operands.top();
		operands.pop();
		oper = operators.top();
		operators.pop();
		operands.push(process(lhs, rhs, oper));
	}
	//The top of the operand stack is the solution
	return operands.top();


}