"""
defines the tokens that the tokenizer uses to tokenize a file
by simon jones
1/1/2017
"""

try:
	from compiler.lcd_string_token import *
except ImportError:
	from lcd_string_token import *



class BasicToken(Token):
	"""
	a basic token. consumes anything that is not a control character
	"""

	def __init__(self, data=''):
		super().__init__(data)


class EscapeSequenceToken(Token):
	"""
	defines an escape character
	"""

	ESCAPE_CHARACTER = '^'

	def __init__(self, data=''):
		super().__init__(data)
		self.add_control_character(self.ESCAPE_CHARACTER)

	def consume(self, string):
		"""
		consumes the string until the condition is met
		"""
		if len(string) >= 2:
			self.data += string[1]
			return string[2:]
		else:
			return ''

	def matches(self, string):
		"""
		deduces whether or not the current string matches what this token can parse
		"""
		return string[0] == self.ESCAPE_CHARACTER


class MacroToken(Token):
	"""
	Defines the token that begins a command
	"""

	BEGIN_MACRO = "@"

	def __init__(self, data=''):
		super().__init__(data)
		self.add_control_character(self.BEGIN_MACRO)

	def consume(self, string):
		"""
		consumes the string until the condition is met
		"""
		if len(string) >= 1:
			self.data += string[0]
			return string[1:]
		else:
			return ''

	def matches(self, string):
		"""
		deduces whether or not the current string matches what this token can parse
		"""
		return string[0] == self.BEGIN_MACRO


class CommandToken(Token):
	"""
	Defines the token that begins a command
	"""

	BEGIN_COMMAND = "#"

	def __init__(self, data=''):
		super().__init__(data)
		self.add_control_character(self.BEGIN_COMMAND)

	def consume(self, string):
		"""
		consumes the string until the condition is met
		"""
		if len(string) >= 1:
			self.data += string[0]
			return string[1:]
		else:
			return ''

	def matches(self, string):
		"""
		deduces whether or not the current string matches what this token can parse
		"""
		return string[0] == self.BEGIN_COMMAND


class BeginStatementToken(Token):
	"""
	defines the opening parenthesis of a command or macro
	"""

	BEGIN_STATEMENT = '('

	def __init__(self, data=''):
		super().__init__(data)
		self.add_control_character(self.BEGIN_STATEMENT)

	def consume(self, string):
		"""
		consumes the string until the condition is met
		"""
		if len(string) >= 1:
			self.data += string[0]
			return string[1:]
		else:
			return ''

	def matches(self, string):
		"""
		deduces whether or not the current string matches what this token can parse
		"""
		return string[0] == self.BEGIN_STATEMENT


class EndStatementToken(Token):
	"""
	defines the closing parenthesis of a command or macro
	"""

	END_STATEMENT = ')'

	def __init__(self, data=''):
		super().__init__(data)
		self.add_control_character(self.END_STATEMENT)

	def consume(self, string):
		"""
		consumes the string until the condition is met
		"""
		if len(string) >= 1:
			self.data += string[0]
			return string[1:]
		else:
			return ''

	def matches(self, string):
		"""
		deduces whether or not the current string matches what this token can parse
		"""
		return string[0] == self.END_STATEMENT


class SeparatorToken(Token):
	"""
	defines the symbol that seperates parameters
	"""

	COMMAND_SEPARATOR = ','

	def __init__(self, data=''):
		super().__init__(data)
		self.add_control_character(self.COMMAND_SEPARATOR)

	def consume(self, string):
		"""
		consumes the string until the condition is met
		"""
		if len(string) >= 1:
			self.data += string[0]
			return string[1:]
		else:
			return ''

	def matches(self, string):
		"""
		deduces whether or not the current string matches what this token can parse
		"""
		return string[0] == self.COMMAND_SEPARATOR


class EndLineToken(Token):
	"""
	defines an endline character
	"""

	END_LINE = '\n'

	def __init__(self, data=''):
		super().__init__(data)
		self.add_control_character(self.END_LINE)

	def consume(self, string):
		"""
		consumes the string until the condition is met
		"""
		if len(string) >= 1:
			self.data += string[0]
			return string[1:]
		else:
			return ''

	def matches(self, string):
		"""
		deduces whether or not the current string matches what this token can parse
		"""
		return string[0] == self.END_LINE


class TokenArray(object):
	ARRAY = [EndLineToken(),
			 SeparatorToken(),
			 CommandToken(),
			 MacroToken(),
			 BeginStatementToken(),
			 EndStatementToken(),
			 EscapeSequenceToken(),
			 BasicToken()]


def main():
	print("RUNNING TESTS")
	t = BasicToken()
	e = EscapeSequenceToken()
	b = BeginStatementToken()
	f = EndStatementToken()
	c = CommandToken()
	m = MacroToken()
	s = SeparatorToken()
	l = EndLineToken()

	assert t.matches("basic test")
	assert e.matches("^escaped")
	assert b.matches("(test")
	assert f.matches(")test")
	assert c.matches("#test")
	assert m.matches("@test")
	assert s.matches(",test")
	assert l.matches("\nnewline")

	assert t.consume("test") == ''
	assert e.consume("^test") == "est"
	assert b.consume("(test") == "test"
	assert f.consume(")test") == "test"
	assert c.consume("#test") == "test"
	assert m.consume("@test") == "test"
	assert s.consume(",test") == "test"
	assert l.consume("\nnewline") == "newline"

	assert t.data == "test"
	assert e.data == "t"
	assert b.data == "("
	assert f.data == ")"
	assert c.data == "#"
	assert m.data == "@"
	assert s.data == ","
	assert l.data == "\n"

	print(t)
	print(e)
	print(b)
	print(f)
	print(c)
	print(m)
	print(s)
	print(l)

	print("FINISHED TESTS")


if __name__ == "__main__":
	main()
