/* Given                            should become
 *            OperatorToken *                 OperatorToken *
 *            --------------                  --------------
 * type:      TOKEN_OPERATOR_TYPE             TOKEN_OPERATOR_TYPE
 * symbol:       '/='                          '/='
 * arity:         0                           INFIX
 * assoc:         0                           RIGHT_TO_LEFT
 * precedence:    0                           1
 *
 */
void test_extendDoubleCharacterOperator_given_divideEqual_should_give_correct_attributes(void)
{
  OperatorToken *op = (OperatorToken*)createOperatorToken("/=");
  Attributes *attr = &operatorAttributesTable[(int)*(op->symbol)];
  op =(OperatorToken *)attr->extend((Token *)op, attr);

  TEST_ASSERT_EQUAL_ATTRIBUTE_OPERATOR(INFIX, RIGHT_TO_LEFT, 1, "/=", op);
}
/* Given                            should become
 *            OperatorToken *                 OperatorToken *
 *            --------------                  --------------
 * type:      TOKEN_OPERATOR_TYPE             TOKEN_OPERATOR_TYPE
 * symbol:       '('                          '('
 * arity:         0                           PREFIX
 * assoc:         0                           LEFT_TO_RIGHT
 * precedence:    0                           13
 *
 */
void test_extendSingleCharacterOperator_given_openBracket_should_give_correct_attributes(void)
{
  OperatorToken *op = (OperatorToken*)createOperatorToken("(");
  Attributes *attr = &operatorAttributesTable[(int)*(op->symbol)];
  op =(OperatorToken *)attr->extend((Token *)op, attr);

  TEST_ASSERT_EQUAL_ATTRIBUTE_OPERATOR(PREFIX, LEFT_TO_RIGHT, 13, "(", op);
}
/* Given                            should become
 *            OperatorToken *                 OperatorToken *
 *            --------------                  --------------
 * type:      TOKEN_OPERATOR_TYPE             TOKEN_OPERATOR_TYPE
 * symbol:       '<'                          '<'
 * arity:         0                           INFIX
 * assoc:         0                           LEFT_TO_RIGHT
 * precedence:    0                           8
 *
 */
void test_extendQuadrupleCharacterOperator_given_lessThan_should_give_correct_attributes(void)
{
  OperatorToken *op = (OperatorToken*)createOperatorToken("<");
  Attributes *attr = &operatorAttributesTable[(int)*(op->symbol)];
  op =(OperatorToken *)attr->extend((Token *)op, attr);

  TEST_ASSERT_EQUAL_ATTRIBUTE_OPERATOR(INFIX, LEFT_TO_RIGHT, 8, "<", op);
}
/* Given                            should catch the error.
 *            OperatorToken *
 *            --------------
 * type:      TOKEN_OPERATOR_TYPE
 * symbol:       "~="
 * arity:         0
 * assoc:         0
 * precedence:    0
 *
 */
void test_extendSingleCharacterOperator_given_illegal_symbol_should_catch_the_error(void)
{
  OperatorToken *op = (OperatorToken*)createOperatorToken("~=");
  Attributes *attr = &operatorAttributesTable[(int)*(op->symbol)];

  ErrorObject *err;
  Try
  {
    op = (OperatorToken *)attr->extend((Token *)op, attr);
    TEST_FAIL_MESSAGE("Expected to catch Error here, but didn't.\n");
  }
  Catch(err)
  {
    TEST_ASSERT_EQUAL_STRING(("%s is an undefined operator.", ((OperatorToken *)op)->symbol), \
                               err->errorMsg);
    TEST_ASSERT_EQUAL(UNDEFINED_OPERATOR, err->errorCode);
    freeError(err);
  }
}
Example #5
0
/****************************************************************************************
 * 	This is the main function of the Pratt Parser.                                      *
 *  when an equation passed in,                                                         *
 *  the parser will check the equation from the left                                    *
 *  and link up a token tree according to the OPERATOR precedence.                      *
 *                                                                                      *
 *  example1: precedence of multiply(*) is higher than add(+),                          *
 *           so when an equation "2 + 3 * 4" entered to the parser,                     *
 *            it will link (3 * 4) and form a brunch,                                   *
 *            then parser will link the brunch to integer "2" by (+)                    *
 *            last, it will form a tree as shown below.                                 *
 *            This is an example of LINK DOWN.                                          *
 *                                                                                      *
 *                    (+)                                                               *
 *                    / \                                                               *
 *                  (2) (*)                                                             *
 *                      / \                                                             *
 *                    (3) (4)                                                           *
 *                                                                                      *                                                                                       *
 *  example2: precedence of sub(-) is smaller than multiply(*),                         *
 *           so when an equation "2 * 3 - 4" entered to the parser,                     *
 *            it will link (2 * 3) and form a brunch,                                   *
 *            then parser will link the brunch to integer "2" by (-)                    *
 *            last, it will form a tree as shown below.                                 *
 *            This is an example of LINK UP.                                            *
 *                                                                                      *
 *                    (-)                                                               *
 *                    / \                                                               *
 *                  (*) (4)                                                             *
 *                  / \                                                                 *
 *                (2) (3)                                                               *
 *                                                                                      *
 ****************************************************************************************/
