модуль джесон импорт "стд::строки" импорт "исх/массивы" импорт "исх/спринтф" // да, это тоже цифры. просто поверьте пусть цифры = массивы.Строки["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "+"] тип ДжесонТокен = класс { } фн (токен: ДжесонТокен) в строку(): Строка { вернуть "пустой токен. где вы его взяли вообще?" } тип ДжесонТокены = []ДжесонТокен фн массив токенов в строку(токены: ДжесонТокены): Строка { пусть рез := "" цикл [номер]токен среди токены { рез := строки.собрать(рез, токен.в строку()) } вернуть рез } тип ТокенФигурнаяСкобка = класс(ДжесонТокен) { закрывающая: Лог := ложь } фн (токен: ТокенФигурнаяСкобка) в строку(): Строка { если токен.закрывающая { вернуть "}" } иначе { вернуть "{" } } тип ТокенКвадратнаяСкобка = класс(ДжесонТокен) { закрывающая: Лог := ложь } фн (токен: ТокенКвадратнаяСкобка) в строку(): Строка { если токен.закрывающая { вернуть "]" } иначе { вернуть "[" } } тип ТокенЗапятая = класс(ДжесонТокен) { } фн (токен: ТокенЗапятая) в строку(): Строка { вернуть "," } тип ТокенДвоеточие = класс(ДжесонТокен) { } фн (токен: ТокенДвоеточие) в строку(): Строка { вернуть ":" } тип ТокенЧисло = класс(ДжесонТокен) { значение: Цел64 := 0 } фн (токен: ТокенЧисло) в строку(): Строка { вернуть спринтф.ф("$цел", токен.значение) } тип ТокенСтрока = класс(ДжесонТокен) { значение: Строка := "" } фн (токен: ТокенСтрока) в строку(): Строка { пусть строка := строки.заменить все(токен.значение, "\\", "\\\\") строка := строки.заменить все(строка, "\"", "\\\"") вернуть спринтф.ф("\"$стр\"", строка) } тип ТокенБульБуль = класс(ДжесонТокен) { значение: Лог := ложь } фн (токен: ТокенБульБуль) в строку(): Строка { если токен.значение { вернуть "true" } иначе { вернуть "false" } } фн съесть символ(стр := Строка, ошибка := Строка): Строка { пусть символ = посмотреть но не трогать(стр, ошибка) если ошибка # "" { вернуть "" } стр := строки.извлечь(стр, 1, длина(стр(:Строка8)) - 1) вернуть символ } фн съесть конкретный символ(стр := Строка, ожидаемый символ: Строка, ошибка := Строка): Строка { пусть символ = посмотреть конкретный символ но не трогать(стр, ожидаемый символ, ошибка) если ошибка # "" { вернуть "" } стр := строки.извлечь(стр, 1, длина(стр(:Строка8)) - 1) вернуть символ } фн посмотреть но не трогать(стр := Строка, ошибка := Строка): Строка { если длина(стр) = 0 { ошибка := "нежданный конец строки" вернуть "" } пусть символ := строки.извлечь(стр, 0, 1) вернуть символ } фн посмотреть конкретный символ но не трогать (стр := Строка, ожидаемый символ: Строка, ошибка := Строка): Строка { если длина(стр) = 0 { ошибка := спринтф.ф("нежданный конец строки, ожидался символ '$символ'", ожидаемый символ) вернуть "" } пусть символ = строки.извлечь(стр, 0, 1) если символ # ожидаемый символ { ошибка := спринтф.ф("ожидался символ '$стр', а пришёл '$символ'", ожидаемый символ, символ) вернуть "" } вернуть символ } фн читать число(стр := Строка, ошибка := Строка): Цел64 { пусть число := "" пока истина { пусть символ = посмотреть но не трогать(стр, ошибка) если ошибка # "" { вернуть 0 } пусть является цифрой := ложь пусть является знаком := ложь цикл [номер]цифра среди цифры { если символ = цифра { является цифрой := истина прервать } } если является цифрой { число := строки.собрать(число, символ) стр := строки.извлечь(стр, 1, длина(стр(:Строка8)) - 1) } иначе { если длина(число) = 0 { ошибка := спринтф.ф("ожидалось число, а пришёл '$символ'", символ) вернуть 0 } пусть целое := 0 пусть номер байта зачем он тебе нужен вообще глупая машина := 0 пусть мне повезло = строки.извлечь цел(число, номер байта зачем он тебе нужен вообще глупая машина, целое) если ~мне повезло { ошибка := спринтф.ф("ошибка преобразования числа '$число'", число) } вернуть целое } } вернуть 0 } фн читать строку(стр := Строка, ошибка := Строка): Строка { съесть конкретный символ(стр, "\"", ошибка) если ошибка # "" { вернуть "" } пусть экран := ложь пусть строка := "" пока истина { пусть символ = съесть символ(стр, ошибка) если ошибка # "" { вернуть "" } если символ = "\\" { экран := ~экран } иначе если символ = "\"" & ~экран { вернуть строка } иначе { экран := ложь строка := строки.собрать(строка, символ) } } вернуть строка } фн читать буль буль(стр := Строка, ошибка := Строка): Лог { пусть истинаСтр = "true" пусть ложьСтр = "false" если строки.есть префикс(стр, истинаСтр) { стр := строки.извлечь(стр, длина(истинаСтр(:Строка8)), длина(стр(:Строка8)) - длина(истинаСтр(:Строка8))) вернуть истина } иначе если строки.есть префикс(стр, ложьСтр) { стр := строки.извлечь(стр, длина(ложьСтр(:Строка8)), длина(стр(:Строка8)) - длина(ложьСтр(:Строка8))) вернуть ложь } иначе { пусть символ = посмотреть но не трогать(стр, ошибка) если ошибка # "" { вернуть ложь } ошибка := спринтф.ф("ожидалось 'true' или 'false', а пришёл '$символ'", символ) вернуть ложь } } фн токенизировать(стр: Строка, ошибка := Строка): ДжесонТокены { пусть токены = ДжесонТокены[] пусть сколько открыто := 0 пока истина { если длина(стр) = 0 & сколько открыто = 0 { прервать } пусть символ = посмотреть но не трогать(стр, ошибка) если ошибка # "" { вернуть ДжесонТокены[] } пусть является цифрой := ложь цикл [номер]цифра среди цифры { если символ = цифра { является цифрой := истина прервать } } если символ = " " | символ = "\n" | символ = "\r" | символ = "\t" { стр := строки.извлечь(стр, 1, длина(стр(:Строка8)) - 1) } иначе если символ = "{" { стр := строки.извлечь(стр, 1, длина(стр(:Строка8)) - 1) токены.добавить(ТокенФигурнаяСкобка{закрывающая: ложь}) сколько открыто := сколько открыто + 1 } иначе если символ = "}" { стр := строки.извлечь(стр, 1, длина(стр(:Строка8)) - 1) токены.добавить(ТокенФигурнаяСкобка{закрывающая: истина}) сколько открыто := сколько открыто - 1 } иначе если символ = "[" { стр := строки.извлечь(стр, 1, длина(стр(:Строка8)) - 1) токены.добавить(ТокенКвадратнаяСкобка{закрывающая: ложь}) } иначе если символ = "]" { стр := строки.извлечь(стр, 1, длина(стр(:Строка8)) - 1) токены.добавить(ТокенКвадратнаяСкобка{закрывающая: истина}) } иначе если символ = "," { стр := строки.извлечь(стр, 1, длина(стр(:Строка8)) - 1) токены.добавить(ТокенЗапятая{}) } иначе если символ = ":" { стр := строки.извлечь(стр, 1, длина(стр(:Строка8)) - 1) токены.добавить(ТокенДвоеточие{}) } иначе если является цифрой { пусть число = читать число(стр, ошибка) если ошибка # "" { вернуть ДжесонТокены[] } токены.добавить(ТокенЧисло{значение: число}) } иначе если символ = "\"" { пусть строка = читать строку(стр, ошибка) если ошибка # "" { вернуть ДжесонТокены[] } токены.добавить(ТокенСтрока{значение: строка}) } иначе если символ = "t" | символ = "f" { пусть буль = читать буль буль(стр, ошибка) если ошибка # "" { вернуть ДжесонТокены[] } токены.добавить(ТокенБульБуль{значение: буль}) } иначе { ошибка := спринтф.ф("внезапный символ '$стр'", символ) вернуть ДжесонТокены[] } } вернуть токены }