johnymkp
@johnymkp

Как создать объектную модель содержимого файла?

Есть файл примерно такой структуры:

Структура файла

"DOTAHeroes"
{
	//=================================================================================================================
	// HERO: Antimage
	//=================================================================================================================
	"npc_dota_hero_antimage"
	{
		// General
		//-------------------------------------------------------------------------------------------------------------
		"Persona"
		{
			"1"
			{
				"name"					"npc_dota_hero_antimage_persona1"
				"token"					"#npc_dota_hero_antimage_persona1"
				"token_english"			"#npc_dota_hero_antimage_persona1__en"
				"Model"					"models/heroes/antimage_female/antimage_female.vmdl"	// For tools only
				"ModelScale"		"1.05"
			}
		}
		"HeroOrderID"	"1"


		// Abilities
		//-------------------------------------------------------------------------------------------------------------
		"Ability1"		"antimage_mana_break"
		"Ability2"		"antimage_blink"
		"Ability3"		"antimage_counterspell"
		"Ability4"		"antimage_mana_overload"
		"Ability5"		"antimage_counterspell_ally"
		"Ability6"		"antimage_mana_void"
		"Ability10"		"special_bonus_strength_9"
		"Ability11"		"special_bonus_unique_antimage_manavoid_aoe"
		"Ability12"		"special_bonus_unique_antimage_7"
		"Ability13"		"special_bonus_unique_antimage"
		"Ability14"		"special_bonus_unique_antimage_6"
		"Ability15"		"special_bonus_unique_antimage_3"
		"Ability16"		"special_bonus_unique_antimage_4"
		"Ability17"		"special_bonus_unique_antimage_2"

		// Armor
		//-------------------------------------------------------------------------------------------------------------
		"ArmorPhysical"		"1"

		// Attack
		//-------------------------------------------------------------------------------------------------------------
		"AttackCapabilities"		"DOTA_UNIT_CAP_MELEE_ATTACK"
		"AttackDamageMin"		"29"
		"AttackDamageMax"		"33"
		"AttackRate"		"1.400000"
		"AttackAnimationPoint"		"0.300000"
		"AttackAcquisitionRange"		"600"
		"AttackRange"		"150"
		"ProjectileSpeed"		"0"
		"AttackSpeedActivityModifiers"
		{
			"fast"		"180"
			"faster"	"300"
		}

		// Attributes
		//-------------------------------------------------------------------------------------------------------------
		"AttributePrimary"		"DOTA_ATTRIBUTE_AGILITY"
		"AttributeBaseStrength"		"19"
		"AttributeStrengthGain"		"1.600000"
		"AttributeBaseIntelligence"		"12"
		"AttributeIntelligenceGain"		"1.800000"
		"AttributeBaseAgility"		"24"
		"AttributeAgilityGain"		"2.8"
		"StatusHealthRegen"		"0.75"

		// Movement
		//-------------------------------------------------------------------------------------------------------------
		"MovementSpeed"		"310"
		

	}
	
	//=================================================================================================================
	// HERO: Axe
	//=================================================================================================================
	"npc_dota_hero_axe"
	{
	...



Хотелось бы разобрать его и сформировать объект, у которого можно было бы спросить "Дай мне объект npc_dota_hero_antimage". А у полученного объекта спросить "Дай мне объект AttributeBaseAgility", а из него уже получить значение 24. В данный момент я исходную структуру файла вижу как корневой объект "DOTAHeroes", значение которого - это массив объектов, в данном фрагменте это "npc_dota_hero_antimage" и "npc_dota_hero_axe". У каждого объекта есть набор полей. Например, "Persona", а его значение тоже объект. А у поля "AttributeBaseAgility" значение 24.

Я сделал токенизацию, т.е. прошел весь файл и выделил элементы, такие как "Строка", "Комментарий", "Скобка открывающая", "Скобка закрывающая". Но вот хотя бы в общих чертах понять, что делать дальше - не получается. Как будто надо идти по токенам и анализировать их комбинации, вроде того "если встретилась строка, а за ней еще строка, то создаем объект, даем ему имя по первой строке, а в значение записываем вторую строку. Если же после строки идет открывающая скобка, то создаем объект, даем ему имя по первой строке, а в значение создаем еще объект" и т.д. Как будто пахнет рекурсией, и похоже на то, что делают библиотеки для работы с JSON, но для меня сейчас выглядит сложновато.

Подскажите, к какому разделу вообще подобная задача относится, как такое правильно загуглить, мб какую-то литературу \ статьи сможете посоветовать максимально приближенную к подобным задачам. Ну и если кому не лень, можете и своих идей написать в виде псевдокода, алгоритма на словах и т.д.
  • Вопрос задан
  • 62 просмотра
Пригласить эксперта
Ответы на вопрос 4
mayton2019
@mayton2019
Bigdata Engineer
Ты можешь работать на JavaScript/Node языках. С их точки зрения JSON (JavaScript Object Notation) это и есть
объект и никаких других преобразований уже делать не надо.
Ответ написан
@chemdev
Тут придется пройтись по файлу построчно, убрав комментарии, и сделать из него json. Вот задача на скобки, она тут пригодится.
Ответ написан
Комментировать
NikFaraday
@NikFaraday
Student full-stack Developer
Ну псевдокод для это выглядит примерно так (С использованием библиотек .net):

содержимоеФайла = файл.ЧитатьВсеСтроки()
новоеСодержимое = пустаяСтрока

цикл (строка по содержимоеФайла)
   если (НЕ строк.НачинаетсяС(*знакКомментария*) тогда
      новоеСодержимое += (строка + *знакПереносаСтроки*)
конецЦикла

объектКласса = джсонКонвертер.ДесериализироватьОбъект(новоеСодержимое)
Ответ написан
Комментировать
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
В принципе, грамматика тут несложная, достаточно рекурсивной обработки, в которой комментарии пропускает токенизатор.
функция получитьТокен() {
  // Читает файл и формирует токен вида { тип: тип_токена, значение: строка }
  // Пропускает комментарии, пробелы и концы строк
  вернуть токен
}

функция списокПараметров() {
  объект = {}
  пока истина {
    имя = получитьТокен()
    если имя.тип == закрывающая_скобка или имя.тип == конец_файла {
      вернуть объект
    }
    значение = получитьТокен()
    если значение.тип == строка {
      объект[имя.значение] = значение.значение
    }
    если значение.тип = открывающая_скобка {
      объект[имя.значение] = списокПараметров()
    }
  }
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы