модуль джесон импорт "исх/строка" импорт "исх/спринтф" фн парсить массив(токены: ДжесонТокены, старт: Цел64, использовано токенов := Цел64, ошибка := Строка): ДжесонМногоЗначений { пусть массив = ДжесонМногоЗначений{значения: ДжесонЗначения[]} пусть текущий индекс := старт если текущий индекс >= длина(токены) { ошибка := "неожиданный конец, ожидалась [" вернуть ДжесонМногоЗначений{} } пусть токен := токены[текущий индекс] выбор пусть т: тип токен { когда ТокенКвадратнаяСкобка: если т.закрывающая { ошибка := спринтф.ф("ожидалась [, а получен $стр", токен.в строку()) вернуть ДжесонМногоЗначений{} } иначе { текущий индекс++ } другое ошибка := спринтф.ф("ожидалась [, а получен $стр", токен.в строку()) вернуть ДжесонМногоЗначений{} } пока текущий индекс < длина(токены) { токен := токены[текущий индекс] пусть значение: ДжесонЗначение := ДжесонЗначение{} выбор пусть т: тип токен { когда ТокенСтрока: значение := ДжесонСтрока{значение: т.значение} текущий индекс++ когда ТокенЧисло: значение := ДжесонЧисло{значение: т.значение} текущий индекс++ когда ТокенБульБуль: значение := ДжесонЛог{значение: т.значение} текущий индекс++ когда ТокенКвадратнаяСкобка: если т.закрывающая { текущий индекс++ использовано токенов := текущий индекс - старт вернуть массив } иначе { ошибка := спринтф.ф("ожидалась значение или ], а получен $стр", токен.в строку()) вернуть ДжесонМногоЗначений{} } когда ТокенФигурнаяСкобка: если ~т.закрывающая { пусть использовано := 0 значение := парсить объект(токены, текущий индекс, использовано, ошибка) если ошибка # "" { вернуть ДжесонМногоЗначений{} } текущий индекс := текущий индекс + использовано } другое ошибка := спринтф.ф("неожиданное значение: $стр", токен.в строку()) вернуть ДжесонМногоЗначений{} } массив.значения.добавить(значение) если текущий индекс >= длина(токены) { ошибка := "неожиданный конец, ожидался , или ]" вернуть ДжесонМногоЗначений{} } токен := токены[текущий индекс] выбор пусть т: тип токен { когда ТокенКвадратнаяСкобка: если т.закрывающая { текущий индекс++ использовано токенов := текущий индекс - старт вернуть массив } иначе { ошибка := спринтф.ф("ожидалась , или ], а получен $стр", токен.в строку()) вернуть ДжесонМногоЗначений{} } когда ТокенЗапятая: текущий индекс++ другое ошибка := спринтф.ф("ожидалась , или ], а получен $стр", токен.в строку()) вернуть ДжесонМногоЗначений{} } } ошибка := "неожиданный конец во время парсинга массива" вернуть ДжесонМногоЗначений{} } фн парсить объект(токены: ДжесонТокены, старт: Цел64, использовано токенов := Цел64, ошибка := Строка): ДжесонОбъект { пусть объект = ДжесонОбъект{} пусть текущий индекс := старт если текущий индекс >= длина(токены) { ошибка := "неожиданный конец, ожидалось {" вернуть ДжесонОбъект{} } пусть токен := токены[текущий индекс] выбор пусть т: тип токен { когда ТокенФигурнаяСкобка: если т.закрывающая { ошибка := спринтф.ф("ожидалась {, а получен $стр", токен.в строку()) вернуть ДжесонОбъект{} } иначе { текущий индекс++ } другое ошибка := спринтф.ф("ожидалась {, а получен $стр", токен.в строку()) вернуть ДжесонОбъект{} } пока текущий индекс < длина(токены) { токен := токены[текущий индекс] пусть ключ := "" выбор пусть т: тип токен { когда ТокенСтрока: ключ := т.значение текущий индекс++ когда ТокенФигурнаяСкобка: если т.закрывающая { текущий индекс++ использовано токенов := текущий индекс - старт вернуть объект } иначе { ошибка := спринтф.ф("ожидалась строка (ключ), а получен $стр", токен.в строку()) вернуть ДжесонОбъект{} } другое ошибка := спринтф.ф("ожидалась строка (ключ), а получен $стр", токен.в строку()) вернуть ДжесонОбъект{} } если текущий индекс >= длина(токены) { ошибка := "неожиданный конец, ожидалось :" вернуть ДжесонОбъект{} } токен := токены[текущий индекс] выбор пусть т: тип токен { когда ТокенДвоеточие: текущий индекс++ другое ошибка := спринтф.ф("ожидался :, а получен $стр", токен.в строку()) вернуть ДжесонОбъект{} } если текущий индекс >= длина(токены) { ошибка := "неожиданный конец, ожидалось значение" вернуть ДжесонОбъект{} } токен := токены[текущий индекс] пусть значение: ДжесонЗначение := ДжесонЗначение{} выбор пусть т: тип токен { когда ТокенСтрока: значение := ДжесонСтрока{значение: т.значение} текущий индекс++ когда ТокенЧисло: значение := ДжесонЧисло{значение: т.значение} текущий индекс++ когда ТокенБульБуль: значение := ДжесонЛог{значение: т.значение} текущий индекс++ когда ТокенФигурнаяСкобка: если ~т.закрывающая { пусть использовано := 0 значение := парсить объект(токены, текущий индекс, использовано, ошибка) если ошибка # "" { вернуть ДжесонОбъект{} } текущий индекс := текущий индекс + использовано } иначе { ошибка := спринтф.ф("ожидалось значение, а получен $стр", токен.в строку()) вернуть ДжесонОбъект{} } когда ТокенКвадратнаяСкобка: если т.закрывающая { ошибка := спринтф.ф("ожидалось значение, а получен $стр", токен.в строку()) вернуть ДжесонОбъект{} } иначе { пусть использовано := 0 значение := парсить массив(токены, текущий индекс, использовано, ошибка) если ошибка # "" { вернуть ДжесонОбъект{} } текущий индекс := текущий индекс + использовано } другое ошибка := спринтф.ф("неожиданное значение: $стр", токен.в строку()) вернуть ДжесонОбъект{} } объект.значения.добавить(ДжесонКлючЗначение{ключ: ключ, значение: значение}) если текущий индекс >= длина(токены) { ошибка := "неожиданный конец, ожидался , или }" вернуть ДжесонОбъект{} } токен := токены[текущий индекс] выбор пусть т: тип токен { когда ТокенЗапятая: текущий индекс++ когда ТокенФигурнаяСкобка: если т.закрывающая { текущий индекс++ использовано токенов := текущий индекс - старт вернуть объект } иначе { ошибка := спринтф.ф("ожидалась , или }, а получен $стр", токен.в строку()) вернуть ДжесонОбъект{} } другое ошибка := спринтф.ф("ожидалась , или }, а получен $стр", токен.в строку()) вернуть ДжесонОбъект{} } } ошибка := "неожиданный конец во время парсинга объекта" вернуть ДжесонОбъект{} } фн парсить токены(токены: ДжесонТокены, ошибка := Строка): ДжесонОбъект { пусть использовано токенов := 0 вернуть парсить объект(токены, 0, использовано токенов, ошибка) } фн парсить*(строка: Строка, ошибка := Строка): ДжесонОбъект { пусть токены = токенизировать(строка, ошибка) если ошибка # "" { вернуть ДжесонОбъект{} } пусть объект = парсить токены(токены, ошибка) если ошибка # "" { вернуть ДжесонОбъект{} } вернуть объект } фн сериализовать*(объект: ДжесонОбъект): Строка { вернуть массив токенов в строку(объект.в токены()) }