Skip to content

Commit

Permalink
token: changed conversion code handling
Browse files Browse the repository at this point in the history
changed convert constant to throw error for nonconvertible doubles
changed convert code to throw errors for nonconvertible tokens
added is data type compatible function for checking references
modified table find code for changes to convert constant and code
modified translator routines for changes to convert constant and code
modified translator get operand to use is data type compatible
removed table set token code with data type argument
- only caller left was token constructor for string constants
  • Loading branch information
thunder422 committed Jan 6, 2015
1 parent 68593c2 commit c2f2420
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 95 deletions.
21 changes: 8 additions & 13 deletions table.cpp
Expand Up @@ -1730,9 +1730,16 @@ Code Table::findCode(TokenPtr &token, TokenPtr &operandToken, int operandIndex)
// check if constant should be converted to needed data type
if (operandIndex == operandCount(token) - 1 // last operand?
&& !hasFlag(token, UseConstAsIs_Flag))
try
{
operandToken->convertConstant(expectedDataType);
}
catch (Status)
{
// don't throw unconvertible doubles to integer errors here
// doubles as is may be acceptable depending on operator
// (will catch if double can't be converted if integer needed below)
}

// see if any alternate code's data types match
if (setTokenCode(token.get(), token->code(), operandToken->dataType(),
Expand All @@ -1742,14 +1749,7 @@ Code Table::findCode(TokenPtr &token, TokenPtr &operandToken, int operandIndex)
}

// get a conversion code if no alternate code was found
Code cvtCode {operandToken->convertCode(expectedDataType)};
if (operandToken->isType(Type::Constant)
&& expectedDataType == DataType::Integer
&& operandToken->isDataType(DataType::Double))
{
operandToken->setDataType(DataType{}); // to report invalid integer
}
return cvtCode; // convert code or invalid
return operandToken->convertCode(expectedDataType);
}


Expand Down Expand Up @@ -1779,11 +1779,6 @@ void Table::setTokenCode(Token *token, Code code, DataType dataType)
token->setDataType(dataType);
}

void Table::setTokenCode(Token *token, Code baseCode)
{
setTokenCode(token, baseCode, token->dataType());
}


// function to set the code for of token for the specified operand
// appropriate for the data type specified
Expand Down
1 change: 0 additions & 1 deletion table.h
Expand Up @@ -162,7 +162,6 @@ class Table
bool setTokenCode(Token *token, Code code, DataType dataType,
int operandIndex);
void setTokenCode(Token *token, Code code, DataType dataType);
void setTokenCode(Token *token, Code baseCode);
std::string name(const TokenPtr &token) const;

// TABLE SPECIFIC FUNCTIONS
Expand Down
102 changes: 50 additions & 52 deletions token.cpp
Expand Up @@ -91,10 +91,10 @@ Token::Token(DataType dataType, int column, int length,

// constructor for string constants
Token::Token(int column, int length, const std::string string) :
m_column{column}, m_length{length}, m_dataType{DataType::String},
m_string{string}, m_code{Invalid_Code}, m_reference{}, m_subCode{}
m_column{column}, m_length{length}, m_string{string}, m_reference{},
m_subCode{}
{
Table::instance().setTokenCode(this, Const_Code);
Table::instance().setTokenCode(this, Const_Code, DataType::String);
}


Expand Down Expand Up @@ -130,8 +130,9 @@ std::string Token::stringWithDataType() const


// function to change constant token to desired data type
// - resets integer constant sub-code for numeric desired data types
// - resets integer constant sub-code on double constants
// - does nothing if constant is not changed
// - throws error if double cannot be converted to integer
bool Token::convertConstant(DataType dataType)
{
if (!isType(Type::Constant))
Expand All @@ -149,77 +150,74 @@ bool Token::convertConstant(DataType dataType)
{
return false;
}
// fall to below and change constant type to double
}
else if (dataType == DataType::Integer && m_dataType == DataType::Double
&& hasSubCode(IntConst_SubCode))
else if (dataType == DataType::Integer)
{
removeSubCode(IntConst_SubCode);
if (m_dataType == DataType::Double)
{
if (!hasSubCode(IntConst_SubCode))
{
throw Status::ExpIntConst;
}
removeSubCode(IntConst_SubCode);
// fall to below and change constant type to integer
}
else
{
return m_dataType == DataType::Integer;
}
}
else
{
return false;
return false; // can't convert to number or any
}
m_dataType = dataType;
Table::instance().setTokenCode(this, Const_Code);
Table::instance().setTokenCode(this, Const_Code, dataType);
return true;
}


