📄 compiler.cpp
字号:
fd, expr);
} else if (fd->type == dbField::tpRectangle) {
expr = new dbExprNode(expr != NULL ? dbvmLoadRectangle: dbvmLoadSelfRectangle,
fd, expr);
} else if (fd->type != dbField::tpStructure) {
expr = new dbExprNode((expr != NULL
? dbvmLoadBool : dbvmLoadSelfBool)
+ fd->type, fd, expr);
}
lex = scan();
}
}
dbExprNode* dbCompiler::buildList() {
dbExprNode* expr = disjunction();
return new dbExprNode(dbvmList, expr, lex == tkn_comma ? buildList() : NULL);
}
dbExprNode* dbCompiler::term()
{
dbFieldDescriptor* fd;
dbTableDescriptor* refTable;
int cop;
int pos = currPos;
int prevLex = lex;
dbBinding* bp;
dbExprNode* expr = NULL;
dbUserFunction* func;
if ((cop = scan()) == tkn_where) {
if (firstPos == 0) {
firstPos = currPos;
}
cop = scan(); // just ignore 'where' keyword
}
lex = cop;
switch (cop) {
case tkn_eof:
case tkn_order:
case tkn_start:
case tkn_limit:
return new dbExprNode(dbvmVoid);
case tkn_current:
lex = scan();
return field(new dbExprNode(dbvmCurrent), table, NULL);
case tkn_ident:
for (bp = bindings; bp != NULL; bp = bp->next) {
if (name == bp->name) {
bp->used = true;
lex = scan();
return new dbExprNode(dbvmVariable, (dbExprNode*)0, bp->index);
}
}
if ((fd = table->findSymbol(name)) == NULL) {
if ((func = dbUserFunction::find(name)) != NULL) {
pos = currPos;
expr = term();
int argType = func->getParameterType();
int nParams = func->getNumberOfParameters();
if (nParams > 1) {
if (expr->type != tpList) {
error("Too few paramters for user defined function");
}
dbExprNode* params[3];
int n = 0;
do {
if (n == nParams) {
error("Too many parameters for user defined function");
}
dbExprNode* param = expr->operand[0];
if (param->type != tpInteger && param->type != tpReal && param->type != tpString
&& param->type != tpReference && param->type != tpRawBinary && param->type != tpBoolean)
{
error("User function should receive parameters of boolean, integer, real, string, reference or user defined type", pos);
}
params[n++] = param;
expr = expr->operand[1];
} while (expr != NULL);
if (n != nParams) {
error("Too few parameters for user defined function");
}
expr = new dbExprNode(dbvmFuncInt2Bool + func->type, func->fptr, params[0], params[1], params[2]);
} else {
if (argType == tpReal && expr->type == tpInteger) {
expr = int2real(expr);
} else if (argType == tpList) {
if (expr->type != tpInteger && expr->type != tpReal && expr->type != tpString
&& expr->type != tpReference && expr->type != tpRawBinary && expr->type != tpBoolean)
{
error("User function should receive parameter of boolean, integer, real, string, reference or user defined type", pos);
}
} else if (argType != expr->type) {
error("Incompatible function argument", pos);
}
expr = new dbExprNode(dbvmFuncInt2Bool + func->type, func->fptr, expr);
}
return field(expr, NULL, NULL);
}
error("Field not found", pos);
}
if (fd->type == dbField::tpRawBinary) {
expr = new dbExprNode(dbvmLoadSelfRawBinary, fd);
} else if (fd->type == dbField::tpRectangle) {
expr = new dbExprNode(dbvmLoadSelfRectangle, fd);
} else if (fd->type != dbField::tpStructure) {
expr = new dbExprNode(dbvmLoadSelfBool + fd->type, fd);
}
lex = scan();
return field(expr, NULL, fd);
case tkn_exists:
if (scan() == tkn_ident) {
dbBinding var;
var.next = bindings;
var.name = name;
var.used = false;
var.index = nFreeVars++;
bindings = &var;
if (nFreeVars >= maxFreeVars) {
error("Too many nested EXISTS clauses\n");
}
pos = currPos;
if (scan() != tkn_col) {
error("':' expected", pos);
}
expr = term();
if (expr->type != tpBoolean) {
error("Expresion in EXISTS clause should be of boolean type");
}
if (var.used) {
expr = new dbExprNode(dbvmExists, expr, nFreeVars-1);
}
nFreeVars -= 1;
assert(bindings == &var);
bindings = var.next;
return expr;
} else {
error("Free variable name expected");
}
break;
case tkn_first:
lex = scan();
return field(new dbExprNode(dbvmFirst), table, NULL);
case tkn_last:
lex = scan();
return field(new dbExprNode(dbvmLast), table, NULL);
case tkn_false:
expr = new dbExprNode(dbvmLoadFalse);
break;
case tkn_true:
expr = new dbExprNode(dbvmLoadTrue);
break;
case tkn_null:
expr = new dbExprNode(dbvmLoadNull);
break;
case tkn_iconst:
expr = new dbExprNode(dbvmLoadIntConstant, ivalue);
break;
case tkn_fconst:
expr = new dbExprNode(dbvmLoadRealConstant, fvalue);
break;
case tkn_sconst:
expr = new dbExprNode(dbvmLoadStringConstant, svalue);
lex = scan();
return field(expr, NULL, NULL);
case tkn_var:
expr = new dbExprNode(dbvmLoadVarBool + varType -
dbQueryElement::qVarBool, varPtr);
refTable = varRefTable;
lex = scan();
return field(expr, refTable, NULL);
case tkn_abs:
case tkn_area:
case tkn_length:
case tkn_lower:
case tkn_upper:
case tkn_integer:
case tkn_real:
case tkn_string:
pos = currPos;
expr = term();
switch (cop) {
case tkn_abs:
if (expr->type == tpInteger) {
cop = dbvmAbsInt;
} else if (expr->type == tpReal) {
cop = dbvmAbsReal;
} else {
error("ABS function can be applied only "
"to integer or real expression", pos);
}
break;
case tkn_area:
if (expr->type == tpRectangle) {
cop = dbvmRectangleArea;
} else if (expr->type == tpList) {
expr = rectangleConstant(expr);
cop = dbvmRectangleArea;
} else {
error("AREA function can be applied only to rectangles", pos);
}
break;
case tkn_length:
if (expr->type == tpArray) {
cop = dbvmLength;
} else if (expr->type == tpString) {
cop = dbvmStringLength;
} else {
error("LENGTH function is defined only for arrays and strings",
pos);
}
break;
case tkn_integer:
if (expr->type == tpReal) {
cop = dbvmRealToInt;
} else {
error("INTEGER function can be applied only to "
"expression of real type", pos);
}
break;
case tkn_real:
if (expr->type == tpInteger) {
cop = dbvmIntToReal;
} else {
error("REAL function can be applied only to "
"expression of integer type", pos);
}
break;
case tkn_string:
if (expr->type == tpInteger) {
cop = dbvmIntToString;
} else if (expr->type == tpReal) {
cop = dbvmRealToString;
} else {
error("STRING function can be applied only "
"to integer or real expression", pos);
}
break;
case tkn_lower:
if (expr->type != tpString) {
error("LOWER function can be applied only to string argument",
pos);
} else {
cop = dbvmLowerString;
}
break;
case tkn_upper:
if (expr->type != tpString) {
error("UPPER function can be applied only to string argument",
pos);
} else {
cop = dbvmUpperString;
}
break;
default:
assert(false);
}
return field(new dbExprNode(cop, expr), NULL, NULL);
case tkn_lpar:
{
expr = disjunction();
if (lex == tkn_comma) {
expr = new dbExprNode(dbvmList, expr, buildList());
} else if (prevLex == tkn_in) {
expr = new dbExprNode(dbvmList, expr);
}
if (lex != tkn_rpar) {
error("')' expected");
}
}
break;
case tkn_not:
pos = currPos;
expr = comparison();
if (expr->type == tpInteger) {
if (expr->cop == dbvmLoadIntConstant) {
expr->ivalue = ~expr->ivalue;
} else {
expr = new dbExprNode(dbvmNotInt, expr);
}
return expr;
} else if (expr->type == tpBoolean) {
return new dbExprNode(dbvmNotBool, expr);
} else {
error("NOT operator can be applied only to "
"integer or boolean expressions", pos);
}
break;
case tkn_add:
error("Using of unary plus operator has no sence");
break;
case tkn_sub:
pos = currPos;
expr = term();
if (expr->type == tpInteger) {
if (expr->cop == dbvmLoadIntConstant) {
expr->ivalue = -expr->ivalue;
} else {
expr = new dbExprNode(dbvmNegInt, expr);
}
return expr;
} else if (expr->type == tpReal) {
if (expr->cop == dbvmLoadRealConstant) {
expr->fvalue = -expr->fvalue;
} else {
expr = new dbExprNode(dbvmNegReal, expr);
}
return expr;
} else {
error("Unary minus can be applied only to "
"integer or real expressions", pos);
}
default:
error("operand expected");
}
lex = scan();
return expr;
}
void dbCompiler::error(const char* msg, int pos)
{
if (pos < 0) {
if ((pos = currPos-1) < 0) {
pos = 0;
}
} else if (pos < firstPos) {
pos = firstPos;
}
if (pos + offsetWithinStatement >= 0) {
pos += offsetWithinStatement;
}
table->db->handleError(dbDatabase::QueryError, msg, pos);
longjmp(abortCompilation, dbDatabase::QueryError);
}
void dbCompiler::compileStartFollowPart(dbQuery& query)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -