compiler.cpp

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

CPP
2,195
字号

      break;

    default:
      assert(false);
    }

    return field(new dbExprNode(cop, expr), NULL, NULL);

  case tkn_lpar:
    {
      expr = disjunction();
      dbExprNode* list = NULL;

      while (lex == tkn_comma)
      {
        list = new dbExprNode(dbvmList, list, expr);
        expr = disjunction();
      }

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

      if (list != NULL)
      {
        expr = new dbExprNode(dbvmList, list, expr);
      }
    }

    break;

  case tkn_not:
    pos = currPos;
    expr = comparison();

    if (expr->type == tpInteger)
    {
      if (expr->cop == dbvmLoadIntConstant)
      {
        expr->ivalue = ~expr->ivalue;
      }
      else
      {
        expr = new dbExprNode(dbvmNotInt, expr);
      }

      return expr;
    }
    else if (expr->type == tpBoolean)
    {
      return new dbExprNode(dbvmNotBool, expr);
    }
    else
    {
      error("NOT operator can be applied only to "
            "integer or boolean expressions", pos);
    }

    break;

  case tkn_add:
    error("Using of unary plus operator has no sence");
    break;

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

    if (expr->type == tpInteger)
    {
      if (expr->cop == dbvmLoadIntConstant)
      {
        expr->ivalue = -expr->ivalue;
      }
      else
      {
        expr = new dbExprNode(dbvmNegInt, expr);
      }

      return expr;
    }
    else if (expr->type == tpReal)
    {
      if (expr->cop == dbvmLoadRealConstant)
      {
        expr->fvalue = -expr->fvalue;
      }
      else
      {
        expr = new dbExprNode(dbvmNegReal, expr);
      }

      return expr;
    }
    else
    {
      error("Unary minus can be applied only to "
            "integer or real expressions", pos);
    }

  default:
    error("operand expected");
  }

  lex = scan();
  return expr;
}

void dbCompiler::error(const char* msg, int pos)
{
  if (pos < 0)
  {
    if ((pos = currPos-1) < 0)
    {
      pos = 0;
    }
  }
  else if (pos < firstPos)
  {
    pos = firstPos;
  }

  if (pos + offsetWithinStatement >= 0)
  {
    pos += offsetWithinStatement;
  }

  table->db->handleError(dbDatabase::QueryError, msg, pos);
  longjmp(abortCompilation, dbDatabase::QueryError);
}

void dbCompiler::compileStartFollowPart(dbQuery& query)
{
  if (lex != tkn_start)
  {
    return;
  }

  int pos = currPos;

  if (scan() != tkn_from)
  {
    error("FROM expected after START", pos);
  }

  pos = currPos;

  switch (scan())
  {

  case tkn_first:
    query.startFrom = dbCompiledQuery::StartFromFirst;
    break;

  case tkn_last:
    query.startFrom = dbCompiledQuery::StartFromLast;
    break;

  case tkn_var:

    if (varType == dbQueryElement::qVarReference)
    {
      if (varRefTable != table)
      {
        error("Incompatiable type of reference variable");
      }

      query.startFrom = dbCompiledQuery::StartFromRef;
    }
    else if (varType == dbQueryElement::qVarArrayOfRef)
    {
      if (varRefTable != table)
      {
        error("Incompatiable type of array of reference variable");
      }

      query.startFrom = dbCompiledQuery::StartFromArray;
    }
    else if (varType == dbQueryElement::qVarArrayOfRefPtr)
    {
      if (varRefTable != table)
      {
        error("Incompatiable type of array of reference variable");
      }

      query.startFrom = dbCompiledQuery::StartFromArrayPtr;
    }
    else
    {
      error("Reference or array of reference variable expected");
    }

    query.root = varPtr;
    break;

  default:
    error("FIRST, LAST or reference varaible expected", pos);
  }

  if ((lex = scan()) == tkn_follow)
  {
    pos = currPos;

    if (scan() != tkn_by)
    {
      error("BY expected after FOLLOW", pos);
    }

    do
    {
      pos = currPos;

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

      dbFieldDescriptor* fd;

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

      while (fd->type == dbField::tpStructure)
      {
        pos = currPos;

        if (scan() != tkn_dot)
        {
          error("'.' expected", pos);
        }

        pos = currPos;

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

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

      if (!(fd->type == dbField::tpReference
            && fd->refTable == table) &&
          !(fd->type == dbField::tpArray
            && fd->components->type == dbField::tpReference
            && fd->components->refTable == table))
      {
        error("Follow field should be of compatibale reference "
              "or array of reference type");
      }

      dbFollowByNode* node = new dbFollowByNode;
      node->field = fd;
      node->next = query.follow; // list should be inverted
      query.follow = node;
    }
    while ((lex = scan()) == tkn_comma);
  }
}

void dbCompiler::compileOrderByPart(dbQuery& query)
{
  if (lex == tkn_order)
  {
    dbOrderByNode** opp = &query.order;
    int pos = currPos;

    if (scan() != tkn_by)
    {
      error("BY expected after ORDER", pos);
    }

    int parentheses = 0;

    do
    {
      pos = currPos;
      int tkn = scan();

      if (tkn == tkn_lpar)
      {
        parentheses += 1;
      }
      else
      {
        ungetToken(tkn);
      }

      dbExprNode* expr = disjunction();
      dbOrderByNode* node = new dbOrderByNode;

      switch (expr->cop)
      {

      case dbvmLoadSelfBool:

      case dbvmLoadSelfInt1:

      case dbvmLoadSelfInt2:

      case dbvmLoadSelfInt4:

      case dbvmLoadSelfInt8:

      case dbvmLoadSelfReal4:

      case dbvmLoadSelfReal8:

      case dbvmLoadSelfString:

      case dbvmLoadSelfArray:

      case dbvmLoadSelfReference:

      case dbvmLoadSelfRawBinary:
        assert(expr->ref.field != NULL);
        node->field = expr->ref.field;
        node->expr = NULL;
        delete expr;
        break;

      case dbvmLength:

        if (expr->operand[0]->cop == dbvmLoadSelfArray)
        {
          node->field = expr->operand[0]->ref.field;
          node->expr = NULL;
          delete expr;
          break;
        }

        // no break

      default:
        if (expr->type > tpReference)
        {
          error("Expressions in ORDER BY part should have scalar type", pos);
        }

        node->field = NULL;
        node->expr = expr;
      }

      node->table = table;
      node->ascent = true;
      *opp = node;
      opp = &node->next;
      *opp = NULL;

      if (lex == tkn_desc)
      {
        node->ascent = false;
        lex = scan();
      }
      else if (lex == tkn_asc)
      {
        lex = scan();
      }

      if (lex == tkn_rpar)
      {
        if (--parentheses < 0)
        {
          error("Unbalanced parentheses ");
        }

        lex = scan();
      }
    }
    while (lex == tkn_comma);
  }
}


dbExprNode* dbCompiler::compileExpression(dbTableDescriptor* table, char const* expr, int startPos)
{
  TRACE_MSG(("Compile expression %s for table %s\n", table->name));

  if (setjmp(abortCompilation) == 0)
  {
    this->table = table;
    bindings = NULL;
    nFreeVars = 0;
    dbQueryElement elem(dbQueryElement::qExpression, expr, NULL);
    queryElement = &elem;
    currPos = firstPos = 0;
    offsetWithinStatement = startPos;
    return disjunction();
  }
  else
  {
    return NULL;
  }
}

bool dbCompiler::compile(dbTableDescriptor* table, dbQuery& query)
{
  TRACE_MSG(("Compile query for table %s\n", table->name));
  query.destroy();

  if (setjmp(abortCompilation) == 0)
  {
    this->table = table;
    bindings = NULL;
    nFreeVars = 0;
    queryElement = query.elements;
    currPos = firstPos = 0;
    hasToken  = false;
    offsetWithinStatement = query.pos;
    dbExprNode* expr = disjunction();

    if (expr->type != tpBoolean && expr->type != tpVoid)
    {
      table->db->handleError(dbDatabase::QueryError, "Conditional "
                             "expression should have boolean type\n", 0);
      delete expr;
      return false;
    }

    compileStartFollowPart(query);
    compileOrderByPart(query);
    query.tree  = expr;
    query.table = table;
    return true;
  }
  else
  {
    for (dbOrderByNode *op = query.order, *nop; op != NULL; op = nop)
    {
      nop = op->next;
      delete op;
    }

    for (dbFollowByNode *fp = query.follow, *nfp; fp != NULL; fp = nfp)
    {
      nfp = fp->next;
      delete fp;
    }

    return false;
  }
}

dbCompiler::dbCompiler()
{

  static struct
  {
    char* name;
    int   tag;
  }

  keywords[] = {
                 {"all",     tkn_all},
                 {"abs",     tkn_abs},
                 {"and",     tkn_and},
                 {"asc",     tkn_asc},
                 {"between", tkn_between},
                 {"by",      tkn_by},
                 {"current", tkn_current},
                 {"desc",    tkn_desc},
                 {"escape",  tkn_escape},
                 {"exists",  tkn_exists},
                 {"first",   tkn_first},
                 {"false",   tkn_false},
                 {"follow",  tkn_follow},
                 {"from",    tkn_from},
                 {"in",      tkn_in},
                 {"is",      tkn_is},
                 {"integer", tkn_integer},
                 {"insert",  tkn_insert},
                 {"into",    tkn_into},
                 {"last",    tkn_last},
                 {"length",  tkn_length},
                 {"like",    tkn_like},
                 {"lower",   tkn_lower},
                 {"not",     tkn_not},
                 {"null",    tkn_null},
                 {"or",      tkn_or},
                 {"order",   tkn_order},
                 {"real",    tkn_real},
                 {"select",  tkn_select},
                 {"start",   tkn_start},
                 {"string",  tkn_string},
                 {"table",   tkn_table},
                 {"true",    tkn_true},
                 {"upper",   tkn_upper},
                 {"where",   tkn_where}
               };

  if (!initialized)
  {
    for (unsigned i = 0; i < itemsof(keywords); i++)
    {

      dbSymbolTable::add
        (keywords[i].name, keywords[i].tag, FASTDB_CLONE_ANY_IDENTIFIER);
    }

    initialized = true;
  }
}

void dbInheritedAttribute::removeTemporaries()
{
  for (dbStringValue *next, *s = tempStrings; s != NULL; s = next)
  {
    next = s->next;
    delete s;
  }
}


static void stderrTrace(char* msg)
{
  fputs(msg, stderr);
}

dbTraceFunctionPtr dbTraceFunction = stderrTrace;

void dbTrace(char* message, ...)
{
  va_list args;
  va_start (args, message);
  char buffer[1024];
  vsprintf(buffer, message, args);
  (*dbTraceFunction)(buffer);
  va_end(args);
}


byte* dbMalloc(size_t size)
{
  return (byte*)malloc(size);
}

void  dbFree(void* p)
{
  free(p);
}

⌨️ 快捷键说明

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