Token* parser(int prevBindingPower){
 /***************************************************************************************
  *  These command allocated memory for the function to work.                           *
  ***************************************************************************************/
  Token* nextToken            = malloc(sizeof(Token));
  IntegerToken* nextIntToken  = malloc(sizeof(IntegerToken));
  OperatorToken* nextOprToken = malloc(sizeof(OperatorToken) + 2*(sizeof(Token*)));
  OperatorToken* currentToken = malloc(sizeof(OperatorToken) + 2*(sizeof(Token*)));
  Attributes* attr            = malloc(sizeof(Attributes));

 /***************************************************************************************
  *  These command assigned attributes to EXPRESSION for further usage in the function. *
  ***************************************************************************************/ 
  nextToken     = getToken();
  attr          = &tokenTypeAttributesTable[nextToken->type];
  nextIntToken  = (IntegerToken*)attr->extend(nextToken, attr);
  nextIntToken  = (IntegerToken*)nextToken->nud((Token*)nextIntToken);
  
 /***************************************************************************************
  *  These command assigned attributes to OPERATIONS for further usage in the function. *
  ***************************************************************************************/ 
  nextToken     = peepToken();
  attr          = &tokenTypeAttributesTable[nextToken->type];
  nextOprToken  = (OperatorToken*)attr->extend(nextToken, attr);
  nextOprToken  = (OperatorToken*)nextToken->led((Token*)nextOprToken);

 /***************************************************************************************
  *   When the precedence of the OPERATOR is larger than previous OPERATOR              *
  *   this command will link down to the next OPERATOR.                                 *
  ***************************************************************************************/
  if((nextOprToken->bindingPower)> prevBindingPower){
    nextOprToken = (OperatorToken*)getToken();
    nextOprToken->token[0] = (Token*)nextIntToken;
    if(nextOprToken->arity != POSTFIX)
      nextOprToken->token[1] = parser(nextOprToken->bindingPower);
  }
  else
    return (Token*)nextIntToken;
  
  
 /***************************************************************************************
  *   When the precedence of the OPERATOR is smaller than previous OPERATOR             *
  *   this command will link up to the next OPERATOR.                                   *
  ***************************************************************************************/  
  do{
    currentToken = (OperatorToken*)peepToken();
    attr         = &tokenTypeAttributesTable[currentToken->type];
    currentToken = (OperatorToken*)attr->extend((Token*)currentToken, attr);
    currentToken = (OperatorToken*)currentToken->led((Token*)currentToken);
    if(strcmp(currentToken->symbol, ")") == 0 \
    || strcmp(currentToken->symbol, "]") == 0){
      currentToken = (OperatorToken*)getToken();
      if(prevBindingPower == 1)
        return (Token*)nextOprToken;
    }
    if(currentToken->bindingPower > prevBindingPower){
      currentToken = (OperatorToken*)getToken();
      currentToken->token[0] = (Token*)nextOprToken;
      if(currentToken->arity != POSTFIX)
        currentToken->token[1] = parser(currentToken->bindingPower);
      nextOprToken = currentToken;
    }
  }while(strcmp(currentToken->symbol, "$") != 0 \
      && prevBindingPower == 0);
  return (Token*)nextOprToken;
}