Thursday, April 15, 2010

Translator – Assignment Operator Implementation

The reference flag for the first operand of an assignment operator or the list of operands of an assignment list operator will be checked in the add_operator() function before these operators are added to the output list. These operator remain on the hold stack until the end of statement processing since the precedence of these operators is low.

When the expected reference flag is not set, a “cannot be assigned” error will occur. The error needs to  point to the token that is not a reference, not to the assignment operator token. Therefore, the add_operator() function's argument was changed to be a reference to the token pointer so that the a different token can be returned upon an error.

For the assignment list operator, the error should point to the first token in the line that is not a reference. There could be more than one token in the list that is not a reference, but only the first one will be reported. Because the tokens are pulled from the done stack in reverse order, the last one pulled that is not a reference is the token that needs to be reported. There will be a bad token pointer that will be set for each non-reference token. Once the stack is empty, if there was a non-reference, the bad token pointer will be pointing to the first non-reference token in the statement.

Upon modifying the code to return the bad token, I realized there was a problem doing this. Previously the code that calls the add_token() function deleted the token with the error since it had not been added to the output list. The tokens in the output list are deleted by the clean_up() function called after an error occurs. Before the Translator returned a different token on an error, it deleted the token passed to the add_token() function. This is where the problem occurred; the caller would delete the error token coming back unconditionally. If it was a token in the output list, it would be deleted twice (once by the caller, once by the clean_up function). This was corrected in the caller by checking if the original token was passed back and only then deleting the token.