compiler.cpp

来自「FastDb是高效的内存数据库系统」· C++ 代码 · 共 2,195 行 · 第 1/4 页

CPP
2,195
字号
  }
  else if (expr->type == tpBoolean && elem->type == tpBoolean)
  {
    cop = dbvmEqBool;
  }
  else if (expr->type == tpRawBinary && elem->type == tpRawBinary)
  {
    cop = dbvmEqBinary;

    if ((expr->cop == dbvmLoadSelfRawBinary || expr->cop == dbvmLoadRawBinary)
        && expr->ref.field != NULL)
    {
      rawBinarySize = expr->ref.field->dbsSize;
      rawBinaryComparator = (void*)expr->ref.field->comparator;
    }
    else if ((elem->cop == dbvmLoadSelfRawBinary || elem->cop == dbvmLoadRawBinary)
             && elem->ref.field != NULL)
    {
      rawBinarySize = elem->ref.field->dbsSize;
      rawBinaryComparator = (void*)elem->ref.field->comparator;
    }
    else
    {
      error("Operations with raw binary types should include at least one record field");
    }
  }

  if (cop == dbvmVoid)
  {
    char buf[256];
    sprintf(buf, "Expression %d in right part of IN operator have "
            "incompatible type", n);
    error(buf);
  }
  else
  {
    list->type = tpBoolean;

    if (list->operand[0] != NULL)
    {
      expr = new dbExprNode(cop, expr, elem, rawBinarySize);
      expr->func.fptr = rawBinaryComparator;
      list->operand[1] = expr;
      list->cop = dbvmOrBool;
    }
    else
    {
      list->operand[0] = expr;
      list->cop = cop;
      list->offs = rawBinarySize;
      list->func.fptr = rawBinaryComparator;
    }
  }

  return ++n;
}

