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 );
}