// function to get convert code needed to convert token to data type
// - changes number constant tokens to desired data type
// - returns conversion code if needed
// - returns null code if no conversion needed
// - returns invalid code if cannot be converted
// - if cannot be converted then sets data type for error reporting
// - throws error status if cannot be converted
Code Token::convertCode(DataType dataType)
{
if (convertConstant(dataType))
{
return Null_Code;
}
switch (dataType)
if (!convertConstant(dataType) && m_dataType != dataType)
{
case DataType::Double:
if (m_dataType == DataType::Integer)
switch (dataType)
{
case DataType::Double:
if (m_dataType != DataType::Integer)
{
throw Status::ExpNumExpr;
}
return CvtDbl_Code;
}
else if (m_dataType == DataType::Double)
{
return Null_Code;
}
break;

case DataType::Integer:
if (m_dataType == DataType::Double)
{
return isType(Type::Constant) ? Invalid_Code : CvtInt_Code;
}
else if (m_dataType == DataType::Integer)
{
return Null_Code;
}
break;
case DataType::Integer:
if (m_dataType != DataType::Double)
{
throw Status::ExpNumExpr;
}
return CvtInt_Code;

case DataType::String:
if (m_dataType == DataType::String)
{
return Null_Code;
}
break;
case DataType::String:
throw Status::ExpStrExpr;

case DataType::Number:
if (m_dataType != DataType::String)
{
return Null_Code;
}
break;
case DataType::Number:
if (m_dataType == DataType::String)
{
throw Status::ExpNumExpr;
}
break;

case DataType::None:
case DataType::Any:
return Null_Code;
case DataType::None:
case DataType::Any:
break;
}
}
m_dataType = dataType;
return Invalid_Code;
return Null_Code;
}


Expand Down
7 changes: 7 additions & 0 deletions token.h
Expand Up @@ -110,6 +110,13 @@ class Token
{
return dataType == m_dataType;
}
bool isDataTypeCompatible(DataType dataType)
{
// check if token data type is compatible with desired data type
return dataType == m_dataType
|| (dataType == DataType::Number && m_dataType != DataType::String)
|| dataType == DataType::Any || dataType == DataType::None;
}

// string access function
std::string string(void) const
Expand Down
42 changes: 13 additions & 29 deletions translator.cpp
Expand Up @@ -297,26 +297,19 @@ void Translator::getExpression(DataType dataType, int level)
if (!processOperator())
{
if (level == 0)
try
{
// add convert code if needed or report error
TokenPtr doneToken {m_doneStack.top().rpnItem->token()};
Code cvtCode {doneToken->convertCode(dataType)};
if (cvtCode == Invalid_Code)
{
if (doneToken->isType(Type::Constant)
&& dataType == DataType::Integer
&& doneToken->isDataType(DataType::Double))
{
// constant could not be converted
throw doneStackTopTokenError(Status::ExpIntConst);
}
throw doneStackTopTokenError(expectedErrorStatus(dataType));
}
else if (cvtCode != Null_Code)
if (Code cvtCode = doneToken->convertCode(dataType))
{
m_output.append(std::make_shared<Token>(cvtCode));
}
}
catch (Status status)
{
throw doneStackTopTokenError(status);
}
break;
}

Expand Down Expand Up @@ -423,8 +416,7 @@ bool Translator::getOperand(DataType dataType, Reference reference)
}
// for reference, check data type
if (reference != Reference::None
&& m_doneStack.top().rpnItem->token()->convertCode(dataType)
!= Null_Code)
&& !m_doneStack.top().rpnItem->token()->isDataTypeCompatible(dataType))
{
throw doneStackTopTokenError(expectedErrorStatus(dataType, reference));
}
Expand Down Expand Up @@ -845,32 +837,24 @@ void Translator::processDoneStackTop(TokenPtr &token, int operandIndex,
{
*last = localLast;
}
m_doneStack.pop(); // remove from done stack

// see if main code's data type matches
Code cvtCode {m_table.findCode(token, topToken, operandIndex)};

if (cvtCode != Invalid_Code)
try
{
m_doneStack.pop(); // remove from done stack

// is there an actual conversion code to insert?
if (cvtCode != Null_Code)
if (Code cvtCode = m_table.findCode(token, topToken, operandIndex))
{
// INSERT CONVERSION CODE
// create convert token with convert code
// append token to end of output list (after operand)
m_output.append(std::make_shared<Token>(cvtCode));
}
}
else // no match found, throw error
catch (Status status)
{
// use main code's expected data type for operand
// (if no data type, then double constant can't be converted to integer)
// report entire expression from first token through last
throw TokenError {topToken->isDataType(DataType{})
? Status::ExpIntConst : expectedErrorStatus(topToken->dataType()),
localFirst->column(), localLast->column() + localLast->length()
- localFirst->column()};
throw TokenError {status, localFirst->column(), localLast->column()
+ localLast->length() - localFirst->column()};
}
}

Expand Down

0 comments on commit c2f2420

Please sign in to comment.