⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compiler.cpp

📁 用于嵌入式环境的数据库
💻 CPP
📖 第 1 页 / 共 4 页
字号:
            }
        }
        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 + -