Beispiel #1
0
// Return the last fetched token skipping push backed token if it exists
Token* SqlParser::GetLastToken()
{
	Token *token = NULL; 

	if(_push_back_token != NULL)
		token = _push_back_token->prev;
	else
		token = _tokens.GetLastNoCurrent();

	// Return previous non-blank, non-comment token
	while(token && (token->IsBlank() == true || token->type == TOKEN_COMMENT))
		token = token->prev;

	return token;
}
Beispiel #2
0
// Skip blanks, tabs and newlines
Token* Token::SkipSpaces(Token *token)
{
	if(token == NULL)
		return NULL;

	Token *cur = token;

	// Skip spaces
	while(cur != NULL)
	{
		if(cur->IsBlank() == false)
			break;

		cur = cur->next;
	}

	return cur;
}
Beispiel #3
0
// Get next token from the input
Token* SqlParser::GetNextToken()
{
	// Check push back tokens first
	while(_push_back_token != NULL)
	{
		Token *token = _push_back_token;

		// Multiple tokens can be push back
		_push_back_token = token->next;

		if(token->IsBlank() == true || token->type == TOKEN_COMMENT)
			continue;

		return token;
	}

	Token *token = new Token();
	bool exists = false;

	while(true)
	{
		if(_next_start == NULL || _remain_size <= 0)
		{
			delete token;
			return NULL;
		}

		SkipSpaceTokens();
		
		// Check for a word first as it can start with special symbol such as _ @
		exists = GetWordToken(token);

		if(exists == true)
			break;

		// Check for a single char token
		exists = GetSingleCharToken(token);

		if(exists == true)
			break;
	}
	
	return token;
}
Beispiel #4
0
// Set Removed flag for the token
void Token::Remove(Token *token, bool remove_spaces_before)
{
	if(token == NULL)
		return;

	token->flags |= TOKEN_REMOVED;

	Token *prev = token->prev;
	Token *next = token->next;

	if(prev == NULL)
		return;

	if(remove_spaces_before == true)
	{
		// Remove spaces token before the removed word (recursively), but only if there is a blank or ) , ;
		// after removed token (otherwise tokens can be merged)
		if(prev->Compare(' ', L' ') == true || prev->Compare('\t', L'\t') == true)
		{
			if(next != NULL)
			{
				if(next->IsBlank() == true || next->Compare(')', L')') == true || 
					next->Compare(',', L',') == true || next->Compare(';', L';') == true)
					Remove(prev);
			}
			else
			// Next token can be not selected yet
			if(token->next_start != NULL && token->remain_size > 1)
			{
				const char *cur = token->next_start;

				if(*cur == ' ' || *cur == ')' || *cur == ',' || *cur == ';')
					Remove(prev);
			}
		}
	}
	// In case cases better to remove spaces after: "SET var = 1" to "var := 1" when SET is removed 
	else
	{
		if(next != NULL && next->Compare(' ', L' ') == true)
			Remove(next);
	}
}
Beispiel #5
0
// Get the previous non-blank, non comment token
Token* SqlParser::GetPrevToken(Token *token)
{
	if(token == NULL)
		return NULL;

	Token *prev = NULL;
	Token *cur = token->prev;

	while(cur != NULL)
	{
		if(cur->IsBlank() == false && cur->type != TOKEN_COMMENT)
		{
			prev = cur;
			break;
		}

		cur = cur->prev;
	}

	return prev;
}
Beispiel #6
0
// Generate output
void SqlParser::CreateOutputString(const char **output, int *out_size)
{
	if(output == NULL)
		return;

	Token *token = _tokens.GetFirst();

	int len = 0;

	int not_removed = 0;
	int removed = 0;

	// Calculate the output size in bytes and format output
	while(token != NULL)
	{
		bool r = false;
		bool n = false;

		// If token removed its target length is 0
		len += token->GetTargetLength();

		if(token->IsRemoved() == false)
		{
			r = token->Compare('\r', L'\r');

			if(r == false)
				n = token->Compare('\n', L'\n');
		}

		// Check if we need to remove newline (0D0A \r\n on Windows, 0D on Unix)
		if(r == true || n == true)
		{
			// String was not empty and all tokens removed
			if(not_removed == 0 && removed != 0)
			{
				Token::Remove(token);
				len--;

				// If current is \r and next is \n remove \n 
				if(r == true && token->next != NULL && token->next->Compare('\n', L'\n') == true)
				{
					// Its size will be reduced in the next iteration
					Token::Remove(token->next);
				}

				// Remove all spaces in this empty line
				Token *cur = token->prev;

				while(cur != NULL)
				{
					// Remove until new line
					if(cur->Compare('\n', L'\n') || cur->Compare('\r', L'\r'))
						break;

					if(cur->IsBlank() == true && cur->IsRemoved() == false)
					{
						Token::Remove(cur);
						len--;
					}

					cur = cur->prev;
				}
			}

			not_removed = 0;
			removed = 0;
		}
		// Calculate the number of removed and not removed tokens in line
		else
		{
			if(token->IsBlank() == false)
			{
				if(token->IsRemoved() == true)
					removed++;
				else
					not_removed++;
			}
		}

		token = _tokens.GetNext();
	}
	
	if(len == 0)
	{
		*output = NULL;

		if(out_size != NULL)
			*out_size = 0;

		return;
	}

	// Allocate buffer
	char *out = new char[len + 1]; *out = 0;

	token = _tokens.GetFirst();
	int cur_len = 0;

	while(token != NULL)
	{
		token->AppendTarget(out, &cur_len);

		token = _tokens.GetNext();
	}

	out[cur_len] = 0;

	*output = out; 

	if(out_size != NULL)
		*out_size = cur_len;
}