bool Dictionary<K, V, FuncModel>::Add(const K& key, const V& value)
{
	if (_size * 10 >= _capacity * 8)//载荷因子超过0.8,增容
	{
		Dictionary<K, V, FuncModel> tmp(_capacity * 2 + 1);
		for (size_t i = 0; i < _capacity; ++i)
		{
			if (_state[i] == EXIST)
			{
				KV node(_table[i]._key, _table[i]._value);
				size_t adress = HashFunc(_table[i]._key);
				size_t index = adress;
				size_t flag = 0;
				while (tmp._state[index] == EXIST)
				{
					index = adress + flag*flag;
					while (index >= _capacity)//如果到了散列表的末尾,要返回表的头
					{
						index -= _capacity;
					}
					flag++;
				}
				tmp._table[index] = node;
				tmp._size++;
				tmp._state[index] = EXIST;
			}
		}
		Swap(tmp);
	}
	size_t adress = HashFunc(key);
	size_t index = adress;//adress是不能变的,用index来标记最后的位置
	size_t flag = 0;
	while (_state[index] == EXIST)//二次探测
	{
		index = adress + flag*flag;
		while(index >= _capacity)//如果到了散列表的末尾,要返回表的头
		{
			index -= _capacity;
		}
		flag++;
	}
	KV tmp(key, value);
	_table[index] = tmp;
	_state[index] = EXIST;
	_size++;
	return true;
}
Esempio n. 2
0
LSQ_IteratorT LSQ_GetElementByIndex(LSQ_HandleT handle, LSQ_KeyT key) {
    HashTableDataT* container = NULL;
    NodeT* node = NULL;    
    assert(handle != LSQ_HandleInvalid);
    container = (HashTableDataT*)handle;
    for(node = container->buckets[HashFunc(container, key)]; node != NULL && container->keyCompFunc(node->key, key) != 0; node = node->next);
    return CreateIterator(container, node, node != NULL ? ITS_DEREFERENCABLE : ITS_PAST_REAR);
}
Esempio n. 3
0
CRezTyp* CRezTypeHashTable::Find(REZTYPE nType) {
  CRezTypeHash* pItm = GetFirstInBin(HashFunc(nType));
  while (pItm != NULL) {
    ASSERT(pItm->GetRezTyp() != NULL);
    if (pItm->GetRezTyp()->GetType() == nType) return pItm->GetRezTyp();
    pItm = pItm->NextInBin();
  }
  return NULL;
};
Esempio n. 4
0
File: Hash.c Progetto: taysom/tau
HashNode *
HashInsert(Hash *h, void *v)
{
    HashNode **b = HashFunc(h, v);
    HashNode *x = HashNew(v, h->keyLen);
    x->next = *b;
    *b = x;
    return x;
}
Esempio n. 5
0
TabRecord* ArrayHashTable:: Search (int key1)
{
	pos = HashFunc(key1)%size;
	freePos = -1;
	for(int i=0; i<size; i++)
		if(recs[pos]==0)
			return 0;
	if (recs[pos]->GetKey()==key1)
		return recs[pos];
	if((recs[pos]==pMark) && (freePos==-1))
		freePos = pos;
	pos = SetNextPos(pos);
	return 0;
}
Esempio n. 6
0
//
// Get value from hash
//
UINT_64 ReducedHashTable::Get(CCHAR_P        szKey,
                              const UINT_32  iKeyLength) const
{
	// 1. Calculate hash
	const UINT_64 iHash = HashFunc(szKey, iKeyLength);
	// 2. Get position in array
	const UINT_64 iPos = iHash & iBase;
	// 3. Check hash value
	const HashElement & oElement = aElements[iPos];

	// Mistake?
	if (iHash != oElement.hash) { return (UINT_64)-1; }

return oElement.value;
}
Esempio n. 7
0
bool HashMap::find(string findStr)//if the element is in a map, returns true. Otherwise false.
{
	auto str_hash = HashFunc(findStr);
	if ((int)str_hash > SIZE) return false;

	member* tmp = table[str_hash];
	while (tmp != NULL)
	{
		if (tmp->key == findStr)
			return true;

		tmp = tmp->next;
	}
	return false;
}
Esempio n. 8
0
void HashTable<T>::DumpKeys() const
{
	for (unsigned i = 0; i < m_size; ++i)
	{
		if (m_keys[i])
		{
			int hash = HashFunc(m_keys[i]);
			int numCollisions = (i - hash + m_size) & m_mask;
			AppDebugOut("%03d: %s - %d\n", i, m_keys[i], numCollisions);
		}
        else
        {
            AppDebugOut("%03d: empty\n", i );
        }
	}
}
Esempio n. 9
0
File: Hash.c Progetto: taysom/tau
HashNode *
HashSearch(Hash *h, void *v)
{
    HashNode **b = HashFunc(h, v);
    HashNode *x = *b;

    while (x) {
        if (IsEqual(v, x)) {
            PRs(v);
            PRs(x->key);
            break;
        }
        x = x->next;
    }
    return x;
}
Esempio n. 10
0
void HashMap::showMember(string str)
{	
	if (!find(str)) return;
	
	auto str_hash = HashFunc(str);
	
	member* tmp = table[str_hash];
	while (tmp != NULL)
	{
		if (tmp->key == str)
			break;

		tmp = tmp->next;
	}
	
	cout << " string: " << tmp->key << " str_hash: " << str_hash  << " value: " << tmp->hashVal << endl;
}
Esempio n. 11
0
void LSQ_AdvanceOneElement(LSQ_IteratorT iterator) {
    NodeT* node = NULL;
    int index = 0;
    IteratorT* iter = NULL;
    assert(iterator != LSQ_HandleInvalid);
    iter = (IteratorT*)iterator;
    if(iter->status == ITS_PAST_REAR)
        return;
    if(iter->status == ITS_DEREFERENCABLE && iter->curNode->next != NULL) {
        iter->curNode = iter->curNode->next;
        return;
    }   
    index = iter->status == ITS_DEREFERENCABLE ? HashFunc(iter->seq, iter->curNode->key) + 1 : 0;
    for(; index < BUCKETS_ARRAY_SIZE && iter->seq->buckets[index] == NULL; ++index);
    node = index < BUCKETS_ARRAY_SIZE ? iter->seq->buckets[index] : NULL;
    iter->curNode = node;
    iter->status = node == NULL ? ITS_PAST_REAR : ITS_DEREFERENCABLE;
}
Esempio n. 12
0
bool CSecurityCache::Add(SecCachStruct& sec,int style)
{
    unsigned char uid = HashFunc(sec.filename);

    SecCachStruct *data = new SecCachStruct;

    memcpy(data->filename,sec.filename,sizeof(sec.filename));
    memcpy(data->chkdata,sec.chkdata,sizeof(sec.chkdata));
    if(style == 0)
        data->tag = 3;//表明新增
    else
        data->tag = 4;//表明为学习的数据

    m_secuBucket[uid].push_back(data);
    m_isChange = true;//表明新增
    m_number ++;
    return true;
}
Esempio n. 13
0
size_t Dictionary<K, V, FuncModel>::Find(const K& key)
{
	size_t adress = HashFunc(key);
	size_t index = adress;
	for (size_t flag = 0; flag < _capacity;)
	{
		if (_table[index]._key == key)//二次探测
		{
			return index;
		}
		index = adress + flag*flag;
		while (index >= _capacity)
		{
			index -= _capacity;
		}
		flag++;
	}
	return -1;
}
Esempio n. 14
0
//
// Put value into hash
//
UINT_32 HashTable::Put(CCHAR_P        szKey,
                       const UINT_32  iKeyLength,
                       const UINT_64  iValue)
{
	// 1. Calculate hash
	const UINT_64 iHash = HashFunc(szKey, iKeyLength);

	for (;;)
	{
		// 2. Get position in array
		const UINT_64 iPos = iHash & iBase;
		// 3. Check hash value
		HashElement & oElement = aElements[iPos];

		// Duplicate!
		if (oElement.hash == iHash) { 
			// is exact duplicate ?
			if(!strcmp(szKey, oElement.key)) { // yes, exact! Replace
				oElement.value = iValue;
				return 0;
			} else { // Need to Resize!
				Resize();		
			}

		} else { 

			// Resize hash
			if (oElement.value != (UINT_64)-1) { Resize(); }
			else
			{
				++iUsed;
				oElement.key   = strdup(szKey); 
				oElement.hash  = iHash;
				oElement.value = iValue;
				return 0;
			}
		} 
	}

// Make compiler happy
return (UINT_32)-1;
}
Esempio n. 15
0
int IsVariableDefinition(const std::string &a_expression)
{
	bool found = false;
	int index;

	for (int i = 0; i < a_expression.length(); i++)
	{
		if (a_expression[i] == ':')
		{
			if (!found)
			{
				found = true;
				index = i;
			}
			else throw ExpressionError("Invalid assignment", new Token);
		}
	}

	if (found)
	{
		// parse
		int name_end = index - 1;
		while (a_expression[name_end] == ' ' && name_end >= 0) name_end--;
		if (name_end < 0) throw ExpressionError("Invalid variable definition", new Token);
		
		last_variable_name = a_expression.substr(0, name_end + 1);
		if (!isvalidname(last_variable_name) || isallupper(last_variable_name, true)) return 0;

		int value_start = index + 1;
		while (a_expression[value_start] == ' ' && value_start < a_expression.length()) value_start++;
		if (value_start == a_expression.length())
		{
			G::variables.Remove(HashFunc(last_variable_name));
			return 2;
		}
		last_variable_value = a_expression.substr(value_start);
		return 1;
	}

	return 0;
}
Esempio n. 16
0
CRezItm* CRezItmHashTableByName::Find(REZCNAME sName, BOOL bIgnoreCase) {
  ASSERT(sName != NULL);
  if (sName == NULL) return NULL;
  CRezItmHashByName* pItm = GetFirstInBin(HashFunc(sName));
  if (bIgnoreCase) {
    while (pItm != NULL) {
      ASSERT(pItm->GetRezItm() != NULL);
      ASSERT(pItm->GetRezItm()->GetName() != NULL);
      if (stricmp(pItm->GetRezItm()->GetName(),sName) == 0) return pItm->GetRezItm();
      pItm = pItm->NextInBin();
    }
  }
  else {
    while (pItm != NULL) {
      ASSERT(pItm->GetRezItm() != NULL);
      ASSERT(pItm->GetRezItm()->GetName() != NULL);
      if (strcmp(pItm->GetRezItm()->GetName(),sName) == 0) return pItm->GetRezItm();
      pItm = pItm->NextInBin();
    }
  }
  return NULL;
};
Esempio n. 17
0
unsigned int HashTable<T>::GetInsertPos(char const *_key) const
{
	unsigned int index = HashFunc(_key);

	// Test if the target slot is empty, if not increment until we
	// find an empty one
	while (m_keys[index] != NULL)
	{
		if(stricmp(m_keys[index], _key) == 0)
        {
            AppDebugOut( "GetInsertPos critical error : trying to insert key '%s'\n", _key );
            DumpKeys();
            AppAbort("Error with HashTable");
        }

		index++;
		index &= m_mask;
		m_numCollisions++;
	}

	return index;
}
Esempio n. 18
0
int HashTable<T>::GetIndex(char const *_key) const
{
	unsigned int index = HashFunc(_key);		// At last profile, was taking an avrg of 550 cycles

	if (m_keys[index] == NULL)
	{
		return -1;
	}

	while (stricmp(m_keys[index], _key) != 0)
	{
		index++;
		index &= m_mask;

		if (m_keys[index] == NULL)
		{
			return -1;
		}
	}

	return index;
}
Esempio n. 19
0
		bool Insert(const _DataType & data)
		{
			int hash = HashFunc(data);
			int slot = HashLevel(hash, level_);
			if (slot < splitPos_)
			{
				slot = HashLevel(hash, level_ + 1);
			}
			//if (buckets_[slot]->Full())
			if ((float) size_ / capacity_ >= 0.8)
			{
				Split();
				slot = HashLevel(hash, level_);
				if (slot < splitPos_)
				{
					slot = HashLevel(hash, level_ + 1);
				}
			}
			++size_;
			buckets_[slot]->Add(data);
			return true;
		}
Esempio n. 20
0
bool AddSecureHash(const unsigned char* hash)
{
	//
	if(!g_isReceive)
		g_isReceive = true;
	//
	SECURE_HASH* secuHash = (SECURE_HASH*)ExAllocatePoolWithTag(PagedPool, sizeof(SECURE_HASH), 'knab');
	if(secuHash == NULL)
		return false;

	memcpy(secuHash->Hash, hash, HASH_SIZE);

	UCHAR id = HashFunc(hash);
	secuHash->next = g_secuHash[id];
	g_secuHash[id] = secuHash;

// 	DbgPrint ("AddSecuHash %2d: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", id, 
// 		hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7], hash[8], hash[9], hash[10], 
// 		hash[11], hash[12], hash[13], hash[14], hash[15]) ;

	
	return true;
}
Esempio n. 21
0
//adds member to the map
void HashMap::push(string addStr, unsigned long int val) {
	
	auto str_hash = HashFunc(addStr);

	if (!table[str_hash])//if no collisions had occured before, creates a new member
		table[str_hash] = new member(val, addStr);
	
	else {
		//adds it to end of the list 
		member *entry = table[str_hash];
		while (entry->next != NULL)
		{
			if (entry->key == addStr)
			{
				entry->hashVal = val;
				return;
			}
			entry = entry->next;
	
		}
		entry->next = new member(val, addStr);
	}
	ElementsNumber++;//increments the number of elements
}
Esempio n. 22
0
void LSQ_DeleteElement(LSQ_HandleT handle, LSQ_KeyT key) {
    HashTableDataT* container = NULL;
    NodeT* node = NULL;
    NodeT* prevNode = NULL;
    int index;
    assert(handle != NULL);
    container = (HashTableDataT*)handle;
    index = HashFunc(container, key);
    node = container->buckets[index];
    while(node != NULL && container->keyCompFunc(node->key, key) != 0) {
        prevNode = node;
        node = node->next;
    }
    if(node != NULL) {
        if(prevNode != NULL)
            prevNode->next = node->next;
        if(container->buckets[index] == node)
            container->buckets[index] = node->next;
        free(node->key);
        free(node->value);
        free(node);
        container->size--;
    }
}
Esempio n. 23
0
size_t HashBucket<K,V,HashFunc>::_HashFunc(const K& key){
	return HashFunc()(key)%_table.size();
}
Esempio n. 24
0
void STARTUP_user() {
  GenesisObject* object;
  GenesisObject  tobject;
  char*          slotnames[50];
  char*          argv[50];

  /* Definition of object pulsegen */
  BZERO(&tobject,sizeof(GenesisObject));
  tobject.name = "pulsegen";
  tobject.type = "pulsegen_type";
  tobject.size = sizeof(struct pulsegen_type);
  { extern int PulseGen(); tobject.function = PulseGen; HashFunc("PulseGen", PulseGen, "int"); }
  ObjectAddClass(&tobject,ClassID("device"),CLASS_PERMANENT);
  AddDefaultFieldList(&tobject);
  tobject.defaults = (Element*) calloc(1, tobject.size);
  AddObject(&tobject);
  object = GetObject("pulsegen");
  object->defaults->object = object;
  object->defaults->name = CopyString("pulsegen");
  object->author = "M.Nelson Caltech 4/89";
  { extern int PulseGen(); AddActionToObject(object, "RESET", PulseGen, 0) ? 0 : (Error(), printf("adding action 'RESET' to object 'pulsegen'\n")); HashFunc("PulseGen", PulseGen, "int"); }
  { extern int PulseGen(); AddActionToObject(object, "PROCESS", PulseGen, 0) ? 0 : (Error(), printf("adding action 'PROCESS' to object 'pulsegen'\n")); HashFunc("PulseGen", PulseGen, "int"); }
  slotnames[0] = "gate/trig";
  MsgListAdd(object, "INPUT", pulsegen_INPUT, slotnames, 1);
  slotnames[0] = "pulse#";
  slotnames[1] = "level";
  MsgListAdd(object, "LEVEL", pulsegen_LEVEL, slotnames, 2);
  slotnames[0] = "pulse#";
  slotnames[1] = "width";
  MsgListAdd(object, "WIDTH", pulsegen_WIDTH, slotnames, 2);
  slotnames[0] = "pulse#";
  slotnames[1] = "delay";
  MsgListAdd(object, "DELAY", pulsegen_DELAY, slotnames, 2);
  object->description = "General purpose pulse generator\n";
  FieldListMakePermanent(object);
  MsgListMakePermanent(object);

  /* Definition of object PID */
  BZERO(&tobject,sizeof(GenesisObject));
  tobject.name = "PID";
  tobject.type = "PID_type";
  tobject.size = sizeof(struct PID_type);
  { extern int PIDcontroller(); tobject.function = PIDcontroller; HashFunc("PIDcontroller", PIDcontroller, "int"); }
  ObjectAddClass(&tobject,ClassID("device"),CLASS_PERMANENT);
  AddDefaultFieldList(&tobject);
  tobject.defaults = (Element*) calloc(1, tobject.size);
  AddObject(&tobject);
  object = GetObject("PID");
  object->defaults->object = object;
  object->defaults->name = CopyString("PID");
  object->author = "M.Nelson Caltech 4/89";
  { extern int PIDcontroller(); AddActionToObject(object, "INIT", PIDcontroller, 0) ? 0 : (Error(), printf("adding action 'INIT' to object 'PID'\n")); HashFunc("PIDcontroller", PIDcontroller, "int"); }
  { extern int PIDcontroller(); AddActionToObject(object, "RESET", PIDcontroller, 0) ? 0 : (Error(), printf("adding action 'RESET' to object 'PID'\n")); HashFunc("PIDcontroller", PIDcontroller, "int"); }
  { extern int PIDcontroller(); AddActionToObject(object, "PROCESS", PIDcontroller, 0) ? 0 : (Error(), printf("adding action 'PROCESS' to object 'PID'\n")); HashFunc("PIDcontroller", PIDcontroller, "int"); }
  slotnames[0] = "command";
  MsgListAdd(object, "CMD", PID_CMD, slotnames, 1);
  slotnames[0] = "sense";
  MsgListAdd(object, "SNS", PID_SNS, slotnames, 1);
  slotnames[0] = "gain";
  MsgListAdd(object, "GAIN", PID_GAIN, slotnames, 1);
  object->description = "PID (proportional, integral, derivative) feedback controller\n";
  FieldListMakePermanent(object);
  MsgListMakePermanent(object);

/* Script variables */

} /* STARTUP_user */
Esempio n. 25
0
bool CSecurityCache::Init()
{
    Clear();
    CRecordProgram::GetInstance()->RecordCommonInfo(L"SeCathe", 1000, L"创建Cathe");

    //Vista权限问题
    TCHAR szDataPath[MAX_PATH + 1];
    SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, szDataPath);
    _tcscat_s(szDataPath, _T("\\MoneyHub"));

    WCHAR szAppDataPath[MAX_PATH + 1];
    ExpandEnvironmentStringsW(szDataPath, szAppDataPath, MAX_PATH);

    ::CreateDirectoryW(szAppDataPath, NULL);

    WCHAR expName[MAX_PATH] = {0};
    CRecordProgram::GetInstance()->RecordCommonInfo(L"SeCathe", 1000, m_cathfile.c_str());
    ExpandEnvironmentStringsW(m_cathfile.c_str(), expName, MAX_PATH);
    HANDLE hFile;
    /*if(true == isonce)
    {
    	hFile = CreateFileW(expName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    }
    else
    {*/
    // 读取原来的cache文件
    hFile = CreateFileW(expName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    //}

    if(hFile == INVALID_HANDLE_VALUE)
    {
        int error = ::GetLastError();
        CRecordProgram::GetInstance()->FeedbackError(L"SeCathe", 1000, CRecordProgram::GetInstance()->GetRecordInfo(L"读%s失败:%d", expName, error));
        return false;
    }

    DWORD dwLength = GetFileSize(hFile, NULL);
    if(dwLength <= 0)
    {
        CloseHandle(hFile);
        return true;
    }
    unsigned char* lpBuffer = new unsigned char[dwLength + 1];

    if (lpBuffer == NULL)
    {
        ::MessageBoxW(NULL, L"内存空间满",L"安全缓存",MB_OK | MB_SETFOREGROUND);
        CloseHandle(hFile);
        return false;
    }

    DWORD dwRead = 0;
    if (!ReadFile(hFile, lpBuffer, dwLength, &dwRead, NULL))
    {
        delete []lpBuffer;
        CloseHandle(hFile);
        ::MessageBoxW(NULL, L"读安全缓存失败",L"安全缓存",MB_OK | MB_SETFOREGROUND);
        return false;
    }
    CloseHandle(hFile);

    unsigned char* unPackBuf = new unsigned char[dwRead];
    if(unPackBuf == NULL)
    {
        delete []lpBuffer;
        ::MessageBoxW(NULL, L"内存空间满",L"安全缓存",MB_OK | MB_SETFOREGROUND);
        return false;
    }

    int ret = CacheUnPack(lpBuffer,dwRead,unPackBuf);

    delete []lpBuffer;

    if(ret < 0)
    {
        CRecordProgram::GetInstance()->FeedbackError(L"SeCathe", 1000, CRecordProgram::GetInstance()->GetRecordInfo(L"读%sUnPack异常", expName));

        delete[] unPackBuf;
        return false;
    }
    CRecordProgram::GetInstance()->RecordCommonInfo(L"SeCathe", 1000, L"读入Cathe");
    for(DWORD i = 0; i < (unsigned long)ret;)
    {
        SecCachStruct *data = new SecCachStruct;
        if(data == NULL)
            break;
        memcpy(data->filename,unPackBuf + i,sizeof(data->filename));
        i += sizeof(data->filename);
        memcpy(data->chkdata,unPackBuf + i,SECURE_SIZE);
        i += SECURE_SIZE;
        memcpy(&data->tag,unPackBuf + i,sizeof(short int));//tag文件从缓存中读出
        i += sizeof(short int);
        if(data->tag != 4)//表明是非学习数据
            data->tag = 1;//在缓存中读出的数据添加的话初始化为0,这里先设置为1,表明有效
        unsigned char uid = HashFunc(data->filename);
        m_secuBucket[uid].push_back(data);
        m_number ++;
    }
    delete[] unPackBuf;
    m_isChange = false;
    return true;
}
Esempio n. 26
0
void TokenListToRPN(TokenList &a_list, RPNStack &a_rpn)
{
	// Shunting yard algorithm
	std::vector<Token*> opStack;
	Token *c_token = a_list.head;

	while (c_token)
	{
		switch (c_token->type)
		{
		case Token::Type::Name:
			if (isalllower(c_token->name, true) && isvalidname(c_token->name))
			{
				if (G::functions.Exists(c_token->name))
				{
					opStack.push_back(c_token);
					c_token->type = Token::Type::E_Function;
				}
				else if (G::variables.Exists(c_token->name))
				{
					a_rpn.push_back({ ExprNode::Type::Number, G::variables.Get(c_token->name) });
				}
				else throw ExpressionError("Undefined reference", c_token);
			}
			else if (isallupper(c_token->name, true) && isvalidname(c_token->name))
			{
				if (G::constants.Exists(c_token->name))
					a_rpn.push_back({ ExprNode::Type::Number, G::constants.Get(c_token->name) });
				else throw ExpressionError("Undefined constant", c_token);
			}
			else throw ExpressionError("Invalid value name", c_token);
			break;
		case Token::Type::Number:
			a_rpn.push_back({ ExprNode::Type::Number, c_token->value });
			break;
		case Token::Type::Operator:
			if (opStack.size() > 0)
			{
				if (c_token->optype == Token::OpType::RPar)
				{
					Token *tos = opStack.back();
					if (opStack.size() == 0)
						throw ExpressionError("#1 Mismatched parenthesis", c_token);
					while (tos->optype != Token::OpType::LPar)
					{
						a_rpn.push_back({ ExprNode::Type::Operator, 0, tos->optype });
						opStack.pop_back();
						tos = opStack.back();
						if (opStack.size() == 0)
							throw ExpressionError("#2 Mismatched parenthesis", c_token);
					}
					opStack.pop_back(); // pop opening parantheses
					if (opStack.size() > 0)
					{
						tos = opStack.back();
						if (tos->type == Token::Type::E_Function)
						{
							a_rpn.push_back({ ExprNode::Type::Function, 0, Token::OpType::None,
								HashFunc(tos->name) });
							opStack.pop_back();
						}
					}
				}
				else if (c_token->optype == Token::OpType::Comma)
				{
					Token *tos = opStack.back();
					if (opStack.size() == 0)
						throw ExpressionError("Invalid separator", c_token);
					while (tos->optype != Token::OpType::LPar)
					{
						a_rpn.push_back({ ExprNode::Type::Operator, 0, tos->optype });
						opStack.pop_back();
						tos = opStack.back();
						if (opStack.size() == 0)
							throw ExpressionError("Invalid separator", c_token);
					}
				}
				else
				{
					if (c_token->optype != Token::OpType::LPar)
					{
						while (opStack.size() > 0 && opStack.back()->optype != Token::OpType::LPar)
						{
							Token *tos = opStack.back();
							if ((is_la(c_token->optype) && precedence(c_token->optype) <= precedence(tos->optype)) ||
								(is_ra(c_token->optype) && precedence(c_token->optype) < precedence(tos->optype)))
							{
								opStack.pop_back();
								a_rpn.push_back({ ExprNode::Type::Operator, 0, tos->optype });
							}
							else break;
						}
					}
					opStack.push_back(c_token);
				}
			}
			else if (c_token->optype != Token::OpType::RPar ||
					c_token->optype != Token::OpType::Comma)
				opStack.push_back(c_token);
			break;
		case Token::Type::Special:
			a_rpn.push_back({ ExprNode::Type::Special, 0, ExprNode::OpType::None, 0, c_token->sptype });
			break;
		}

		c_token = c_token->next;
	}
	
	for (unsigned i = opStack.size(); i-- > 0; )
	{
		if (opStack[i]->optype == Token::OpType::LPar ||
			opStack[i]->optype == Token::OpType::RPar)
			throw ExpressionError("#3 Mismatched parenthesis", opStack[i]);
		a_rpn.push_back({ ExprNode::Type::Operator, 0, opStack[i]->optype });
	}
}