void BinaryOperatorExpressionSyntax::stringify(stringstream* stream, int tabulation)
        {
            tabulate(stream, tabulation);

            if (_left->getPrecedence() > getPrecedence()) *stream << "(";
            _left->stringify(stream, 0);
            if (_left->getPrecedence() > getPrecedence()) *stream << ")";

            *stream << " " << getOperatorSymbol() << " ";

            if (_right->getPrecedence() > getPrecedence()) *stream << "(";
            _right->stringify(stream, 0);
            if (_right->getPrecedence() > getPrecedence()) *stream << ")";
        }
        void BinaryOperatorExpressionSyntax::resolveTypes(types::NameResolutionContextStack *ctx)
        {
            _left->resolveTypes(ctx);
            _right->resolveTypes(ctx);

            auto bin_op = getBinaryOperator();
            if (bin_op == nullptr) return;
            _overload = bin_op->findOverload(_left->getExpressionType(), _right->getExpressionType());

            if (_overload == nullptr)
            {
                this->reportError("Cannot find binary operator overload for operator %s", getOperatorSymbol());
                return;
            }

            _left->suggestExpressionType(_overload->getParameterInfo(0)->getType());
            _right->suggestExpressionType(_overload->getParameterInfo(1)->getType());
            _left->resolveTypes(ctx);
            _right->resolveTypes(ctx);

            if (!_left->getExpressionType()->isSameAs(_overload->getParameterInfo(0)->getType()))
            {
                _castLeft = op::Operator::implicitCast()->findOverload(_left->getExpressionType(), _overload->getParameterInfo(0)->getType());
            }
            if (!_right->getExpressionType()->isSameAs(_overload->getParameterInfo(1)->getType()))
            {
                _castRight = op::Operator::implicitCast()->findOverload(_right->getExpressionType(), _overload->getParameterInfo(1)->getType());
            }
        }
	//*************************************************************************
	// Method:		getUserInput
	// Description: Displays the values from the listviewitem supplied and returns
	//				the user edited values in a listviewitem
	//
	// Parameters:
	//	lvi	-	the current listviewitem values, cannot be NULL
	//	compareType - compare type for the parameter
	//
	// Return Value: (ListViewItem) used edited values for param match
	//*************************************************************************
	ListViewItem * TestPatternBuilderDialog::getUserInput (ListViewItem * lvi, int compareType)
	{
		if (lvi == NULL)
			return NULL;

		

		//Set the dialog title
		this->Text = String::Concat (S"Specify match condition for param ", lvi->SubItems->Item[1]->Text);

		//Set the param name textbox value
		this->tbParamName->Text = lvi->SubItems->Item[1]->Text;

		//Set the appropriate values for MatchType combobox
		cbMatchType->Items->Clear();
		switch (compareType)
		{
			case BooleanType:
				cbMatchType->Items->Add(new String(EQUAL_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(NOT_EQUAL_OPERATOR_TEXT));

				tbMatchValue->Items->Add(new String(IN_PARAM_MATCH_TRUE_STRING));
				tbMatchValue->Items->Add(new String(IN_PARAM_MATCH_FALSE_STRING));
				break;
			case IntegerType:
			case UnsignedLongType:
			case RealType:
			case Integer64Type:
				cbMatchType->Items->Add(new String(EQUAL_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(NOT_EQUAL_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(LESS_THAN_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(GREATER_THAN_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(LESS_EQUAL_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(GREATER_EQUAL_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(BINARY_CONTAINS_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(BINARY_NOT_CONTAINS_OPERATOR_TEXT));
				break;
			case PointerType:
			case PointerPointerType:
				cbMatchType->Items->Add(new String(EQUAL_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(NOT_EQUAL_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(LESS_THAN_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(GREATER_THAN_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(LESS_EQUAL_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(GREATER_EQUAL_OPERATOR_TEXT));
				if (!isDotNetFunction)
				{
					cbMatchType->Items->Add(new String(EQUAL_RESOURCE_OPERATOR_TEXT));
					cbMatchType->Items->Add(new String(NOT_EQUAL_RESOURCE_OPERATOR_TEXT));
					cbMatchType->Items->Add(new String(CONTAINS_RESOURCE_OPERATOR_TEXT));
					cbMatchType->Items->Add(new String(NOT_CONTAINS_RESOURCE_OPERATOR_TEXT));
					cbMatchType->Items->Add(new String(STARTS_WITH_RESOURCE_OPERATOR_TEXT));
				}

				tbMatchValue->Items->Add(new String(IN_PARAM_MATCH_NULL_STRING));
				break;
			case StringType:
			case WideStringType:
			case OutStringType:
			case OutWideStringType:
			case IIDRefType:
				cbMatchType->Items->Add(new String(EQUAL_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(NOT_EQUAL_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(LESS_THAN_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(GREATER_THAN_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(LESS_EQUAL_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(GREATER_EQUAL_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(STARTS_WITH_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(ENDS_WITH_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(SUBSTRING_OPERATOR_TEXT));
				cbMatchType->Items->Add(new String(NOT_CONTAINS_OPERATOR_TEXT));
				if (!isDotNetFunction)
				{
					cbMatchType->Items->Add(new String(EQUAL_RESOURCE_OPERATOR_TEXT));
					cbMatchType->Items->Add(new String(NOT_EQUAL_RESOURCE_OPERATOR_TEXT));
					cbMatchType->Items->Add(new String(CONTAINS_RESOURCE_OPERATOR_TEXT));
					cbMatchType->Items->Add(new String(NOT_CONTAINS_RESOURCE_OPERATOR_TEXT));
					cbMatchType->Items->Add(new String(STARTS_WITH_RESOURCE_OPERATOR_TEXT));
				}
				break;
			default:
				break;
		}

		//Select the appropriate value in the combobox
		cbMatchType->Text = getOperatorText (lvi->SubItems->Item[2]->Text);

		//Set the value of the MatchValue textbox
		this->tbMatchValue->Text = lvi->SubItems->Item[3]->Text;

		//Display the dialog and return the appropriaste result
		if (this->ShowDialog() == DialogResult::OK)
		{
			ListViewItem * newLvi = new ListViewItem(S"");
			newLvi->SubItems->Add (this->tbParamName->Text);
			newLvi->SubItems->Add (getOperatorSymbol (this->cbMatchType->Text));
			newLvi->SubItems->Add (this->tbMatchValue->Text);

			return newLvi;
		}
		else
			return NULL;

	}