compiler.cpp

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

CPP
2,195
字号
              "integer or real type", leftPos);
      }

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

      left = new dbExprNode(cop, left, right);
    }
    else if (left->type == tpInteger && right->type == tpInteger)
    {
      left = new dbExprNode(dbvmPowerInt, left, right);
    }
    else
    {
      error("operands of arithmentic operator should be of "
            "integer or real type", rightPos);
    }
  }

  return left;
}


dbExprNode* dbCompiler::userDefinedOperator()
{
  dbExprNode* left = term();

  while (lex == tkn_ident)
  {
    dbUserFunction* func = dbUserFunction::find(name);

    if (func != NULL)
    {
      int nParams =  func->getNumberOfParameters();

      if (nParams != 2)
      {
        error("Only function with two arguments can be used as operator", currPos);
      }

      int rightPos = currPos;
      dbExprNode* right = term();

      if ((left->type != tpInteger && left->type != tpReal && left->type != tpString
           && left->type != tpReference && left->type != tpRawBinary && left->type != tpBoolean)
          || (right->type != tpInteger && right->type != tpReal && right->type != tpString
              && right->type != tpReference && right->type != tpRawBinary && right->type != tpBoolean))
      {

        error("User function should receive parameter of boolean, integer, real, string, reference or user defined type", rightPos);
      }

      left = new dbExprNode(dbvmFuncInt2Bool + func->type, func->fptr, left, right);
    }
    else
    {
      break;
    }
  }

  return left;
}

dbExprNode* dbCompiler::field(dbExprNode* expr, dbTableDescriptor* refTable,
                              dbFieldDescriptor* fd)
{
  int pos;

  while (true)
  {
    switch (lex)
    {

    case tkn_dot:
      pos = currPos;

      if (scan() != tkn_ident)
      {
        error("identifier expected", pos);
      }

      if (fd != NULL && fd->type == dbField::tpStructure)
      {
        if ((fd = fd->find(name)) == NULL)
        {
          error("Field not found");
        }
      }
      else
      {
        assert(expr != NULL);

        if (expr->type != tpReference)
        {
          error("Left operand of '.' should be "
                "structure or reference", pos);
        }

        if (refTable == NULL)
        {
          refTable = fd->refTable;
        }

        if (refTable == NULL)
        {
          refTable = fd->refTable;
        }

        if (refTable == NULL || (fd = refTable->findSymbol(name)) == NULL)
        {
          error("Field not found");
        }

        refTable = NULL;
        expr = new dbExprNode(dbvmDeref, expr);
      }

      break;

    case tkn_lbr:

      if (expr == NULL ||
          (expr->type != tpArray && expr->type != tpString))
      {
        error("Index can be applied only to arrays");
      }
      else
      {
        dbExprNode* index = disjunction();

        if (lex != tkn_rbr)
        {
          error("']' expected");
        }

        if (index->type != tpInteger && index->type != tpFreeVar)
        {
          error("Index should have integer type");
        }

        if (expr->type == tpString)
        {
          lex = scan();
          return new dbExprNode(dbvmCharAt, expr, index);
        }

        if (fd == NULL)
        {
          // variable of array of reference type
          expr = new dbExprNode(dbvmGetAt,expr,index,sizeof(oid_t));
        }
        else
        {
          if (refTable == NULL)
          {
            refTable = fd->refTable;
          }

          fd = fd->components;
          expr = new dbExprNode(dbvmGetAt, expr, index, fd->dbsSize);
        }
      }

      break;

    default:

      if (expr == NULL)
      {
        error("'.' expected");
      }

      return expr;
    }

    if (fd == NULL)
    {
      expr = new dbExprNode(dbvmLoadReference, expr, 0);
    }
    else if (fd->type == dbField::tpRawBinary)
    {
      expr = new dbExprNode(expr != NULL ? dbvmLoadRawBinary : dbvmLoadSelfRawBinary,
                            fd, expr);
    }
    else if (fd->type != dbField::tpStructure)
    {
      expr = new dbExprNode((expr != NULL
                             ? dbvmLoadBool : dbvmLoadSelfBool)
                            + fd->type, fd, expr);
    }

    lex = scan();
  }
}