dbExprNode* dbCompiler::comparison()
{
  int leftPos = currPos;
  dbExprNode *left, *right;
  left = addition();
  int cop = lex;

  if (cop == tkn_eq || cop == tkn_ne || cop == tkn_gt || cop == tkn_ge
      || cop == tkn_le || cop == tkn_lt || cop == tkn_between
      || cop == tkn_like || cop == tkn_not || cop == tkn_is || cop == tkn_in)
  {
    int rightPos = currPos;
    bool notOp = false;

    if (cop == tkn_not)
    {
      notOp = true;
      cop = scan();

      if (cop != tkn_like && cop != tkn_between && cop != tkn_in)
      {
        error("LIKE, BETWEEN or IN expected", rightPos);
      }

      rightPos = currPos;
    }
    else if (cop == tkn_is)
    {
      if (left->type != tpReference)
      {
        error("IS [NOT] NULL predicate can be applied only to "
              "references", rightPos);
      }

      rightPos = currPos;

      if ((cop = scan()) == tkn_null)
      {
        left = new dbExprNode(dbvmIsNull, left);
      }
      else if (cop == tkn_not)
      {
        rightPos = currPos;

        if (scan() == tkn_null)
        {
          left = new dbExprNode(dbvmNotBool,
                                new dbExprNode(dbvmIsNull, left));
        }
        else
        {
          error("NULL expected", rightPos);
        }
      }
      else
      {
        error("[NOT] NULL expected", rightPos);
      }

      lex = scan();
      return left;
    }

    right = addition();

    if (cop == tkn_in)
    {
      int type;

      switch (right->type)
      {

      case tpArray:
        type = (right->cop == dbvmLoadVarArray || right->cop == dbvmLoadVarArrayPtr)
               ? dbField::tpReference
               : right->ref.field->components->type;

        if ((left->type == tpBoolean && type == dbField::tpBool)
            || (left->type == tpInteger
                && (type == dbField::tpInt1
                    || type == dbField::tpInt2
                    || type == dbField::tpInt4
                    || type == dbField::tpInt8))
            || (left->type == tpReal
                && (type == dbField::tpReal4
                    || type == dbField::tpReal8))
            || (left->type == tpString && type == dbField::tpString)
            || ((left->type == tpReference || left->type == tpInteger)
                && type == dbField::tpReference))
        {
          if (left->type == tpInteger && type == dbField::tpReference)
          {
            left = new dbExprNode(dbvmIntToReference, left);
          }

          left = new dbExprNode(dbvmInArrayBool + type, left, right);
        }
        else
        {
          error("Type of selective expression of IN operator doesn't"
                " match type of the array");
        }

        break;

      case tpString:

        if (left->type == tpString)
        {
          left = new dbExprNode(dbvmInString, left, right);
        }
        else
        {
          error("Left operand of IN expression hasn't string type");
        }

        break;

      case tpList:
        compare(left, right);
        left = right;
        break;

      default:
        error("List of expressions or array expected", rightPos);
      }
    }
    else if (cop == tkn_between)
    {
      int andPos = currPos;

      if (lex != tkn_and)
      {
        error("AND expected");
      }

      dbExprNode* right2 = addition();

      if (left->type == tpReal
          || right->type == tpReal || right2->type == tpReal)
      {
        if (left->type == tpInteger)
        {
          left = int2real(left);
        }
        else if (left->type != tpReal)
        {
          error("operand of BETWEEN operator should be of "
                "integer, real or string type", leftPos);
        }

        if (right->type == tpInteger)
        {
          right = int2real(right);
        }
        else if (right->type != tpReal)
        {
          error("operand of BETWEEN operator should be of "
                "integer, real or string type", rightPos);
        }

        if (right2->type == tpInteger)
        {
          right2 = int2real(right2);
        }
        else if (right2->type != tpReal)
        {
          error("operand of BETWEEN operator should be of "
                "integer, real or string type", andPos);
        }

        left = new dbExprNode(dbvmBetweenReal, left, right, right2);
      }
      else if (left->type == tpInteger && right->type == tpInteger
               && right2->type == tpInteger)
      {
        left = new dbExprNode(dbvmBetweenInt, left, right, right2);
      }
      else if (left->type == tpString && right->type == tpString
               && right2->type == tpString)
      {
        left = new dbExprNode(dbvmBetweenString, left, right, right2);
      }
      else if (left->type == tpRawBinary && right->type == tpRawBinary
               && right2->type == tpRawBinary)
      {
        int rawBinarySize = 0;
        void* rawBinaryComparator = NULL;

        if ((left->cop == dbvmLoadSelfRawBinary || left->cop == dbvmLoadRawBinary)
            && left->ref.field != NULL)
        {
          rawBinarySize = left->ref.field->dbsSize;
          rawBinaryComparator = (void*)left->ref.field->comparator;
        }
        else
        {
          error("Operations with raw binary types should include at least one record field");
        }

        left = new dbExprNode(dbvmBetweenBinary, left, right, right2);
        left->offs = rawBinarySize;
        left->func.fptr = rawBinaryComparator;
      }
      else
      {
        error("operands of BETWEEN operator should be of "
              "integer, real or string type", rightPos);
      }
    }
    else if (cop == tkn_like)
    {
      if (left->type != tpString || right->type != tpString)
      {
        error("operands of LIKE operator should be of "
              "string type", rightPos);
      }

      if (lex == tkn_escape)
      {
        rightPos = currPos;

        if (scan() != tkn_sconst)
        {
          error("String literal espected after ESCAPE", rightPos);
        }

        lex = scan();
        left = new dbExprNode(dbvmLikeEscapeString, left, right,
                              new dbExprNode(dbvmLoadStringConstant, svalue));
      }
      else
      {
        left = new dbExprNode(dbvmLikeString, left, right);
      }
    }
    else
    {
      if (left->type == tpReal || right->type == tpReal)
      {
        if (left->type == tpInteger)
        {
          left = int2real(left);
        }
        else if (left->type != tpReal)
        {
          error("operands of relation operator should be of "
                "intger, real or string type", leftPos);
        }

        if (right->type == tpInteger)
        {
          right = int2real(right);
        }
        else if (right->type != tpReal)
        {
          error("operands of relation operator should be of "
                "intger, real or string type", rightPos);
        }

        left = new dbExprNode(dbvmEqReal + cop - tkn_eq, left, right);
      }
      else if (left->type == tpInteger && right->type == tpInteger)
      {
        left = new dbExprNode(dbvmEqInt + cop - tkn_eq, left, right);
      }
      else if (left->type == tpString && right->type == tpString)
      {
        left = new dbExprNode(dbvmEqString + cop-tkn_eq, left, right);
      }
      else if ((left->type == tpReference || left->type == tpInteger)
               && (right->type == tpReference || right->type == tpInteger))
      {
        if (cop != tkn_eq && cop != tkn_ne)
        {
          error("References can be checked only for equality",
                rightPos);
        }

        if (left->type == tpInteger)
        {
          left = new dbExprNode(dbvmIntToReference, left);
        }
        else if (right->type == tpInteger)
        {
          right = new dbExprNode(dbvmIntToReference, right);
        }

        left = new dbExprNode(dbvmEqReference+cop-tkn_eq, left, right);
      }
      else if (left->type == tpBoolean && right->type == tpBoolean)
      {
        if (cop != tkn_eq && cop != tkn_ne)
        {
          error("Boolean variables can be checked only for equality",
                rightPos);
        }

        left = new dbExprNode(dbvmEqBool + cop - tkn_eq, left, right);
      }
      else if (left->type == tpRawBinary && right->type == tpRawBinary)
      {
        int rawBinarySize = 0;
        void* rawBinaryComparator = NULL;

        if ((left->cop == dbvmLoadSelfRawBinary || left->cop == dbvmLoadRawBinary)
            && left->ref.field != NULL)
        {
          rawBinarySize = left->ref.field->dbsSize;
          rawBinaryComparator = (void*)left->ref.field->comparator;
        }
        else if ((right->cop == dbvmLoadSelfRawBinary || right->cop == dbvmLoadRawBinary)
                 && right->ref.field != NULL)
        {
          rawBinarySize = right->ref.field->dbsSize;
          rawBinaryComparator = (void*)right->ref.field->comparator;
        }
        else
        {
          error("Operations with raw binary types should include at least one record field");
        }

        left = new dbExprNode(dbvmEqBinary + cop - tkn_eq, left, right, rawBinarySize);
        left->func.fptr = rawBinaryComparator;
      }
      else
      {
        error("operands of relation operator should be of "
              "integer, real or string type", rightPos);
      }

      //
      // Optimization for applying indices: if operation is
      // commuatative and left operand is constant then swap operands
      //
      if (IS_CONSTANT(left->operand[0]->cop))
      {
        right = left->operand[1];
        left->operand[1] = left->operand[0];
        left->operand[0] = right;
        left->cop = dbExprNode::commutativeOperator[left->cop];
      }
    }

    if (notOp)
    {
      left = new dbExprNode(dbvmNotBool, left);
    }
  }

  return left;
}

