📄 compiler.cpp
字号:
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_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_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(); 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){ dbOrderByNode** opp = &query.order; if (lex == tkn_order) { int pos = currPos; if (scan() != tkn_by) { error("BY expected after ORDER", pos); } int parentheses = 0; bool length = false; dbFieldDescriptor* fd; while (true) { pos = currPos; switch (scan()) { case tkn_lpar: parentheses += 1; continue; case tkn_rpar: if (--parentheses < 0) { error("Unbalanced parentheses "); } continue; case tkn_length: length = true; continue; case tkn_ident: if ((fd = table->findSymbol(name)) == NULL) { error("Field not found", pos); } while (fd->type == dbField::tpStructure) { if (scan() != tkn_dot) { error("'.' expected"); } if (scan() != tkn_ident) { error("field name expected", pos); } if ((fd = fd->find(name)) == NULL) { error("Field not found", pos); } } if (fd->type > dbField::tpReference) { if (fd->type != dbField::tpRawBinary && (fd->type != dbField::tpArray || !length)) { error("Sort key should be of scalar or string type", pos); } } else if (length && fd->type != dbField::tpString) { error("Length in ORDER BY part can be applied only to arrays or strings", pos); } dbOrderByNode* node = new dbOrderByNode; node->field = fd; node->ascent = true; node->stringLength = length; *opp = node; opp = &node->next; *opp = NULL; int tkn = scan(); while (tkn == tkn_rpar) { if (--parentheses < 0) { error("Unbalanced parentheses"); } tkn = scan(); } if (tkn == tkn_desc) { node->ascent = false; tkn = scan(); } else if (tkn == tkn_asc) { tkn = scan(); } while (tkn == tkn_rpar) { if (--parentheses < 0) { error("Unbalanced parentheses"); } tkn = scan(); } if (tkn == tkn_eof) { if (parentheses != 0) { error("Unbalanced parentheses"); } return; } else if (tkn != tkn_comma) { error("',' expected"); } } } } else if (lex != tkn_eof) { error("ORDER BY expected"); }}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; 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 < items(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; }}void dbTrace(char* message, ...) { va_list args; va_start (args, message); vfprintf(stderr, message, args); va_end(args);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -