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

📄 compiler.cpp

📁 实现内存数据库的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		if (right->type == tpInteger) {
		    right = int2real(right);
		} else if (right->type != tpReal) { 
		    error("operand of BETWEEN operator should be of "
			  "integer, real or string type", rightPos);
		}
		if (right2->type == tpInteger) {
		    right2 = int2real(right2);
		} else if (right2->type != tpReal) { 
		    error("operand of BETWEEN operator should be of "
			  "integer, real or string type", andPos);
		}
		left = new dbExprNode(dbvmBetweenReal, left, right, right2);
	    } 
	    else if (left->type == tpInteger && right->type == tpInteger 
		     && right2->type == tpInteger)
	    {		    
		left = new dbExprNode(dbvmBetweenInt, left, right, right2);
	    }
	    else if (left->type == tpString && right->type == tpString 
		     && right2->type == tpString)
	    {
		left = new dbExprNode(dbvmBetweenString, left, right, right2);
	    }
 	    else if (left->type == tpRawBinary && right->type == tpRawBinary
 		     && right2->type == tpRawBinary)
 	    {
 		int rawBinarySize = 0;
 		if ((left->cop == dbvmLoadSelfRawBinary || left->cop == dbvmLoadRawBinary) 
 		    && left->ref.field != NULL)
 		{
 		    rawBinarySize = left->ref.field->dbsSize;
 		} else { 
 		    error("Operations with raw binary types should include at least one record field");
 		}
		left = new dbExprNode(dbvmBetweenBinary, left, right, right2);
 		left->offs = rawBinarySize;
  	    }
	    else { 
		error("operands of BETWEEN operator should be of "
		      "integer, real or string type", rightPos);
	    }
	} else if (cop == tkn_like) {  
	    if (left->type != tpString || right->type != tpString) { 
		error("operands of LIKE operator should be of "
		      "string type", rightPos);
	    }
	    if (lex == tkn_escape) { 
		rightPos = currPos;
		if (scan() != tkn_sconst) { 
		    error("String literal espected after ESCAPE", rightPos);
		}
		lex = scan();
		left = new dbExprNode(dbvmLikeEscapeString, left, right,
			   new dbExprNode(dbvmLoadStringConstant, svalue));
	    } else { 
		left = new dbExprNode(dbvmLikeString, left, right);
	    }
	} else { 
	    if (left->type == tpReal || right->type == tpReal) { 
		if (left->type == tpInteger) { 
		    left = int2real(left);
		} else if (left->type != tpReal) { 
		    error("operands of relation operator should be of "
			  "intger, real or string type", leftPos);
		}
		if (right->type == tpInteger) { 
		    right = int2real(right);
		} else if (right->type != tpReal) { 
		    error("operands of relation operator should be of "
			  "intger, real or string type", rightPos);
		}
		left = new dbExprNode(dbvmEqReal + cop - tkn_eq, left, right);
	    } else if (left->type == tpInteger && right->type == tpInteger) { 
		left = new dbExprNode(dbvmEqInt + cop - tkn_eq, left, right);
	    } else if (left->type == tpString && right->type == tpString) { 
		left = new dbExprNode(dbvmEqString + cop-tkn_eq, left, right);
	    } else if (left->type==tpReference && right->type==tpReference) { 
		if (cop != tkn_eq && cop != tkn_ne) { 
		    error("References can be checked only for equality", 
			  rightPos);
		}
		left = new dbExprNode(dbvmEqReference+cop-tkn_eq, left, right);
	    } else if (left->type == tpBoolean && right->type == tpBoolean) { 
		if (cop != tkn_eq && cop != tkn_ne) { 
		    error("Boolean variables can be checked only for equality",
			  rightPos);
		}
		left = new dbExprNode(dbvmEqBool + cop - tkn_eq, left, right);
 	    } else if (left->type == tpRawBinary && right->type == tpRawBinary) {
 		int rawBinarySize = 0;
 		if ((left->cop == dbvmLoadSelfRawBinary || left->cop == dbvmLoadRawBinary) 
 		    && left->ref.field != NULL)
 		{
 		    rawBinarySize = left->ref.field->dbsSize;
 		} else if ((right->cop == dbvmLoadSelfRawBinary || right->cop == dbvmLoadRawBinary) 
 			   && right->ref.field != NULL)
 		{
 		    rawBinarySize = right->ref.field->dbsSize;
 		} else { 
 		    error("Operations with raw binary types should include at least one record field");
 		}
  		left = new dbExprNode(dbvmEqBinary + cop - tkn_eq, left, right, rawBinarySize);
	    } else { 
		error("operands of relation operator should be of "
		      "integer, real or string type", rightPos);
	    }
	    //
	    // Optimization for applying indices: if operation is 
	    // commuatative and left operand is constant then swap operands
	    //
	    if (IS_CONSTANT(left->operand[0]->cop)) { 
		right = left->operand[1];
		left->operand[1] = left->operand[0];
		left->operand[0] = right;
		left->cop = dbExprNode::commutativeOperator[left->cop];
	    }   
	}
	if (notOp) { 
	    left = new dbExprNode(dbvmNotBool, left);
	}
    }
    return left;
}

