Exemple #1
0
TToken ASNLexer::LookupToken(void)
{
    char c = Char();
    switch ( c ) {
    case ':':
        if ( Char(1) == ':' && Char(2) == '=' ) {
            StartToken();
            AddChars(3);
            return T_DEFINE;
        }
        return T_SYMBOL;
    case '-':
    case '+':
        if ( IsDigit(Char(1)) ) {
            StartToken();
            AddChar();
            return LookupNumber();
        }
        return T_SYMBOL;
    case '\"':
        StartToken();
        AddChar();
        StartString();
        LookupString();
        return T_STRING;
    case '\'':
        StartToken();
        AddChar();
        return LookupBinHexString();
    case '[':
        StartToken();
        AddChar();
        LookupTag();
        return T_TAG;
    default:
        if ( IsDigit(c) ) {
            StartToken();
            AddChar();
            return LookupNumber();
        }
        else if ( c >= 'a' && c <= 'z' ) {
            StartToken();
            AddChar();
            LookupIdentifier();
            return T_IDENTIFIER;
        }
        else if ( c >= 'A' && c <= 'Z' ) {
            StartToken();
            AddChar();
            LookupIdentifier();
            return LookupKeyword();
        }
        return T_SYMBOL;
    }
}
FieldDecl *Sema::ActOnDerivedTypeFieldDecl(ASTContext &C, DeclSpec &DS, SourceLocation IDLoc,
                                           const IdentifierInfo *IDInfo,
                                           ExprResult Init) {
  QualType T = ActOnTypeName(C, DS);
  if(auto ArrTy = T->asArrayType()) {
    // FIXME: check deferred shape when pointer is used.
    for(auto Dim : ArrTy->getDimensions()) {
      if(!isa<ExplicitShapeSpec>(Dim)) {
        Diags.Report(IDLoc, diag::err_invalid_type_field_array_shape);
        break;
      }
    }
  } else if(auto RecordTy = T->asRecordType()) {
    if(cast<RecordDecl>(CurContext)->isSequence()) {
      auto Record = RecordTy->getElement(0)->getParent();
      if(!Record->isSequence()) {
        Diags.Report(IDLoc, diag::err_record_member_not_sequence)
          << IDInfo << T;
      }
    }
  }

  FieldDecl* Field = FieldDecl::Create(C, CurContext, IDLoc, IDInfo, T);

  if (auto Prev = LookupIdentifier(IDInfo)) {
    Diags.Report(IDLoc, diag::err_duplicate_member) << IDInfo;
    Diags.Report(Prev->getLocation(), diag::note_previous_declaration);
  } else
    CurContext->addDecl(Field);

  return Field;
}
Decl *Sema::ActOnIntrinsicEntityDecl(ASTContext &C, QualType T,
                                     SourceLocation IDLoc, const IdentifierInfo *IDInfo) {
  auto FuncResult = IntrinsicFunctionMapping.Resolve(IDInfo);
  if(FuncResult.IsInvalid) {
    Diags.Report(IDLoc, diag::err_intrinsic_invalid_func)
      << IDInfo << getTokenRange(IDLoc);
    return nullptr;
  }

  QualType Type = T.isNull()? C.RealTy : T;
  if (auto Prev = LookupIdentifier(IDInfo)) {
    auto Quals = getDeclQualifiers(Prev);
    if(Quals.hasAttributeSpec(Qualifiers::AS_intrinsic)) {
      Diags.Report(IDLoc, diag::err_duplicate_attr_spec)
        << DeclSpec::getSpecifierName(Qualifiers::AS_intrinsic);
      return Prev;
    }

    auto VD = dyn_cast<VarDecl>(Prev);
    if(VD && VD->isUnusedSymbol()) {
      Type = VD->getType();
      CurContext->removeDecl(VD);
    } else {
      DiagnoseRedefinition(IDLoc, IDInfo, Prev);
      return nullptr;
    }
  }

  auto Decl = IntrinsicFunctionDecl::Create(C, CurContext, IDLoc, IDInfo,
                                            Type, FuncResult.Function);
  CurContext->addDecl(Decl);
  return Decl;
}
bool Sema::CheckDeclaration(const IdentifierInfo *IDInfo, SourceLocation IDLoc) {
  if(!IDInfo) return false;
  if (auto Prev = LookupIdentifier(IDInfo)) {
    DiagnoseRedefinition(IDLoc, IDInfo, Prev);
    return false;
  }
  return true;
}
Decl *Sema::ActOnEntityDecl(ASTContext &C, const QualType &T,
                            SourceLocation IDLoc, const IdentifierInfo *IDInfo) {
  auto Quals = T.getQualifiers();

  if(Quals.hasAttributeSpec(Qualifiers::AS_external))
    return ActOnExternalEntityDecl(C, T, IDLoc, IDInfo);
  else if(Quals.hasAttributeSpec(Qualifiers::AS_intrinsic))
    return ActOnIntrinsicEntityDecl(C, T, IDLoc, IDInfo);

  if (auto Prev = LookupIdentifier(IDInfo)) {
    FunctionDecl *FD = dyn_cast<FunctionDecl>(Prev);
    if(auto VD = dyn_cast<VarDecl>(Prev)) {
      if(VD->isArgument() && VD->getType().isNull()) {
        VD->setType(T);
        return VD;
      } else if(VD->isFunctionResult())
         FD = CurrentContextAsFunction();
    }

    if(FD && (FD->isNormalFunction() || FD->isExternal())) {
      if(FD->getType().isNull() || FD->getType()->isVoidType()) {
        SetFunctionType(FD, T, IDLoc, SourceRange()); //Fixme: proper loc and range
        return FD;
      } else {
        Diags.Report(IDLoc, diag::err_func_return_type_already_specified) << IDInfo;
        return nullptr;
      }
    }
    Diags.Report(IDLoc, diag::err_redefinition) << IDInfo;
    Diags.Report(Prev->getLocation(), diag::note_previous_definition);
    return nullptr;
  }

  VarDecl *VD = VarDecl::Create(C, CurContext, IDLoc, IDInfo, T);
  CurContext->addDecl(VD);

  if(!T.isNull()) {
    auto SubT = T;
    if(T->isArrayType()) {
      CheckArrayTypeDeclarationCompability(T->asArrayType(), VD);
      SubT = T->asArrayType()->getElementType();
      VD->MarkUsedAsVariable(IDLoc);
    }
    else if(SubT->isCharacterType())
      CheckCharacterLengthDeclarationCompability(SubT, VD);
  }

  return VD;
}
// FIXME:
Decl *Sema::ActOnParameterEntityDecl(ASTContext &C, QualType T,
                                     SourceLocation IDLoc, const IdentifierInfo *IDInfo,
                                     SourceLocation EqualLoc, ExprResult Value) {
  VarDecl *VD = nullptr;

  if (auto Prev = LookupIdentifier(IDInfo)) {
    VD = dyn_cast<VarDecl>(Prev);
    if(!VD || VD->isParameter() || VD->isArgument() ||
       VD->isFunctionResult()) {
      DiagnoseRedefinition(IDLoc, IDInfo, Prev);
      return nullptr;
    }
  }

  // Make sure the value is a constant expression.
  if(!Value.get()->isEvaluatable(C)) {
    llvm::SmallVector<const Expr*, 16> Results;
    Value.get()->GatherNonEvaluatableExpressions(C, Results);
    Diags.Report(IDLoc, diag::err_parameter_requires_const_init)
        << IDInfo << Value.get()->getSourceRange();
    for(auto E : Results) {
      Diags.Report(E->getLocation(), diag::note_parameter_value_invalid_expr)
          << E->getSourceRange();
    }
    return nullptr;
  }

  if(VD) {
    Value = CheckAndApplyAssignmentConstraints(EqualLoc,
                                               VD->getType(), Value.get(),
                                               Sema::AssignmentAction::Initializing);
    if(Value.isInvalid()) return nullptr;
    // FIXME: if value is invalid, mutate into parameter givin a zero value
    VD->MutateIntoParameter(Value.get());
  } else {
    QualType T = Value.get()->getType();
    VD = VarDecl::Create(C, CurContext, IDLoc, IDInfo, T);
    VD->MutateIntoParameter(Value.get());
    CurContext->addDecl(VD);
  }
  return VD;
}
Decl *Sema::ActOnExternalEntityDecl(ASTContext &C, QualType T,
                                    SourceLocation IDLoc, const IdentifierInfo *IDInfo) {
  SourceLocation TypeLoc;
  VarDecl *ArgumentExternal = nullptr;
  if (auto Prev = LookupIdentifier(IDInfo)) {
    auto Quals = getDeclQualifiers(Prev);
    if(Quals.hasAttributeSpec(Qualifiers::AS_external)) {
      Diags.Report(IDLoc, diag::err_duplicate_attr_spec)
        << DeclSpec::getSpecifierName(Qualifiers::AS_external);
      return Prev;
    }

    // apply EXTERNAL to an unused symbol or an argument.
    auto VD = dyn_cast<VarDecl>(Prev);
    if(VD && (VD->isUnusedSymbol() || VD->isArgument()) ) {
      T = VD->getType();
      TypeLoc = VD->getLocation();
      CurContext->removeDecl(VD);
      if(VD->isArgument())
        ArgumentExternal = VD;
    } else {
      DiagnoseRedefinition(IDLoc, IDInfo, Prev);
      return nullptr;
    }
  }
  if(T.isNull())
    T = C.VoidTy;

  DeclarationNameInfo DeclName(IDInfo,IDLoc);
  auto Decl = FunctionDecl::Create(C, ArgumentExternal? FunctionDecl::ExternalArgument :
                                                        FunctionDecl::External,
                                   CurContext, DeclName, T);
  SetFunctionType(Decl, T, TypeLoc, SourceRange()); //FIXME: proper loc, and range
  CurContext->addDecl(Decl);
  if(ArgumentExternal)
    ArgumentExternal->setType(C.getFunctionType(Decl));
  return Decl;
}
// Do Tree:  convert token stream to expression tree
ExpPart* CExpression::DoTree(int& step, bool unaryMode)
{
	ExpPart* LeftPart = NULL;
	ExpPart* Brackets = NULL;
	bool Bracketing; // Brackets override the operator precedentation

	// Too lazy to scope each case label lol
	ExpInteger* pInt;
	ExpFloat* pFloat;
	ExpString* pStr;
	ExpIdent* pIdent;
	ExpAdd* pAdd;
	ExpSubtract* pSub;
	ExpMultiply* pMult;
	ExpDivide* pDiv;
	ExpMod* pMod;
	ExpPower* pPow;
	ExpDot* pDot;
	ExpSin* pSin;
	ExpCos* pCos;
	ExpTan* pTan;
	ExpSqrt* pSqrt;
	ExpFuncInt* pFuncInt;
	ExpFuncFloat* pFuncFloat;
	ExpFuncStr* pFuncStr;
	ExpEqual* pEqual;
	ExpNotEqual* pNotEqual;
	ExpLess* pLess;
	ExpLessEqual* pLessEqual;
	ExpGreater* pGreater;
	ExpGreaterEqual* pGreaterEqual;
	ExpAnd* pAnd;
	ExpOr* pOr;
	ExpConditional* pConditional;
	ExpAsin* pAsin;
	ExpAcos* pAcos;
	ExpAtan* pAtan;
	ExpAbs* pAbs;
	ExpExp* pExp;
	ExpLn* pLn;
	ExpLog10* pLog10;
	ExpCeil* pCeil;
	ExpRound* pRound;
	ExpRandom* pRandom;
	ExpLen* pLen;
	ExpArray* pArray;
	ExpAt* pAt;
	ExpVariableName* pVariableName;
	bool dotIdentifier;

	while (step < toks.size()) {

		const Token& curTok = toks[step];

		if (curTok.t == T_NULL)
			break;

		Bracketing = false;

		switch (curTok.t) {

			//////////////////////
			// Operands
			//
			// Operands are simply kept to one side until we find an
			// operator to do something with.

		case T_INTEGER:
			
			pInt = NEW_UNARY_EXP(ExpInteger, pInt);
			pInt->value = curTok.iValue;

			// Return on close bracket or comma
			CHECK_TERMINATE();

			break;

		case T_FLOAT:

			pFloat = NEW_UNARY_EXP(ExpFloat, pFloat);
			pFloat->value = curTok.fValue;

			// Return on close bracket or comma
			CHECK_TERMINATE();

			break;

		case T_STRINGLITERAL:

			pStr = NEW_UNARY_EXP(ExpString, pStr);
			pStr->value = curTok.str;

			// Return on close bracket or comma
			CHECK_TERMINATE();

			break;

		case T_VARIABLENAME:
			{

			pVariableName = NEW_UNARY_EXP(ExpVariableName, pVariableName);

			CString name = curTok.str;
			name.MakeLower();

			// Lookup the private variable index
			if (pExpressionOwner != NULL)
				pVariableName->index = find_index(pExpressionOwner->privateVars.begin(), pExpressionOwner->privateVars.end(), name);
			else {
				vector<CString>::iterator it = pRuntime->globalNames.begin();
				vector<CString>::iterator end = pRuntime->globalNames.end();

				for ( ; it != end; it++) {
					CString curName = *it;
					curName.MakeLower();

					if (curName == name) {
						pVariableName->index = it - pRuntime->globalNames.begin();
						break;
					}
				}
			}

			pVariableName->pOwnerType = pExpressionOwner;
			
			// Return on close bracket or comma
			CHECK_TERMINATE();

			break;
			}

		case T_LEFTCURLY:

			pArray = NEW_UNARY_EXP(ExpArray, pArray);

			// NEW_UNARY_EXP increments step, but we want to put it back, because the loop
			// below expects to start on {
			step--;

			// Loop until all elements collected
			while (toks[step].t != T_RIGHTCURLY && step < toks.size()) {

				step++;		// Step over { or ,

				// Obtain element
				ExpPart* element = DoTree(step);

				// Add to elements
				pArray->expElements.push_back(element);

			}

			// Step over }
			step++;

			// Resize the evaluation buffer
			pArray->arr.resize(pArray->expElements.size());

			CHECK_TERMINATE();

			break;


			//////////////////////
			// Operators

		case T_ADD:
			
			pAdd = NEW_BINARY_EXP(ExpAdd, pAdd);

			// If child operator is lower precedence, this node must swap places with the child
			if (HasPrecedence(pAdd, pAdd->r))
				return SwapTree(pAdd);

			return pAdd;

		case T_SUBTRACT:

			pSub = NEW_BINARY_EXP(ExpSubtract, pSub);

			if (HasPrecedence(pSub, pSub->r))
				return SwapTree(pSub);

			return pSub;

		case T_MULTIPLY:

			pMult = NEW_BINARY_EXP(ExpMultiply, pMult);

			if (HasPrecedence(pMult, pMult->r))
				return SwapTree(pMult);

			return pMult;

		case T_DIVIDE:

			pDiv = NEW_BINARY_EXP(ExpDivide, pDiv);

			if (HasPrecedence(pDiv, pDiv->r) || SamePrecedence(pDiv, pDiv->r))
				return SwapTree(pDiv);
			
			// Force left-to-right evaluation
			/*
			if (SamePrecedence(pDiv, pDiv->r))
				SwapRightToLeft(pDiv);
			*/

			return pDiv;

		case T_MOD:

			pMod = NEW_BINARY_EXP(ExpMod, pMod);

			if (HasPrecedence(pMod, pMod->r))
				return SwapTree(pMod);

			// Force left-to-right evaluation
			if (SamePrecedence(pMod, pMod->r))
				SwapRightToLeft(pMod);

			return pMod;

		case T_POWER:

			pPow = NEW_BINARY_EXP(ExpPower, pPow);

			if (HasPrecedence(pPow, pPow->r))
				return SwapTree(pPow);

			// Force left-to-right evaluation
			if (SamePrecedence(pPow, pPow->r))
				SwapRightToLeft(pPow);

			return pPow;

		case T_AT:

			pAt = NEW_BINARY_EXP(ExpAt, pAt);

			if (HasPrecedence(pAt, pAt->r))
				return SwapTree(pAt);

			// Force left-to-right evaluation
			if (SamePrecedence(pAt, pAt->r))
				SwapRightToLeft(pAt);

			return pAt;

		case T_EQUAL:

			pEqual = NEW_BINARY_EXP(ExpEqual, pEqual);

			if (HasPrecedence(pEqual, pEqual->r))
				return SwapTree(pEqual);

			return pEqual;

		case T_NOTEQUAL:

			pNotEqual = NEW_BINARY_EXP(ExpNotEqual, pNotEqual);

			if (HasPrecedence(pNotEqual, pNotEqual->r))
				return SwapTree(pNotEqual);

			return pNotEqual;

		case T_LESS:

			pLess = NEW_BINARY_EXP(ExpLess, pLess);

			if (HasPrecedence(pLess, pLess->r))
				return SwapTree(pLess);

			return pLess;

		case T_LESSEQUAL:

			pLessEqual = NEW_BINARY_EXP(ExpLessEqual, pLessEqual);

			if (HasPrecedence(pLessEqual, pLessEqual->r))
				return SwapTree(pLessEqual);

			return pLessEqual;

		case T_GREATER:

			pGreater = NEW_BINARY_EXP(ExpGreater, pGreater);

			if (HasPrecedence(pGreater, pGreater->r))
				return SwapTree(pGreater);

			return pGreater;

		case T_GREATEREQUAL:

			pGreaterEqual = NEW_BINARY_EXP(ExpGreaterEqual, pGreaterEqual);

			if (HasPrecedence(pGreaterEqual, pGreaterEqual->r))
				return SwapTree(pGreaterEqual);

			return pGreaterEqual;

		case T_AND:

			pAnd = NEW_BINARY_EXP(ExpAnd, pAnd);

			if (HasPrecedence(pAnd, pAnd->r))
				return SwapTree(pAnd);

			return pAnd;

		case T_OR:

			pOr = NEW_BINARY_EXP(ExpOr, pOr);

			if (HasPrecedence(pOr, pOr->r))
				return SwapTree(pOr);

			return pOr;

		case T_CONDITIONAL:

			// a ? b : c
			pConditional = new ExpConditional;
			pConditional->t = T_CONDITIONAL;
			pConditional->pCExp = this;
			pConditional->bracketdepth = Depth;
			pConditional->a = LeftPart;	// Get condition part (a)
			step++;

			// Get TRUE part (b)
			/*if (toks[step].t == T_LEFTBRACKET)
				pConditional->b = DoBrackets(step);
			else*/
				pConditional->b = DoTree(step);
				pConditional->b = PostSortTree(pConditional->b);

			// Step over colon
			step++;

			// Get FALSE part (c)
			/*if (toks[step].t == T_LEFTBRACKET)
				pConditional->c = DoBrackets(step);
			else*/
				pConditional->c = DoTree(step);
				pConditional->c = PostSortTree(pConditional->c);

			// (never has precedence)

			return pConditional;

			// Identifier, eg. call without a dot: Object Object(5) MouseX
		case T_IDENTIFIER:
			{

			// Idents cause variability
			isConstant = false;

			pIdent = NEW_UNARY_EXP(ExpIdent, pIdent);
			pIdent->ident = curTok.str;
			pIdent->pRuntime = pRuntime;
			pIdent->pSystemObject = &(pRuntime->system);
			pIdent->numParams = 0;
			pIdent->paramsEnd = pIdent->parameters;

			for (int x = 0; x < CRUNTIME_MAX_PARAMS; x++)
				pIdent->expParamList[x].eType = EXPTYPE_NULL;

			// This will store the correct OID for this name, else -1 and load an expression routine
			LookupIdentifier(curTok.str, pIdent);

			// Check for OID caller match
			pIdent->isCallerOid = (pIdent->oid == this->oidCaller);

			// True if dot precedes this identifier (bit of a hack, but hey)
			// We can't check for unary mode, because unary operators use it and it would break "sin Array(1)"
			dotIdentifier = false;
			if (step > 1) if (toks[step-2].t == T_DOT) dotIdentifier = true;

			// Save expression owner for variable name translation.  Don't change the owner type if
			// this identifier is an expression name.
			if (!dotIdentifier) {
				if (pIdent->oid == -1)
					pExpressionOwner = NULL;
				else
					pExpressionOwner = pRuntime->objects[pIdent->oid];
			}

			// Cursor is currently on token after identifier (NEW_UNARY_EXP increments).
			// Check for left bracket & parameters if not part of a dot identifier (ie the x of object.x)
			if (step < toks.size() && !dotIdentifier) if (toks[step].t == T_LEFTBRACKET) {

				// While we're not on the closing bracket
				while (toks[step].t != T_RIGHTBRACKET && step < toks.size()) {

					// Step over left bracket/comma
					step++;

					// Obtain this parameter's tree, closing on the comma
					ExpPart* param = DoTree(step);
					param = PostSortTree(param);

					pIdent->parameters[pIdent->numParams++] = param;
					pIdent->paramsEnd = pIdent->parameters + pIdent->numParams;
				}

				// Step over right bracket
				step++;
			}

			// Now we have params parsed, but if this isn't a system expression, there isn't yet a routine stored for it.
			// This means it is the default return format, eg. Array(5).  Use the Default Return Value address.
			if (pIdent->oid > -1) {
				pIdent->pType = pRuntime->pOid(pIdent->oid);
				pIdent->pTypeInstances = &(pIdent->pType->instances);
				pIdent->routine = &CRunObject::ReturnDefaultValue;
			}
			else
				pIdent->pType = NULL;

			pIdent->hasParameters = pIdent->numParams > 0;

			// Return on close bracket or comma
			CHECK_TERMINATE();

			// Return if function call (followed by lbracket)
			if (toks[step].t == T_LEFTBRACKET)
				return LeftPart;

			break;
			}

		case T_DOT:

			// Plugin returns cause variability
			isConstant = false;

			pDot = new ExpDot;
			pDot->t = T_DOT;
			// Object name part
			pDot->l = (ExpIdent*)LeftPart;
			pDot->pCExp = this;
			pDot->pRuntime = pRuntime;
			pDot->bracketdepth = Depth;
			pDot->oid = ((ExpIdent*)(pDot->l))->oid;
			pDot->pType = pRuntime->objects[pDot->oid];
			pDot->pTypeInstances = &(pDot->pType->instances);
			pDot->unnamedExp = false;
			pDot->numParams = 0;
			pDot->paramsEnd = pDot->parameters;

			// Save owner type for variable name translation
			pExpressionOwner = pDot->pType;

			for (int x = 0; x < CRUNTIME_MAX_PARAMS; x++)
				pDot->expParamList[x].eType = EXPTYPE_NULL;

			step++;

			// Check for OID match
			pDot->isCallerOid = (pDot->oid == this->oidCaller);
				
			// Brackets not allowed after dot.  Obtain expression name part.
			pDot->r = (ExpIdent*)DoTree(step, true);

			// Now obtain a list of the parameters.  We are pointing after the expression
			// name part, i.e. after:   obj.exp [->] ( params ...
			// So if parameters exist, this is a left bracket.
			if (step < toks.size()) if (toks[step].t == T_LEFTBRACKET) {

				// While we're not on the closing bracket
				while (toks[step].t != T_RIGHTBRACKET && step < toks.size()) {

					// Step over left bracket/comma
					step++;

					// Obtain this parameter's tree, closing on the comma
					ExpPart* param = DoTree(step);
					param = PostSortTree(param);
					pDot->parameters[pDot->numParams++] = param;
					pDot->paramsEnd = pDot->parameters + pDot->numParams;
				}

				// Step over right bracket
				step++;
			}

			// Has parameters?
			pDot->hasParameters = pDot->numParams > 0;

			// Dot will have precedence over most operators
			if (HasPrecedence(pDot, pDot->r)) {

				ExpPart* newParent = SwapTree(pDot);

				// Look up the plugin expression routine
				LookupPluginExpression(((ExpIdent*)(pDot->l))->oid, ((ExpIdent*)(pDot->r))->ident, pDot);

				return newParent;
			}

			// Look up the plugin expression routine
			LookupPluginExpression(((ExpIdent*)(pDot->l))->oid, ((ExpIdent*)(pDot->r))->ident, pDot);

			//return pDot;
			LeftPart = pDot;

			CHECK_TERMINATE();

			break;

			//////////////////////
			// Unary operators

		case T_SIN:

			pSin = NEW_UNARY_OPERATOR(ExpSin, pSin);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_COS:

			pCos = NEW_UNARY_OPERATOR(ExpCos, pCos);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_TAN:

			pTan = NEW_UNARY_OPERATOR(ExpTan, pTan);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_SQRT:

			pSqrt = NEW_UNARY_OPERATOR(ExpSqrt, pSqrt);

			// Return on close bracket
			/*
			if (step >= toks.size())
				return LeftPart;
			if (toks[step].t == T_RIGHTBRACKET)
				return LeftPart;
				*/
			CHECK_TERMINATE();

			break;

		case T_FUNC_INT:

			pFuncInt = NEW_UNARY_OPERATOR(ExpFuncInt, pFuncInt);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_FUNC_FLOAT:

			pFuncFloat = NEW_UNARY_OPERATOR(ExpFuncFloat, pFuncFloat);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_FUNC_STR:

			pFuncStr = NEW_UNARY_OPERATOR(ExpFuncStr, pFuncStr);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_ASIN:

			pAsin = NEW_UNARY_OPERATOR(ExpAsin, pAsin);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_ACOS:

			pAcos = NEW_UNARY_OPERATOR(ExpAcos, pAcos);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_ATAN:

			pAtan = NEW_UNARY_OPERATOR(ExpAtan, pAtan);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_ABS:

			pAbs = NEW_UNARY_OPERATOR(ExpAbs, pAbs);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_EXP:

			pExp = NEW_UNARY_OPERATOR(ExpExp, pExp);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_LN:

			pLn = NEW_UNARY_OPERATOR(ExpLn, pLn);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_LOG10:

			pLog10 = NEW_UNARY_OPERATOR(ExpLog10, pLog10);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_CEIL:

			pCeil = NEW_UNARY_OPERATOR(ExpCeil, pCeil);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_ROUND:

			pRound = NEW_UNARY_OPERATOR(ExpRound, pRound);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_RANDOM:

			pRandom = NEW_UNARY_OPERATOR(ExpRandom, pRandom);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_LEN:

			pLen = NEW_UNARY_OPERATOR(ExpLen, pLen);

			// Return on close bracket
			CHECK_TERMINATE();

			break;

		case T_LEFTBRACKET:

			// THIS WILL BE CALLED ALWAYS NOW!!!
			//step++;
			//TOTIGS: Everywhere else you call DoBracket you dont add 1 to the step...
			// resulting in like 2 brackets omfg
			LeftPart = DoBrackets(step);

			if (unaryMode) return LeftPart;

			CHECK_TERMINATE()
			break;
			

		case T_NULL:
			step++;
			break;

		default:
				throw runtime_error("Syntax error in an expression.  Please report this bug.");

		}//switch
	}//while

	return LeftPart;
}