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

📄 compiler.cpp

📁 用于嵌入式环境的数据库
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    } 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 (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) { 

⌨️ 快捷键说明

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