dbExprNode* dbCompiler::addition()
{
  int leftPos = currPos;
  dbExprNode* left = multiplication();

  while (lex == tkn_add || lex == tkn_sub)
  {
    int cop = lex;
    int rightPos = currPos;
    dbExprNode* right = multiplication();

    if (left->type == tpReal || right->type == tpReal)
    {
      if (left->type == tpInteger)
      {
        left = int2real(left);
      }
      else if (left->type != tpReal)
      {
        error("operands of arithmetic operators should be of "
              "integer or real type", leftPos);
      }

      if (right->type == tpInteger)
      {
        right = int2real(right);
      }
      else if (right->type != tpReal)
      {
        error("operands of arithmetic operator should be of "
              "integer or real type", rightPos);
      }

      left = new dbExprNode(cop==tkn_add ? dbvmAddReal : dbvmSubReal,
                            left, right);
    }
    else if (left->type == tpInteger && right->type == tpInteger)
    {
      left = new dbExprNode(cop==tkn_add ? dbvmAddInt : dbvmSubInt,
                            left, right);
    }
    else if (left->type == tpString && right->type == tpString)
    {
      if (cop == tkn_add)
      {
        left = new dbExprNode(dbvmStringConcat, left, right);
      }
      else
      {
        error("Operation - is not defined for strings", rightPos);
      }
    }
    else
    {
      error("operands of arithmentic operator should be of "
            "integer or real type", rightPos);
    }

    leftPos = rightPos;
  }

  return left;
}


dbExprNode* dbCompiler::multiplication()
{
  int leftPos = currPos;
  dbExprNode* left = power();

  while (lex == tkn_mul || lex == tkn_div)
  {
    int cop = lex;
    int rightPos = currPos;
    dbExprNode* right = power();

    if (left->type == tpReal || right->type == tpReal)
    {
      if (left->type == tpInteger)
      {
        left = int2real(left);
      }
      else if (left->type != tpReal)
      {
        error("operands of arithmetic operators should be of "
              "integer or real type", leftPos);
      }

      if (right->type == tpInteger)
      {
        right = int2real(right);
      }
      else if (right->type != tpReal)
      {
        error("operands of arithmetic operator should be of "
              "integer or real type", rightPos);
      }

      left = new dbExprNode(cop==tkn_mul ? dbvmMulReal : dbvmDivReal,
                            left, right);
    }
    else if (left->type == tpInteger && right->type == tpInteger)
    {
      left = new dbExprNode(cop==tkn_mul ? dbvmMulInt : dbvmDivInt,
                            left, right);
    }
    else
    {
      error("operands of arithmentic operator should be of "
            "integer or real type", rightPos);
    }

    leftPos = rightPos;
  }

  return left;
}

dbExprNode* dbCompiler::power()
{
  int leftPos = currPos;
  dbExprNode* left = userDefinedOperator();

  if (lex == tkn_power)
  {
    int rightPos = currPos;
    dbExprNode* right = power();

    if (left->type == tpReal || right->type == tpReal)
    {
      int cop = dbvmPowerReal;

      if (left->type == tpInteger)
      {
        left = int2real(left);
      }
      else if (left->type != tpReal)
      {
        error("operands of arithmetic operators should be of "

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?