⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compiler.cpp

📁 最新版本!fastdb是高效的内存数据库系统
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    return left;
}

dbExprNode* dbCompiler::conjunction()
{
    dbExprNode* left = comparison();
    if (lex == tkn_and) { 
        int pos = currPos;
        dbExprNode* right = conjunction();
        if (left->type == tpInteger && right->type == tpInteger) { 
            left = new dbExprNode(dbvmAndInt, left, right);
        } else if (left->type == tpBoolean && right->type == tpBoolean) { 
            left = new dbExprNode(dbvmAndBool, left, right);
        } else { 
            error("Bad operands for AND operator", pos);
        }
    }
    return left;
}

inline dbExprNode* int2real(dbExprNode* expr) 
{
    if (expr->cop == dbvmLoadIntConstant) { 
        expr->fvalue = (real8)expr->ivalue;
        expr->cop = dbvmLoadRealConstant;
        expr->type = tpReal;
    } else { 
        expr = new dbExprNode(dbvmIntToReal, expr);
    }
    return expr;
}

void dbCompiler::compare(dbExprNode* expr, dbExprNode* list)
{
    dbExprNode* selector = expr;
    for (int n = 1; list != NULL; n++) { 
        dbExprNode* elem = list->operand[0];
        dbExprNode* tail = list->operand[1];
        int cop = dbvmVoid;
        int rawBinarySize = 0;
        void* rawBinaryComparator = NULL;
        if (expr->type == tpInteger) { 
            if (elem->type == tpReal) { 
                expr = int2real(expr);
                cop = dbvmEqReal;
            } else if (elem->type == tpReference) {
                expr = new dbExprNode(dbvmIntToReference, expr);
                cop = dbvmEqReference;
            } else if (elem->type == tpInteger) { 
                cop = dbvmEqInt;
            }
        } else if (expr->type == tpReal) {
            if (elem->type == tpReal) { 
                cop = dbvmEqReal;
            } else if (elem->type == tpInteger) { 
                cop = dbvmEqReal;
                elem = int2real(elem);
            }
        } else if (expr->type == tpString && elem->type == tpString) {
            cop = dbvmEqString;
        } else if (expr->type == tpReference && (elem->type == tpReference || elem->type == tpInteger)) {
            if (elem->type == tpInteger) {
                elem = new dbExprNode(dbvmIntToReference, elem);
            }
            cop = dbvmEqReference;
        } 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 (tail != NULL) { 
                expr = new dbExprNode(cop, expr, elem, rawBinarySize);
                expr->func.fptr = rawBinaryComparator;
                list->operand[0] = expr;
                list->cop = dbvmOrBool;
                expr = new dbExprNode(selector);
            } else { 
                list->operand[1] = elem;
                list->operand[0] = expr;
                list->cop = cop;
                list->offs = rawBinarySize;
                list->func.fptr = rawBinaryComparator;
            }
        }
        list = tail;
    }
}

dbExprNode* dbCompiler::rectangleConstant(dbExprNode* head)
{
    rectangle r;
    for (int i = 0; i < RECTANGLE_DIMENSION*2; i++) { 
        if (head == NULL) { 
            error("Bad rectangle constant");
        }
        dbExprNode* elem = head->operand[0];
        dbExprNode* tail = head->operand[1];
        if (elem->type == tpReal) {                         
            r.boundary[i] = (coord_t)elem->fvalue;
        } else if (elem->type == tpInteger) {  
            r.boundary[i] = (coord_t)elem->ivalue;
        } else { 
            error("Bad rectangle constant");
        }
        head = tail;
    }
    if (head != NULL) { 
        error("Bad rectangle constant");
    }
    return new dbExprNode(dbvmLoadRectangleConstant, r);
}


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_overlaps
        || cop == tkn_like || cop == tkn_match || 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_match && cop != tkn_between && cop != tkn_in) { 
                error("LIKE, MATCH, 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:
                switch (right->cop) { 
                  case dbvmLoadVarArrayOfOid:
                  case dbvmLoadVarArrayOfOidPtr:
                    type = dbField::tpReference;
                    break;
                  case dbvmLoadVarArrayOfInt4:
                  case dbvmLoadVarArrayOfInt4Ptr:
                    type = dbField::tpInt4;
                    break;
                  case dbvmLoadVarArrayOfInt8:
                  case dbvmLoadVarArrayOfInt8Ptr:
                    type = dbField::tpInt8;
                    break;
                  default:
                    type = 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 == tpRectangle || left->type == tpList) && type == dbField::tpRectangle)
                    || ((left->type == tpReference || left->type == tpInteger)
                        && type == dbField::tpReference))
                {
                    if (left->type == tpInteger && type == dbField::tpReference) { 
                        left = new dbExprNode(dbvmIntToReference, left);
                    }
                    if (type == dbField::tpRectangle) { 
                        if (left->type == tpList) { 
                            left = rectangleConstant(left);
                        }
                        left = new dbExprNode(dbvmInArrayRectangle, left, right);
                    } else { 
                        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 tpRectangle:
                if (left->type == tpRectangle) {
                    if (IS_CONSTANT(left->cop)) {
                        left = new dbExprNode(dbvmGeRectangle, right, left);
                    } else { 
                        left = new dbExprNode(dbvmLeRectangle, left, right);
                    }
                } else if (left->type == tpList) {
                    left = new dbExprNode(dbvmGeRectangle, right, rectangleConstant(left));
                } else {
                    error("Left operand of IN expression hasn't rectangle type");
                }
                break;          
              case tpList:
                if (left->type == tpRectangle) {
                    left = new dbExprNode(dbvmLeRectangle, left, rectangleConstant(right));
                } else { 
                    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);
            }
#ifdef USE_REGEX
        } else if (cop == tkn_match) {
            if (left->type != tpString) {
                error("left operands of MATCH operator should be of string type", leftPos);
            }
            if (right->cop != dbvmLoadStringConstant) { 
                error("right operand of MATCH operator should be string constant", rightPos);
            }
            dbExprNode* expr = new dbExprNode(dbvmMatchString);
            expr->regex.opd = left;
            left = expr;
            if (regcomp(&left->regex.re, (char*)right->svalue.str, REG_EXTENDED|REG_ICASE|REG_NOSUB) != 0) { 
                error("invalid regular expression", rightPos);
            }
#endif
        } 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,

⌨️ 快捷键说明

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