compiler.cpp
来自「FastDb是高效的内存数据库系统」· C++ 代码 · 共 2,195 行 · 第 1/4 页
CPP
2,195 行
break;
default:
assert(false);
}
return field(new dbExprNode(cop, expr), NULL, NULL);
case tkn_lpar:
{
expr = disjunction();
dbExprNode* list = NULL;
while (lex == tkn_comma)
{
list = new dbExprNode(dbvmList, list, expr);
expr = disjunction();
}
if (lex != tkn_rpar)
{
error("')' expected");
}
if (list != NULL)
{
expr = new dbExprNode(dbvmList, list, expr);
}
}
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::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;
delete expr;
break;
case dbvmLength:
if (expr->operand[0]->cop == dbvmLoadSelfArray)
{
node->field = expr->operand[0]->ref.field;
node->expr = NULL;
delete 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)
{
table->db->handleError(dbDatabase::QueryError, "Conditional "
"expression should have boolean type\n", 0);
delete expr;
return false;
}
compileStartFollowPart(query);
compileOrderByPart(query);
query.tree = expr;
query.table = table;
return true;
}
else
{
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 + =
减小字号Ctrl + -
显示快捷键?