# coding: utf8
"""
Содержит тип для обработки слов секции констант.
"""
if True:
	from пакОберон.пакКомпилятор.пакСущность.пакСлово import тСлово
	from пакОберон.пакКомпилятор.пакСущность.пакСекция import тСекцияКонст
	from пакОберон.пакКомпилятор.пакСущность.пакСлово import тСлово
	from пакОберон.пакКомпилятор.пакСущность.пакОшибка import тОшибка

class тСканерКонстанты(тСекцияКонст):
	def __init__(сам, пОберон, пДанные:dict)->None:
		сам.__оберон = пОберон
		сам.__конс = пОберон.конс
		сам.__конс.Отладить("тСканерКонстанты.__init__()")

		сам.ош_ = тОшибка(пОберон, "тСканерКонстанты")

		тСекцияКонст.__init__(сам, пОберон, пДанные)
		if сам.ошк.бВнутр:
			сам.ош_.Внутр("__init__()","При создании тСекцияКонст")
			return

		# Признак того, что в этом пространстве секций констант больше нет
		сам.__бКонстОдин :bool= False
		сам.__модуль_имя :str= пДанные['модуль_имя']
		сам.__Обработать()
		if сам.ошк.бВнутр:
			сам.ош_.Внутр("__init__()","При вызове __Обработать()")
			return

	def __Обработать(сам):
		"""
		Проводит разбор секции CONST.
		"""
		if сам.__ЕслиКонстанты():
			if сам.__ЕслиСекцияНеПусто():
				if сам.ош_.бВнутр:
					сам.ош_.Внутр("__ЕслиКонстанты()", "Ошибка при обнаружении секции")
					return
				if сам.ош_.бИсх:
					сам.__конс.Ошибка("__ЕслиКонстанты()", "Ошибка при обнаружении секции")
					return
				сам.__ЕслиСекцияОграничен()
				if сам.ош_.бВнутр:
					сам.__конс.ОшВнутр("__ЕслиСекцияОграничен()", "Ошибка при обнаружении конца секции")
					return
				if сам.ош_.бИсх:
					сам.ош_.Исх("__ЕслиСекцияОграничен()", "Ошибка при обнаружении конца секции")
					return
				сам.СловаСекции_Получить()
				if сам.ош_.бВнутр:
					сам.ош_.Внутр("СловаСекции_Получить()", "Ошибка при получении слов секции")
					return
				if сам.ош_.бИсх:
					сам.__конс.Ошибка("СловаСекции_Получить()", "Ошибка при получении слов секции")
					return

	def __ЕслиКонстанты(сам) -> bool:
		"""
		Первое слово в списке слов должно быть CONST.
		Если нет -- значит в исходнике нет констант.
		"""
		слово :тСлово= сам.слова_модуля[0]
		if слово.строка =='CONST':
			# укоротить слова
			слова_модуля :dict= {}
			for счёт in range(1, len(сам.слова_модуля)):
				слово = сам.слова_модуля[счёт]
				слова_модуля[счёт-1] = слово
			сам.слова_модуля :dict= {}
			сам.слова_модуля = слова_модуля
			сам.бСекцияЕсть :bool = True
		return сам.бСекцияЕсть

	def __ЕслиСекцияНеПусто(сам)->bool:
		"""
		Может быть следующее слово:  TYPE VAR PROCEDURE BEGIN
		(* END модуля уже отброшено *)
		"""
		бНеПусто :bool= False # признак что-то есть в секции
		# первый слово после CONST, а сам CONST уже распознан и отброшен
		слово :тСлово= сам.слова_модуля[0]
		if type(слово) != тСлово:
			стрОш = "Слово должно быть тСлово, type="+str(type(слово))
			сам.ош_.Внутр("__ЕслиСекцияНеПусто()", стрОш)
		# проверим на внезапный конец секции
		бМаркер :bool= not (слово.строка in ["TYPE", "VAR", "PROCEDURE", "BEGIN", "END"])

		if бМаркер: # секция импорта пустая
			бНеПусто = True
		return бНеПусто

	def __ЕслиСекцияОграничен(сам)->None:
		"""
		Ищет разделитель окончания констант.
		Сканируем слова все подряд.
		Может быть следующий слово-маркер окончания: TYPE VAR PROCEDURE BEGIN END
		(* END уже отброшено *)
		Последнее слово в секции должно быть ";".
		"""
		цСловаСчёт :int= 0 # первый слово после CONST, а сам CONST уже распознали и отбросили
		слово :тСлово= сам.слова_модуля[0]
		ограничитель :tuple= ("TYPE", "VAR", "PROCEDURE", "BEGIN", "END")
		бМаркер :bool= (слово.строка in ограничитель)
		# ищем имя константы
		while (not бМаркер) and (цСловаСчёт < (len(сам.слова_модуля))):
			цСловаСчёт += 1
			слово = сам.слова_модуля[цСловаСчёт]
			if type(слово) != тСлово:
				сам.ош_.Внутр("__ЕслиСекцияОграничен()", "Слово должно быть тСлово, type="+str(type(слово)))
				return
			бМаркер = (слово.строка in ограничитель)
		цСловаСчёт -= 1
		слово = сам.слова_модуля[цСловаСчёт]
		сам.Конец_Уст(слово) # Последнее слово определяет верно.
		if слово.строка != ";":
			# Константы -- могут занимать весь модуль, без других секций
			сам.ош_.Исх("__ЕслиСекцияОграничен()", "Слово должно быть ';'"+слово.строка+слово.стрИсх)
			return

	@property
	def цСловаВсего(сам) -> int:
		return len(сам.слова_секции)

	def Парам_Получ(сам) -> dict:
		парам = {}
		парам['слова'] = сам.слова_модуля
		парам['слова_секции'] = сам.слова_секции
		return парам