dbExprNode* dbCompiler::term()
{
  dbFieldDescriptor* fd;
  dbTableDescriptor* refTable;
  int cop;
  int pos = currPos;
  dbBinding* bp;
  dbExprNode* expr = NULL;
  dbUserFunction* func;

  if ((cop = scan()) == tkn_where)
  {
    if (firstPos == 0)
    {
      firstPos = currPos;
    }

    cop = scan(); // just ignore 'where' keyword
  }

  switch (cop)
  {

  case tkn_eof:

  case tkn_order:

  case tkn_start:
    lex = cop;
    return new dbExprNode(dbvmVoid);

  case tkn_current:
    lex = scan();
    return field(new dbExprNode(dbvmCurrent), table, NULL);

  case tkn_ident:

    for (bp = bindings; bp != NULL; bp = bp->next)
    {
      if (name == bp->name)
      {
        bp->used = true;
        lex = scan();
        return new dbExprNode(dbvmVariable, (dbExprNode*)0, bp->index);
      }
    }

    if ((fd = table->findSymbol(name)) == NULL)
    {
      if ((func = dbUserFunction::find(name)) != NULL)
      {
        pos = currPos;
        expr = term();
        int argType = func->getParameterType();
        int nParams =  func->getNumberOfParameters();

        if (nParams > 1)
        {
          if (expr->type != tpList)
          {
            error("Too few paramters for user defined function");
          }

          dbExprNode* params[3];

          do
          {
            if (nParams == 0)
            {
              error("Too many parameters for user defined function");
            }

            dbExprNode* param = expr->operand[1];

            if (param->type != tpInteger && param->type != tpReal && param->type != tpString
                && param->type != tpReference && param->type != tpRawBinary && param->type != tpBoolean)
            {
              error("User function should receive parameters of boolean, integer, real, string, reference or user defined type", pos);
            }

            params[--nParams] = param;
            expr = expr->operand[0];
          }
          while (expr != NULL);

          if (nParams != 0)
          {
            error("Too few parameters for user defined function");
          }

          expr = new dbExprNode(dbvmFuncInt2Bool + func->type, func->fptr, params[0], params[1], params[2]);
        }
        else
        {
          if (argType == tpReal && expr->type == tpInteger)
          {
            expr = int2real(expr);
          }
          else if (argType == tpList)
          {
            if (expr->type != tpInteger && expr->type != tpReal && expr->type != tpString
                && expr->type != tpReference && expr->type != tpRawBinary && expr->type != tpBoolean)
            {
              error("User function should receive parameter of boolean, integer, real, string, reference or user defined type", pos);
            }
          }
          else if (argType != expr->type)
          {
            error("Incompatible function argument", pos);
          }

          expr = new dbExprNode(dbvmFuncInt2Bool + func->type, func->fptr, expr);
        }

        return field(expr, NULL, NULL);
      }

      error("Field not found", pos);
    }

    if (fd->type == dbField::tpRawBinary)
    {
      expr = new dbExprNode(dbvmLoadSelfRawBinary, fd);
    }
    else if (fd->type != dbField::tpStructure)
    {
      expr = new dbExprNode(dbvmLoadSelfBool + fd->type, fd);
    }

    lex = scan();
    return field(expr, NULL, fd);

  case tkn_exists:

    if (scan() == tkn_ident)
    {
      dbBinding var;
      var.next = bindings;
      var.name = name;
      var.used = false;
      var.index = nFreeVars++;
      bindings = &var;

      if (nFreeVars >= maxFreeVars)
      {
        error("Too many nested EXISTS clauses\n");
      }

      pos = currPos;

      if (scan() != tkn_col)
      {
        error("':' expected", pos);
      }

      expr = term();

      if (expr->type != tpBoolean)
      {
        error("Expresion in EXISTS clause should be of boolean type");
      }

      if (var.used)
      {
        expr = new dbExprNode(dbvmExists, expr, nFreeVars-1);
      }

      nFreeVars -= 1;
      assert(bindings == &var);
      bindings = var.next;
      return expr;
    }
    else
    {
      error("Free variable name expected");
    }

    break;

  case tkn_first:
    lex = scan();
    return field(new dbExprNode(dbvmFirst), table, NULL);

  case tkn_last:
    lex = scan();
    return field(new dbExprNode(dbvmLast), table, NULL);

  case tkn_false:
    expr = new dbExprNode(dbvmLoadFalse);
    break;

  case tkn_true:
    expr = new dbExprNode(dbvmLoadTrue);
    break;

  case tkn_null:
    expr = new dbExprNode(dbvmLoadNull);
    break;

  case tkn_iconst:
    expr = new dbExprNode(dbvmLoadIntConstant, ivalue);
    break;

  case tkn_fconst:
    expr = new dbExprNode(dbvmLoadRealConstant, fvalue);
    break;

  case tkn_sconst:
    expr = new dbExprNode(dbvmLoadStringConstant, svalue);
    lex = scan();
    return field(expr, NULL, NULL);

  case tkn_var:
    expr = new dbExprNode(dbvmLoadVarBool + varType -
                          dbQueryElement::qVarBool, varPtr);
    refTable = varRefTable;
    lex = scan();
    return field(expr, refTable, NULL);

  case tkn_abs:

  case tkn_length:

  case tkn_lower:

  case tkn_upper:

  case tkn_integer:

  case tkn_real:

  case tkn_string:
    pos = currPos;
    expr = term();

    switch (cop)
    {

    case tkn_abs:

      if (expr->type == tpInteger)
      {
        cop = dbvmAbsInt;
      }
      else if (expr->type == tpReal)
      {
        cop = dbvmAbsReal;
      }
      else
      {
        error("ABS function can be applied only "
              "to integer or real expression", pos);
      }

      break;

    case tkn_length:

      if (expr->type == tpArray)
      {
        cop = dbvmLength;
      }
      else if (expr->type == tpString)
      {
        cop = dbvmStringLength;
      }
      else
      {
        error("LENGTH function is defined only for arrays and strings",
              pos);
      }

      break;

    case tkn_integer:

      if (expr->type == tpReal)
      {
        cop = dbvmRealToInt;
      }
      else
      {
        error("INTEGER function can be applied only to "
              "expression of real type", pos);
      }

      break;

    case tkn_real:

      if (expr->type == tpInteger)
      {
        cop = dbvmIntToReal;
      }
      else
      {
        error("REAL function can be applied only to "
              "expression of integer type", pos);
      }

      break;

    case tkn_string:

      if (expr->type == tpInteger)
      {
        cop = dbvmIntToString;
      }
      else if (expr->type == tpReal)
      {
        cop = dbvmRealToString;
      }
      else
      {
        error("STRING function can be applied only "
              "to integer or real expression", pos);
      }

      break;

    case tkn_lower:

      if (expr->type != tpString)
      {
        error("LOWER function can be applied only to string argument",
              pos);
      }
      else
      {
        cop = dbvmLowerString;
      }

      break;

    case tkn_upper:

      if (expr->type != tpString)
      {
        error("UPPER function can be applied only to string argument",
              pos);
      }
      else
      {
        cop = dbvmUpperString;
      }

⌨️ 快捷键说明

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