compiler.cpp

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

CPP
1,688
字号
        } else if (fd->type == dbField::tpRectangle) {            expr = new dbExprNode(expr != NULL ? dbvmLoadRectangle: dbvmLoadSelfRectangle,                                   fd, expr);        } else if (fd->type != dbField::tpStructure) {             expr = new dbExprNode((expr != NULL                                    ? dbvmLoadBool : dbvmLoadSelfBool)                                   + fd->type, fd, expr);        }        lex = scan();    }}dbExprNode* dbCompiler::buildList() {     dbExprNode* expr = disjunction();     return new dbExprNode(dbvmList, expr, lex == tkn_comma ? buildList() : NULL);}dbExprNode* dbCompiler::term() {    dbFieldDescriptor* fd;    dbTableDescriptor* refTable;    int cop;    int pos = currPos;    int prevLex = lex;    dbBinding* bp;    dbExprNode* expr = NULL;    dbUserFunction* func;    if ((cop = scan()) == tkn_where) {         if (firstPos == 0) {             firstPos = currPos;        }        cop = scan(); // just ignore 'where' keyword    }    lex = cop;    switch (cop) {       case tkn_eof:      case tkn_order:      case tkn_start:      case tkn_limit:        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];                    int n = 0;                    do {                         if (n == nParams) {                             error("Too many parameters for user defined function");                        }                               dbExprNode* param = expr->operand[0];                        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[n++] = param;                        expr = expr->operand[1];                    } while (expr != NULL);                    if (n != nParams) {                         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::tpRectangle) {             expr = new dbExprNode(dbvmLoadSelfRectangle, 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_area:      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_area:            if (expr->type == tpRectangle) {                cop = dbvmRectangleArea;            } else if (expr->type == tpList) {                 expr = rectangleConstant(expr);                cop = dbvmRectangleArea;                            } else {                error("AREA function can be applied only to rectangles", 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;            }            break;          default:            assert(false);        }        return field(new dbExprNode(cop, expr), NULL, NULL);      case tkn_lpar:        {            expr = disjunction();                        if (lex == tkn_comma) {                 expr = new dbExprNode(dbvmList, expr, buildList());            } else if (prevLex == tkn_in) {                 expr = new dbExprNode(dbvmList, expr);            }            if (lex != tkn_rpar) {                 error("')' expected");            }        }        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)

⌨️ 快捷键说明

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