dbExprNode* dbCompiler::addition() 
{ 
    int leftPos = currPos;
    dbExprNode* left = multiplication();
    while (lex == tkn_add || lex == tkn_sub) { 
	int cop = lex;
	int rightPos = currPos;
	dbExprNode* right = multiplication();
	if (left->type == tpReal || right->type == tpReal) { 
	    if (left->type == tpInteger) { 
		left = int2real(left);
	    } else if (left->type != tpReal) { 
		error("operands of arithmetic operators should be of "
		      "integer or real type", leftPos);
	    }
	    if (right->type == tpInteger) { 
		right = int2real(right);
	    } else if (right->type != tpReal) { 
		error("operands of arithmetic operator should be of "
		      "integer or real type", rightPos);
	    }
	    left = new dbExprNode(cop==tkn_add ? dbvmAddReal : dbvmSubReal,
				  left, right);
	} else if (left->type == tpInteger && right->type == tpInteger) { 
	    left = new dbExprNode(cop==tkn_add ? dbvmAddInt : dbvmSubInt,
				  left, right);
	} else if (left->type == tpString && right->type == tpString) { 
	    if (cop == tkn_add) { 
		left = new dbExprNode(dbvmStringConcat, left, right);
	    } else { 
		error("Operation - is not defined for strings", rightPos);
	    }
	} else { 
	    error("operands of arithmentic operator should be of "
		  "integer or real type", rightPos);
	}
	leftPos = rightPos;
    }
    return left;
}


dbExprNode* dbCompiler::multiplication() 
{ 
    int leftPos = currPos;
    dbExprNode* left = power();
    while (lex == tkn_mul || lex == tkn_div) { 
	int cop = lex;
	int rightPos = currPos;
	dbExprNode* right = power();
	if (left->type == tpReal || right->type == tpReal) { 
	    if (left->type == tpInteger) { 
		left = int2real(left);
	    } else if (left->type != tpReal) { 
		error("operands of arithmetic operators should be of "
		      "integer or real type", leftPos);
	    }
	    if (right->type == tpInteger) { 
		right = int2real(right);
	    } else if (right->type != tpReal) { 
		    error("operands of arithmetic operator should be of "
			  "integer or real type", rightPos);
	    }
	    left = new dbExprNode(cop==tkn_mul ? dbvmMulReal : dbvmDivReal,
				  left, right);
	} else if (left->type == tpInteger && right->type == tpInteger) { 
	    left = new dbExprNode(cop==tkn_mul ? dbvmMulInt : dbvmDivInt,
				  left, right);
	} else { 
	    error("operands of arithmentic operator should be of "
		  "integer or real type", rightPos);
	}
	leftPos = rightPos;
    }
    return left;
}

dbExprNode* dbCompiler::power() 
{ 
    int leftPos = currPos;
    dbExprNode* left = userDefinedOperator();
    if (lex == tkn_power) { 
	int rightPos = currPos;
	dbExprNode* right = power();
	if (left->type == tpReal || right->type == tpReal) { 
	    int cop = dbvmPowerReal;
	    if (left->type == tpInteger) { 
		left = int2real(left);
	    } else if (left->type != tpReal) { 
		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 ((fd = refTable->find(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 { 
		    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;
    dbBinding* bp;
    dbExprNode* expr = NULL;
    dbUserFunction* func;

    if ((cop = scan()) == tkn_where) { 
	if (firstPos == 0) { 
	    firstPos = currPos;
	}
	cop = scan(); // just ignore 'where' keyword
    }

    switch (cop) { 
      case tkn_eof:
      case tkn_order:
      case tkn_start:
	lex = cop;
	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->find(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;

⌨️ 快捷键说明

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