Esempio n. 1
0
/*
<expression> ::= <unary operator-name> <expression>
  ::= <binary operator-name> <expression> <expression>
  ::= <trinary operator-name> <expression> <expression> <expression>
  ::= st <type>
  ::= <template-param>
  ::= sr <type> <unqualified-name>                   # dependent name
  ::= sr <type> <unqualified-name> <template-args>   # dependent template-id
  ::= <expr-primary>
*/
static int parseExpression(LargeStaticString &src, LargeStaticString &dest, demangle_t &data)
{
  START("Expression");
  
  if (src[0] == 'T')
  {
    if (parseTemplateParam(src, dest, data) == FAIL)
      END_FAIL("Expression");
    else
      END_SUCCESS("Expression");
  }
  else if (src[0] == 'L')
  {
    if (parseExprPrimary(src, dest, data) == FAIL)
      END_FAIL("Expression");
    else
      END_SUCCESS("Expression");
  }
  
  LargeStaticString op = src.left(2);
  src.stripFirst(2);
  
#define UNARY_OP(prefix) { \
  dest += prefix; \
  if (parseExpression(src, dest, data) == FAIL) \
  END_FAIL("Expression"); \
  else \
  END_SUCCESS("Expression"); \
}
#define BINARY_OP(infix) { \
  dest += "("; \
  if (parseExpression(src, dest, data) == FAIL) \
  END_FAIL("Expression"); \
  dest += infix; \
  if (parseExpression(src, dest, data) == FAIL) \
  END_FAIL("Expression"); \
  else \
  { \
  dest += ")"; \
  END_SUCCESS("Expression"); \
} \
}
  if (op == "ps") UNARY_OP("+")
        else if (op == "ng") UNARY_OP("-")
        else if (op == "ad") UNARY_OP("&")
        else if (op == "de") UNARY_OP("*")
        else if (op == "co") UNARY_OP("~")
        else if (op == "nt") UNARY_OP("!")
        else if (op == "pl") BINARY_OP("+")
        else if (op == "mi") BINARY_OP("-")
        else if (op == "ml") BINARY_OP("*")
        else if (op == "dv") BINARY_OP("/")
        else if (op == "rm") BINARY_OP("%")
        else if (op == "an") BINARY_OP("&")
        else if (op == "or") BINARY_OP("|")
        else if (op == "eo") BINARY_OP("^")
        else if (op == "ls") BINARY_OP("<<")
        else if (op == "rs") BINARY_OP(">>")
        else if (op == "st")
  {
    dest += "sizeof (";
    if (parseType(src, dest, data) == FAIL)
      END_FAIL("Expression");
    dest += ")";
    END_SUCCESS("Expression");
  }
  
             
  END_FAIL("Expression");
}
Esempio n. 2
0
/* return 0 on failure, 1 on success */
static int reduce_op() {
  long op_token = stack[sp - 1].value;
  assert(sp > 0);
  assert(stack[sp - 1].op == EXPR_OP);
  /* do some basic checking first: */
  if (stack[sp].op != EXPR_VALUE) {
    errmsg = "Right-hand side is not value";
    return 0;
  }
  if (UNARY_OP(op_token)) {
    if (stack[sp].svalue) {
      errmsg = "Syntax error: attempt to apply unary operator to string";
      return 0;
    }
  } else {
    /* binary operator: */
    if (sp == 1) {
      /* top of stack: don't attempt to use sp-2! */
      errmsg = "Missing left-hand side for binary operator";
      return 0;
    }
    if (stack[sp].op != EXPR_VALUE) {
      errmsg = "Left-hand side of binary operator is not a value";
      return 0;
    }
    if ((!stack[sp - 2].svalue) != (!stack[sp].svalue)) {
      errmsg = "Can't mix strings and integers in expression";
      return 0;
    }
  }
  if (stack[sp].svalue) {
    /* A binary string expression */
    switch (stack[sp - 1].value) {
    case SWIG_TOKEN_EQUALTO:
      stack[sp - 2].value = (Strcmp(stack[sp - 2].svalue, stack[sp].svalue) == 0);
      Delete(stack[sp - 2].svalue);
      Delete(stack[sp].svalue);
      sp -= 2;
      break;
    case SWIG_TOKEN_NOTEQUAL:
      stack[sp - 2].value = (Strcmp(stack[sp - 2].svalue, stack[sp].svalue) != 0);
      Delete(stack[sp - 2].svalue);
      Delete(stack[sp].svalue);
      sp -= 2;
      break;
    default:
      errmsg = "Syntax error: bad binary operator for strings";
      return 0;
      break;
    }
  } else {
    switch (op_token) {
    case SWIG_TOKEN_STAR:
      stack[sp - 2].value = stack[sp - 2].value * stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_EQUALTO:
      stack[sp - 2].value = stack[sp - 2].value == stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_NOTEQUAL:
      stack[sp - 2].value = stack[sp - 2].value != stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_PLUS:
      stack[sp - 2].value = stack[sp - 2].value + stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_MINUS:
      stack[sp - 2].value = stack[sp - 2].value - stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_AND:
      stack[sp - 2].value = stack[sp - 2].value & stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_LAND:
      stack[sp - 2].value = stack[sp - 2].value && stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_OR:
      stack[sp - 2].value = stack[sp - 2].value | stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_LOR:
      stack[sp - 2].value = stack[sp - 2].value || stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_XOR:
      stack[sp - 2].value = stack[sp - 2].value ^ stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_LESSTHAN:
      stack[sp - 2].value = stack[sp - 2].value < stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_GREATERTHAN:
      stack[sp - 2].value = stack[sp - 2].value > stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_LTEQUAL:
      stack[sp - 2].value = stack[sp - 2].value <= stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_GTEQUAL:
      stack[sp - 2].value = stack[sp - 2].value >= stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_NOT:
      stack[sp - 1].value = ~stack[sp].value;
      sp--;
      break;
    case SWIG_TOKEN_LNOT:
      stack[sp - 1].value = !stack[sp].value;
      sp--;
      break;
    case EXPR_UMINUS:
      stack[sp - 1].value = -stack[sp].value;
      sp--;
      break;
    case SWIG_TOKEN_SLASH:
      stack[sp - 2].value = stack[sp - 2].value / stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_PERCENT:
      stack[sp - 2].value = stack[sp - 2].value % stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_LSHIFT:
      stack[sp - 2].value = stack[sp - 2].value << stack[sp].value;
      sp -= 2;
      break;
    case SWIG_TOKEN_RSHIFT:
      stack[sp - 2].value = stack[sp - 2].value >> stack[sp].value;
      sp -= 2;
      break;
    default:
      errmsg = "Syntax error: bad operator";
      return 0;
      break;
    }
  }
  stack[sp].op = EXPR_VALUE;
  stack[sp].svalue = 0;		/* ensure it's not a string! */
  return 1;
}
Esempio n. 3
0
// 'Main' function for parse string
static struct calc_essence* parse_data_parse(struct parse_data* data, int priority)
{
    struct calc_essence* result = NULL;
    // Operand
    switch(parse_data_next_token(data))
    {
    case token_type_error:
        break;//error was already been traced in parse_data_next_token()
    case token_type_eof:
        print_error0("End of file while operand expected");
        break;
    case token_type_value:
    case token_type_constant:
        result = calc_essence_val_create(data->current_token_value);
        if(result) parse_data_next_token(data);// advance to the next token
        break;
    case token_type_variable:
        result = calc_essence_var_create(data->current_token_index);
        if(result) parse_data_next_token(data);// advance to the next token
        break;
    case token_type_weak_variable:
        result = calc_essence_weak_var_create(data->current_token_index);
        if(result) parse_data_next_token(data);// advance to the next token
        break;
    case token_type_open_parenthesis:
        result = parse_data_parse(data, priority_min);
        if(!result) break;
        if(data->current_token_type != token_type_close_parenthesis)
        {
            print_error("Expected close parenthesis (')'), but token of type %d found.",
                        (int)data->current_token_type);
            // rollback result
            calc_essence_free(result);
            result = NULL;
            break;
        }
        parse_data_next_token(data);// advance to the next token
        break;
        //unary operations without left operand
#define UNARY_OP(essence_type_pure, priority_pure) {\
    struct calc_essence* op = parse_data_parse(data, priority_##priority_pure);\
    if(op == NULL) break;\
    result = calc_essence_1op_create(calc_essence_type_##essence_type_pure, op);\
    if(result == NULL) {calc_essence_free(op);}\
}
    case token_type_minus:
        UNARY_OP(unary_minus, unary_minus);
        break;
    case token_type_plus:
        UNARY_OP(unary_plus, unary_plus);
        break;
    case token_type_logical_not:
        UNARY_OP(logical_not, logical_not);
        break;
    case token_type_binary_not:
        UNARY_OP(binary_not, binary_not);
        break;
#undef UNARY_OP
    default:
        print_error("Expected operand, but token of type %d found.",
                    (int)data->current_token_type);
    }

    if(result == NULL) return NULL;
    //Determine operation and update operand in cycle, until error, delemiter or operation with lower priority is encountered
    while(1)
    {
        switch(data->current_token_type)
        {
        case token_type_error:
            calc_essence_free(result);
            return NULL;// error was already been traced in parse_data_next_token()
        // delimiters
        case token_type_eof:
        case token_type_close_parenthesis:
        case token_type_cond_second:
            return result;
            // operations with two operands
#define TWO_OPERANDS_ESSENCE(essence_type_pure, left_priority_pure, right_priority_pure) \
if(priority > priority_##left_priority_pure) return result;\
{\
    struct calc_essence* op1, *op2;\
    debug("Evaluate second operand for essence of type %d...", (int)calc_essence_type_##essence_type_pure);\
    op2 = parse_data_parse(data, priority_##right_priority_pure);\
    if(op2 == NULL) {calc_essence_free(result); return NULL;}\
    op1 = result;\
    debug0("Create essence.");\
    result = calc_essence_2op_create(calc_essence_type_##essence_type_pure, op1, op2);\
    if(result == NULL) {calc_essence_free(op1); calc_essence_free(op2); return NULL;}\
}
        case token_type_multiply:
            TWO_OPERANDS_ESSENCE(multiply, multiply_left, multiply_right);
            break;
        case token_type_divide:
            TWO_OPERANDS_ESSENCE(divide, divide_left, divide_right);
            break;
        case token_type_rest:
            TWO_OPERANDS_ESSENCE(rest, rest_left, rest_right);
            break;
        case token_type_plus:
            TWO_OPERANDS_ESSENCE(plus, plus_left, plus_right);
            break;
        case token_type_minus:
            TWO_OPERANDS_ESSENCE(minus, minus_left, minus_right);
            break;
        case token_type_left_shift:
            TWO_OPERANDS_ESSENCE(left_shift, left_shift_left, left_shift_right);
            break;
        case token_type_right_shift:
            TWO_OPERANDS_ESSENCE(right_shift, right_shift_left, right_shift_right);
            break;
        case token_type_less:
            TWO_OPERANDS_ESSENCE(less, less_left, less_right);
            break;
        case token_type_greater:
            TWO_OPERANDS_ESSENCE(greater, greater_left, greater_right);
            break;
        case token_type_less_equal:
            TWO_OPERANDS_ESSENCE(less_equal, less_equal_left, less_equal_right);
            break;
        case token_type_greater_equal:
            TWO_OPERANDS_ESSENCE(greater_equal, greater_equal_left, greater_equal_right);
            break;
        case token_type_equal:
            TWO_OPERANDS_ESSENCE(equal, equal_left, equal_right);
            break;
        case token_type_inequal:
            TWO_OPERANDS_ESSENCE(inequal, inequal_left, inequal_right);
            break;
        case token_type_binary_or:
            TWO_OPERANDS_ESSENCE(binary_or, binary_or_left, binary_or_right);
            break;
        case token_type_binary_xor:
            TWO_OPERANDS_ESSENCE(binary_xor, binary_xor_left, binary_xor_right);
            break;
        case token_type_binary_and:
            TWO_OPERANDS_ESSENCE(binary_and, binary_and_left, binary_and_right);
            break;
        case token_type_logical_or:
            TWO_OPERANDS_ESSENCE(logical_or, logical_or_left, logical_or_right);
            break;
        case token_type_logical_and:
            TWO_OPERANDS_ESSENCE(logical_and, logical_and_left, logical_and_right);
            break;
#undef TWO_OPERANDS_ESSENCE
        //Only one three operand essence, so without macro
        case token_type_cond_first:
            if(priority > priority_cond_left) return result;
            {
                struct calc_essence *op1, *op2, *op3;
                debug0("Evaluate second operand for 'a ? b : c' operation...");
                \
                op2 = parse_data_parse(data, priority_min);
                if(op2 == NULL)
                {
                    calc_essence_free(result);
                    return NULL;
                }
                if(data->current_token_type != token_type_cond_second)
                {
                    print_error("Expected ':', but token of type %d encountered.",
                                (int)data->current_token_type);
                }
                debug0("Evaluate third operand for 'a ? b : c' operation...");
                \
                op3 = parse_data_parse(data, priority_cond_right);
                if(op3 == NULL)
                {
                    calc_essence_free(op2);
                    calc_essence_free(result);
                    return NULL;
                }
                op1 = result;
                debug0("Create essence.");
                result = calc_essence_3op_create(calc_essence_type_cond, op1, op2, op3);
                if(result == NULL)
                {
                    calc_essence_free(op1);
                    calc_essence_free(op2);
                    calc_essence_free(op3);
                    return NULL;
                }
            }
            break;
        //...
        default:
            print_error("Expected operation, but token of type %d found.",
                        (int)data->current_token_type);
            calc_essence_free(result);
            return NULL;
        }
    }
    return result;
}