📄 compiler.cpp
字号:
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,
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')
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -