📄 compiler.cpp
字号:
}
}
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)
{
if (lex != tkn_start) {
return;
}
int pos = currPos;
if (scan() != tkn_from) {
error("FROM expected after START", pos);
}
pos = currPos;
switch (scan()) {
case tkn_first:
query.startFrom = dbCompiledQuery::StartFromFirst;
break;
case tkn_last:
query.startFrom = dbCompiledQuery::StartFromLast;
break;
case tkn_var:
if (varType == dbQueryElement::qVarReference) {
if (varRefTable != table) {
error("Incompatiable type of reference variable");
}
query.startFrom = dbCompiledQuery::StartFromRef;
} else if (varType == dbQueryElement::qVarArrayOfRef) {
if (varRefTable != table) {
error("Incompatiable type of array of reference variable");
}
query.startFrom = dbCompiledQuery::StartFromArray;
} else if (varType == dbQueryElement::qVarArrayOfRefPtr) {
if (varRefTable != table) {
error("Incompatiable type of array of reference variable");
}
query.startFrom = dbCompiledQuery::StartFromArrayPtr;
} else {
error("Reference or array of reference variable expected");
}
query.root = varPtr;
break;
default:
error("FIRST, LAST or reference varaible expected", pos);
}
if ((lex = scan()) == tkn_follow) {
pos = currPos;
if (scan() != tkn_by) {
error("BY expected after FOLLOW", pos);
}
do {
pos = currPos;
if (scan() != tkn_ident) {
error("Field name expected", pos);
}
dbFieldDescriptor* fd;
if ((fd = table->findSymbol(name)) == NULL) {
error("Field not found");
}
while (fd->type == dbField::tpStructure) {
pos = currPos;
if (scan() != tkn_dot) {
error("'.' expected", pos);
}
pos = currPos;
if (scan() != tkn_ident) {
error("Field name expected", pos);
}
if ((fd = fd->find(name)) == NULL) {
error("Field not found");
}
}
if (!(fd->type == dbField::tpReference
&& fd->refTable == table) &&
!(fd->type == dbField::tpArray
&& fd->components->type == dbField::tpReference
&& fd->components->refTable == table))
{
error("Follow field should be of compatibale reference "
"or array of reference type");
}
dbFollowByNode* node = new dbFollowByNode;
node->field = fd;
node->next = query.follow; // list should be inverted
query.follow = node;
} while ((lex = scan()) == tkn_comma);
}
}
void dbCompiler::deleteNode(dbExprNode* node) {
dbMutex& mutex = dbExprNodeAllocator::instance.getMutex();
dbCriticalSection cs(mutex);
delete node;
}
void dbCompiler::compileOrderByPart(dbQuery& query)
{
if (lex == tkn_order) {
dbOrderByNode** opp = &query.order;
int pos = currPos;
if (scan() != tkn_by) {
error("BY expected after ORDER", pos);
}
int parentheses = 0;
do {
pos = currPos;
int tkn = scan();
if (tkn == tkn_lpar) {
parentheses += 1;
} else {
ungetToken(tkn);
}
dbExprNode* expr = disjunction();
dbOrderByNode* node = new dbOrderByNode;
switch (expr->cop) {
case dbvmLoadSelfBool:
case dbvmLoadSelfInt1:
case dbvmLoadSelfInt2:
case dbvmLoadSelfInt4:
case dbvmLoadSelfInt8:
case dbvmLoadSelfReal4:
case dbvmLoadSelfReal8:
case dbvmLoadSelfString:
case dbvmLoadSelfArray:
case dbvmLoadSelfReference:
case dbvmLoadSelfRawBinary:
assert(expr->ref.field != NULL);
node->field = expr->ref.field;
node->expr = NULL;
deleteNode(expr);
break;
case dbvmLength:
if (expr->operand[0]->cop == dbvmLoadSelfArray) {
node->field = expr->operand[0]->ref.field;
node->expr = NULL;
deleteNode(expr);
break;
}
// no break
default:
if (expr->type > tpReference) {
error("Expressions in ORDER BY part should have scalar type", pos);
}
node->field = NULL;
node->expr = expr;
}
node->table = table;
node->ascent = true;
*opp = node;
opp = &node->next;
*opp = NULL;
if (lex == tkn_desc) {
node->ascent = false;
lex = scan();
} else if (lex == tkn_asc) {
lex = scan();
}
if (lex == tkn_rpar) {
if (--parentheses < 0) {
error("Unbalanced parentheses ");
}
lex = scan();
}
} while (lex == tkn_comma);
}
}
dbExprNode* dbCompiler::compileExpression(dbTableDescriptor* table, char const* expr, int startPos)
{
TRACE_MSG(("Compile expression %s for table %s\n", table->name));
if (setjmp(abortCompilation) == 0) {
this->table = table;
bindings = NULL;
nFreeVars = 0;
dbQueryElement elem(dbQueryElement::qExpression, expr, NULL);
queryElement = &elem;
currPos = firstPos = 0;
offsetWithinStatement = startPos;
return disjunction();
} else {
return NULL;
}
}
bool dbCompiler::compile(dbTableDescriptor* table, dbQuery& query)
{
TRACE_MSG(("Compile query for table %s\n", table->name));
query.destroy();
if (setjmp(abortCompilation) == 0) {
this->table = table;
bindings = NULL;
nFreeVars = 0;
queryElement = query.elements;
currPos = firstPos = 0;
hasToken = false;
offsetWithinStatement = query.pos;
dbExprNode* expr = disjunction();
if (expr->type != tpBoolean && expr->type != tpVoid) {
error("Conditional expression should have boolean type\n");
}
compileStartFollowPart(query);
compileOrderByPart(query);
if (lex != tkn_eof) {
error("START, ORDER BY or LIMIT expected");
}
query.tree = expr;
query.table = table;
return true;
} else {
dbMutex& mutex = dbExprNodeAllocator::instance.getMutex();
dbCriticalSection cs(mutex);
for (dbOrderByNode *op = query.order, *nop; op != NULL; op = nop) {
nop = op->next;
delete op;
}
for (dbFollowByNode *fp = query.follow, *nfp; fp != NULL; fp = nfp) {
nfp = fp->next;
delete fp;
}
return false;
}
}
dbCompiler::dbCompiler() {
static struct {
char* name;
int tag;
} keywords[] = {
{"all", tkn_all},
{"abs", tkn_abs},
{"and", tkn_and},
{"asc", tkn_asc},
{"between", tkn_between},
{"by", tkn_by},
{"current", tkn_current},
{"desc", tkn_desc},
{"escape", tkn_escape},
{"exists", tkn_exists},
{"first", tkn_first},
{"false", tkn_false},
{"follow", tkn_follow},
{"from", tkn_from},
{"in", tkn_in},
{"is", tkn_is},
{"integer", tkn_integer},
{"insert", tkn_insert},
{"into", tkn_into},
{"last", tkn_last},
{"length", tkn_length},
{"like", tkn_like},
{"lower", tkn_lower},
{"not", tkn_not},
{"null", tkn_null},
{"or", tkn_or},
{"order", tkn_order},
{"real", tkn_real},
{"select", tkn_select},
{"start", tkn_start},
{"string", tkn_string},
{"table", tkn_table},
{"true", tkn_true},
{"upper", tkn_upper},
{"where", tkn_where}
};
if (!initialized) {
for (unsigned i = 0; i < itemsof(keywords); i++) {
dbSymbolTable::add(keywords[i].name, keywords[i].tag, FASTDB_CLONE_ANY_IDENTIFIER);
}
initialized = true;
}
}
void dbInheritedAttribute::removeTemporaries()
{
for (dbStringValue *next, *s = tempStrings; s != NULL; s = next) {
next = s->next;
delete s;
}
}
static void stderrTrace(char* msg)
{
fputs(msg, stderr);
}
dbTraceFunctionPtr dbTraceFunction = stderrTrace;
void dbTrace(char* message, ...)
{
va_list args;
va_start (args, message);
char buffer[1024];
vsprintf(buffer, message, args);
(*dbTraceFunction)(buffer);
va_end(args);
}
byte* dbMalloc(size_t size)
{
return (byte*)malloc(size);
}
void dbFree(void* p)
{
free(p);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -