module gedo.text.parser;



private import gedo.text.ctype;
private import gedo.text.convert;



public class Parser
{
public:
	this(char[] text, char[] tag)
	{
		_position = 0;
		_text     = text;

		seek(tag);
	}


	this(char[] text)
	{
		_position = 0;
		_text     = text;
	}


	bool seek(char[] tag)
	{
		while(_position + tag.length < _text.length)
		{
			if(_text[_position .. _position + tag.length] == tag)
			{
				return true;
			}

			++_position;
		}

		_position = _text.length;

		return false;
	}


	bool isValid()
	{
		return (_position < _text.length);
	}


	int geti()
	{
		bool isMinus = false;

		while(_position < _text.length)
		{
			auto c = _text[_position];

			if(isDigit(c))
			{
				auto matchHead = _position;
				if(isMinus)
				{
					--matchHead;
				}

				++_position;
				while(_position < _text.length)
				{
					c = _text[_position];
					if(!isDigit(c))
					{
						break;
					}

					++_position;
				}

				return toInt(_text[matchHead .. _position]);
			}
			else if(c == '-')
			{
				isMinus = true;
			}
			else
			{
				isMinus = false;
			}

			++_position;
		}

		throw new MissingError("geti not found!");
	}


	float getf()
	{
		bool isMinus = false;

		while(_position < _text.length)
		{
			auto c = _text[_position];

			if(isDigit(c))
			{
				auto matchHead = _position;
				if(isMinus)
				{
					--matchHead;
				}

				++_position;
				while(_position < _text.length)
				{
					c = _text[_position];
					if(!isDigit(c) && c != '.')
					{
						break;
					}

					++_position;
				}

				return toReal(_text[matchHead .. _position]);
			}
			else if(c == '-')
			{
				isMinus = true;
			}
			else
			{
				isMinus = false;
			}

			++_position;
		}

		throw new MissingError("getf not found!");
	}


	char[] gets()
	{
		while(_position < _text.length)
		{
			auto c = _text[_position];

			if(c == '"')
			{
				++_position;

				auto matchHead = _position;

				while(_position < _text.length)
				{
					c = _text[_position];
					if(c == '"')
					{
						auto s = _text[matchHead .. _position];

						++_position;

						return s;
					}

					++_position;
				}

				throw new MissingError("gets \" not closed!");
			}

			++_position;
		}

		throw new MissingError("gets not found!");
	}


	char[] text()
	{
		return _text[_position .. length];
	}


private:
	char[] _text;
	uint   _position;
}



public class MissingError : Error
{
public:
	this(string s)
	{
		super(s);
	}
}
