bool ConstraintsInterpreter::ConvertToExclusions()

in cli/gcdexcl.cpp [486:651]


bool ConstraintsInterpreter::ConvertToExclusions( OUT CGcdExclusions& gcdExclusions )
{
    // translate parameters to a form understandable by the core engine
    for( auto & param : _modelData.Parameters )
    {
        CParameter parameter;
        parameter.Name        = param.Name;
        parameter.Type        = getParameterDataType(param );
        parameter.ResultParam = param.IsResultParameter;

        _constrModel.Parameters.push_back( parameter );
    }

    // handle the constraints, in multiple phases
    // 1. tokenize the constraints
    try
    {
        ConstraintsTokenizer tokenizer( _constrModel, _modelData.ConstraintPredicates );
        try
        {
            tokenizer.Tokenize();
        }
        catch( CSyntaxError e )
        {
            wstring text = getConstraintTextForContext( _modelData.ConstraintPredicates, e.ErrAtPosition );
            const wchar_t* failureContext = text.c_str();

            // print message
            switch( (SyntaxErrorType) e.Type )
            {
            case SyntaxErrorType::UnexpectedEndOfString:
                PrintMessage( InputDataError, L"Constraint ended unexpectedly:", failureContext );
                break;
            case SyntaxErrorType::UnknownSpecialChar:
                PrintMessage( InputDataError, L"Non-special character was escaped:", failureContext );
                break;
            case SyntaxErrorType::UnknownRelation:
                PrintMessage( InputDataError, L"Missing or incorrect relation:", failureContext );
                break;
            case SyntaxErrorType::NoParameterNameOpen:
                PrintMessage( InputDataError, L"Missing opening bracket or misplaced keyword:", failureContext );
                break;
            case SyntaxErrorType::NoParameterNameClose:
                PrintMessage( InputDataError, L"Missing closing bracket after parameter name:", failureContext );
                break;
            case SyntaxErrorType::NoValueSetOpen:
                PrintMessage( InputDataError, L"Set of values should start with '{':", failureContext );
                break;
            case SyntaxErrorType::NoValueSetClose:
                PrintMessage( InputDataError, L"Set of values should end with '}':", failureContext );
                break;
            case SyntaxErrorType::NotNumericValue:
                PrintMessage( InputDataError, L"Incorrect numeric value:", failureContext );
                break;
            case SyntaxErrorType::NoKeywordThen:
                PrintMessage( InputDataError, L"Misplaced THEN keyword or missing logical operator:", failureContext );
                break;
            case SyntaxErrorType::NotAConstraint:
                PrintMessage( InputDataError, L"Constraint definition is incorrect:", failureContext );
                break;
            case SyntaxErrorType::NoConstraintEnd:
                PrintMessage( InputDataError, L"Constraint terminated incorectly:", failureContext );
                break;
            case SyntaxErrorType::NoEndParenthesis:
                PrintMessage( InputDataError, L"Missing closing parenthesis:", failureContext );
                break;
            case SyntaxErrorType::FunctionNoParenthesisOpen:
                PrintMessage( InputDataError, L"Missing opening parenthesis in function:", failureContext );
                break;
            case SyntaxErrorType::FunctionNoParenthesisClose:
                PrintMessage( InputDataError, L"Missing closing parenthesis in function:", failureContext );
                break;
            default:
                assert( false );
                break;
            }

            return( false );
        }

        // 2. parse the constraints
        ConstraintsParser parser( tokenizer.GetTokenLists() );

        try
        {
            parser.GenerateSyntaxTrees();

            for( auto & warning : parser.GetWarnings() )
            {
                switch( warning.Type )
                {
                case ValidationWarnType::UnknownParameter:
                    {
                    wstring constraintText = _modelData.GetConstraintText( warning.ErrInConstraint );
                    const wchar_t* failureContext = constraintText.c_str();
                    PrintMessage( ConstraintsWarning, L"Constraint", failureContext, L"contains unknown parameter. Skipping..." );
                    break;
                    }
                default:
                    {
                    assert( false );
                    break;
                    }
                }
            }
        }
        catch( CErrValidation e )
        {
            wstring constraintText = _modelData.GetConstraintText( e.ErrInConstraint );
            const wchar_t* failureContext = constraintText.c_str();
            
            switch( e.Type )
            {
            case ValidationErrType::ParameterComparedToValueOfDifferentType:
                PrintMessage( InputDataError, L"Parameter/value type mismatch:", failureContext );
                break;
            case ValidationErrType::ParametersOfDifferentTypesCompared:
                PrintMessage( InputDataError, L"Parameters are of different types:", failureContext );
                break;
            case ValidationErrType::ParameterComparedToItself:
                PrintMessage( InputDataError, L"Parameter cannot be compared to itself:", failureContext );
                break;
            case ValidationErrType::ParameterValueSetTypeMismatch:
                PrintMessage( InputDataError, L"Parameter/value type mismatch:", failureContext );
                break;
            case ValidationErrType::LIKECannotBeUsedForNumericParameters:
                PrintMessage( InputDataError, L"LIKE operator cannot be used for numeric parameters:", failureContext );
                break;
            case ValidationErrType::LIKECannotBeUsedWithNumericValues:
                PrintMessage( InputDataError, L"LIKE operator cannot be used for numeric values:", failureContext );
                break;
            default:
                assert( false );
                break;
            }

            return( false );
        }

        // 3. interpret and translate into a form understanable by the core engine
        const CConstraints& constraints = parser.GetConstraints();

        if ( _modelData.Verbose )
        {
            PrintLogHeader( L"Constraints: Output from syntax parsing" );
            for( auto & c : constraints )
            {
                c.Print();
            }
        }

        for( auto & c : constraints )
        {
            interpretConstraint( c, gcdExclusions );
        }

        // last-minute cleanup
        removeContradictingExclusions( gcdExclusions );
    }
    catch( std::bad_alloc e )
    { 
        throw new GenerationError( __FILE__, __LINE__, ErrorType::OutOfMemory );
    }

    return( true );
}