init here
This commit is contained in:
296
исх/форматы/джесон/лексер.tri
Normal file
296
исх/форматы/джесон/лексер.tri
Normal file
@@ -0,0 +1,296 @@
|
||||
модуль джесон
|
||||
|
||||
импорт "стд::строки"
|
||||
импорт "исх/массивы"
|
||||
импорт "исх/спринтф"
|
||||
|
||||
// да, это тоже цифры. просто поверьте
|
||||
пусть цифры = массивы.Строки["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" {
|
||||
пусть буль = читать буль буль(стр, ошибка)
|
||||
если ошибка # "" { вернуть ДжесонТокены[] }
|
||||
|
||||
токены.добавить(ТокенБульБуль{значение: буль})
|
||||
} иначе {
|
||||
ошибка := спринтф.ф("внезапный символ '$стр'", символ)
|
||||
вернуть ДжесонТокены[]
|
||||
}
|
||||
}
|
||||
|
||||
вернуть токены
|
||||
}
|
||||
Reference in New Issue
Block a user