📄 compiler.cpp
字号:
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, new dbExprNode(dbvmLoadStringConstant, svalue)); } else { if (right->cop == dbvmLoadStringConstant) { char* str = right->svalue.str; char* w = findWildcard(str); if (w == NULL) { left = new dbExprNode(dbvmEqString, left, right); } else if (w == str && *w == '%' && (w = findWildcard(str+1)) != NULL && *w == '%' && *(w+1) == '\0') { memcpy(str, str+1, w-str-1); str[w-str-1] = '\0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -