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

📄 compiler.cpp

📁 用于嵌入式环境的数据库
💻 CPP
📖 第 1 页 / 共 4 页
字号:
                error("operands of arithmetic operators should be of "
                      "integer or real type", leftPos);
            }
            if (right->type == tpInteger) { 
                cop = dbvmPowerRealInt;
            } else if (right->type != tpReal) { 
                    error("operands of arithmetic operator should be of "
                          "integer or real type", rightPos);
            }
            left = new dbExprNode(cop, left, right);
        } else if (left->type == tpInteger && right->type == tpInteger) { 
            left = new dbExprNode(dbvmPowerInt, left, right);
        } else { 
            error("operands of arithmentic operator should be of "
                  "integer or real type", rightPos);
        }
    }    
    return left;
}


dbExprNode* dbCompiler::userDefinedOperator() 
{ 
    dbExprNode* left = term();
    while (lex == tkn_ident) { 
        dbUserFunction* func = dbUserFunction::find(name);
        if (func != NULL) { 
            int nParams =  func->getNumberOfParameters();
            if (nParams != 2) { 
                error("Only function with two arguments can be used as operator", currPos);
            }
            int rightPos = currPos;
            dbExprNode* right = term();
            if ((left->type != tpInteger && left->type != tpReal && left->type != tpString
                 && left->type != tpReference && left->type != tpRawBinary && left->type != tpBoolean)
                || (right->type != tpInteger && right->type != tpReal && right->type != tpString
                    && right->type != tpReference && right->type != tpRawBinary && right->type != tpBoolean))
            {
                
                error("User function should receive parameter of boolean, integer, real, string, reference or user defined type", rightPos);
            } 
            left = new dbExprNode(dbvmFuncInt2Bool + func->type, func->fptr, left, right);
        } else { 
            break;
        }
    }
    return left;
}

dbExprNode* dbCompiler::field(dbExprNode* expr, dbTableDescriptor* refTable,
                              dbFieldDescriptor* fd) 
{
    int pos;

    while (true) { 
        switch (lex) {
          case tkn_dot: 
            pos = currPos;
            if (scan() != tkn_ident) { 
                error("identifier expected", pos);
            }
            if (fd != NULL && fd->type == dbField::tpStructure) { 
                if ((fd = fd->find(name)) == NULL) { 
                    error("Field not found");
                }
            } else { 
                assert(expr != NULL);
                if (expr->type != tpReference) { 
                    error("Left operand of '.' should be "
                          "structure or reference", pos);
                }
                if (refTable == NULL) { 
                    refTable = fd->refTable;
                }
                if (refTable == NULL) {
                    refTable = fd->refTable;
                }
                if (refTable == NULL || (fd = refTable->findSymbol(name)) == NULL) { 
                    error("Field not found");
                }
                refTable = NULL;
                expr = new dbExprNode(dbvmDeref, expr);
            }
            break;
          case tkn_lbr:
            if (expr == NULL || 
                (expr->type != tpArray && expr->type != tpString))
            { 
                error("Index can be applied only to arrays");
            } else { 
                dbExprNode* index = disjunction();
                if (lex != tkn_rbr) { 
                    error("']' expected");
                }
                if (index->type != tpInteger && index->type != tpFreeVar) {
                    error("Index should have integer type");
                }
                
                if (expr->type == tpString) { 
                    lex = scan();
                    return new dbExprNode(dbvmCharAt, expr, index);
                }
                if (fd == NULL) { 
                    // variable of array of reference type
                    expr = new dbExprNode(dbvmGetAt,expr,index,sizeof(oid_t));
                } else { 
                    if (refTable == NULL) { 
                        refTable = fd->refTable;
                    }
                    fd = fd->components;
                    expr = new dbExprNode(dbvmGetAt, expr, index, fd->dbsSize);
                }
            }
            break;
          default:
            if (expr == NULL) { 
                error("'.' expected");
            }
            return expr;
        }       
        if (fd == NULL) { 
            expr = new dbExprNode(dbvmLoadReference, expr, 0); 
        } else if (fd->type == dbField::tpRawBinary) {
            expr = new dbExprNode(expr != NULL ? dbvmLoadRawBinary : dbvmLoadSelfRawBinary, 
                                  fd, expr);
        } else if (fd->type != dbField::tpStructure) { 
            expr = new dbExprNode((expr != NULL 
                                   ? dbvmLoadBool : dbvmLoadSelfBool) 
                                  + fd->type, fd, expr);
        }
        lex = scan();
    }
}



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:
        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];
                    do { 
                        if (nParams == 0) { 
                            error("Too many parameters for user defined function");
                        }       
                        dbExprNode* param = expr->operand[1];
                        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[--nParams] = param;
                        expr = expr->operand[0];
                    } while (expr != NULL);

                    if (nParams != 0) { 
                        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::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_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 || prevLex == tkn_in) { 
                expr = new dbExprNode(dbvmList, list, expr);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -