compiler.cpp
来自「FastDb是高效的内存数据库系统」· C++ 代码 · 共 2,195 行 · 第 1/4 页
CPP
2,195 行
}
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)
{
error("operands of arithmetic operators should be of "
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?