Pull to refresh
123
0.1
Ivan Kochurkin @KvanTTT

Software Developer at JetBrains (Kotlin Compiler)

Send message

Они и живут меньше, страдают от проблем с легкими и не только

Целлюлоза по крайней мере разлагается

Ну да, печень под него адаптировалась с древнейших времен

Ну почему - здесь примерно одни световые сутки до Вояджеров.

Тогда уж свертка

вам не удастся её расписать контекстно-свободным образом

Любой более менее состоявшийся и используемый язык невозможно описать не то что контекстно-свободно, а вообще формально, т.к. слишком много всего нужно учитывать, а со временем еще накапливаются всяческие костыли для поддержки обратной совместимости. Исходный код компилятора и будет спецификацией.

Выделение AST в отдельный слой абстракции - это разумно, т.к. парсер можно написать на основе лаконичной контекстно-свободной грамматики (с некоторыми исключениями), с другой стороны AST скрывает более низкоуровневые детали, которые не нужны семантической подсистеме.

А вообще огромный же список известных программ: https://en.wikipedia.org/wiki/Qt_(software)#Applications_using_Qt

Я пользуюсь ворктри постоянно и не совсем понимаю, что вы имеете ввиду под "репозиторий один и всегда синхронизирован."

Есть такой юзкейс: вношу я новые изменения в одном репозитории (коммиты). Если второй репозиторий от него не зависит, то, чтобы увидеть в нем изменения от первого, я должен прогнать коммиты через сервер: push и fetch. В случае отдельного ворктри коммиты сразу же будут доступны во второй папке.

Но вот сабмодули в каждом дереве свои и полностью независимые, что неимоверно доставляет когда в репе много лфс в сабмодулях.

Да, сабмодули раньше их использовал, это боль, вроде в любом случае. Но сейчас у меня монорепы и на работе, и в pet проекте. Это удобно.

механика клона не раскрыта (может оно софт линки использует для не измененных файлов и место не жрет почти)

Если аккуратно вести историю, то физический размер репозитория как по мне не особо большая проблема (учитывая сколько сейчас весят игры, фильмы). Хотя большое количество коммитов уже может быть проблемой, т.к. это порождает тормоза. Правда не уверен, что darcs не будет тормозить на больших репозиториях (возможно об этом даже еще не задумывались).

Если пытаться тщательно вчитываться в текст, то кажется, что у автора достаточно специфическийюз-кейс - параллельная работа над одним проектом в куче веток. Возможно, это какие-то эксперименты в проекте, возможно, тупо незавершённая работа. Патчи приходится перекидывать из одной ветки в другую, обновлять и синхронизировать их туда-сюда. И ветки его подзадолбали.

Звучит как идеальный кейс для использования git worktree. И, насколько понял из статьи, в darcs такая проблема как раз не решается, так как нужно создавать отдельные независимые репы на каждую ветку.

То есть когда мы хотим сделать новую фичу, то darcs создает нам "Новая папка(2)" куда копирует содержимое всей репы? Звучит как трата дискового пространства. 

Это не самая большая проблема, я бы даже сказал меньшая. Главная проблема - репозитории разные и сихронизировать их нужно по отдельности. В то время как в Git с использованием worktree репозиторий один и всегда синхронизирован.

Переход на персистентную память означает принципиальное изменение парадигмы программирования, отказ от концепции «файлов», «буфера» и так далее.

Как из первого следует второе? Почему все вдруг будут должны отказаться от файлов?

Я говорю о том, что пробел должен учитываться, хоть в виде отдельного правила

Это верно.

Мы же говорим про новый язык, в котором необязательно так делать.

Может необязательно, но это не очевидно (не известно какие это неоднозначности может порождать).

Ну и пусть, копирование строки целиком все равно нужно для дальнейшей обработки, и так для всех ID. На этом фоне то что вы где-то сравнили 2 инта вместо 2 строк не дает большой экономии.

Не совсем так - сырые строки из исходного кода нужно процессить, чтобы избавиться от возможных escape последовательностей (и зарепортить ошибки, если они есть). К тому же строки сравнивать дольше - сначала проверяется хеш, а затем производится посимвольное сравнение. Это может повлиять на пефоманс, если это делать на этапе парсера и дальнейших.

Если int это отдельное ключевое слово, которое должно давать T_INT, то его надо определять по выражению r'int(?=[^\w])'.

Если говорить про ANTLR и другие лексеры, то там все работает пооптимальней - строится конечный автомат, который одновременно матчит и INT и ID и в конце приходит к единственному возможному состоянию. Вот это отрицание пробельного символа на конец выглядит несколько избыточно.

Правило WHITESPACE: [ \t\r\n]+ -> skip в ANTLR примерно это и делает, вызывает завершение текущего токена, оно должно быть определено до ключевых слов.

Конкретно WHITESPACE в большинстве случаев не важно где объявлять, т.к. другие токены не начинаются с пробела. А вот ключевые слова как раз надо объявлять до объявление идентификатора, чтобы он не захватывал все последовательности из символов.

Можно и так сказать, но на мой взгляд правильное решение это то, которое устраняет причину проблемы. Проблемы с неоднозначностью разбиения на лексемы идут из-за первоначального разбиения на лексемы.

Чтобы понять, проблема это или нет, надо сначала посмотреть на формальное описание, грамматику языка. Если там написано, что int - это ключевое слово, которое нельзя использовать в качестве идентификатора, значит это не проблема.

И вообще определять int как ключевое слово не совсем корректно, оно ничем не отличается от названия класса.

Зависит от языка, но в большинстве случаев int это именно ключевое слово. А то, что вы имеете в виду это soft-keywords - когда токен может быть как идентификатором, так и ключевым словом. Таким токеном, например, является var в C#. Обычно soft-keyword используются при введении нового синтаксиса, при сохранении обратной совместимости.

Я бы не сказал, что намного. Большинство строк это названия классов, переменных и методов, их значения все равно надо хранить. Операторы короче 4 байт, только некоторые ключевые слова длиннее.

Ну так эта инфа достается из инфы про токен. Парсеру почти во всех случаях неинтересно какое значение принимает ID (за исключением вышеупомянутых soft-keyword).

Построения дерева из потока лексем и его анализа, например рекурсивная обработка арифметических выражений или та же обработка строк в PHP.

Я детально не знаю как работает интерпретатор PHP, но в этом случае может быть оправдано двигаться по символам, потому что PHP - динамический язык и может работать почти построчно. Но в компилируемых языках типа C#, Java, Kotlin и других вся информация содержится в дереве, никакого повторного парсинга там нет. А еще там есть несколько проходов по дереву, и повторный парсинг бы ухудшил производительность.

В теории эти файлы не имеют предельного размера, но есть ограничение по количеству пикселей, и многие декодеры тоже накладывают свои рамки.

Так имеют или не имеют? Ограничение на количество пикселей - это и есть теоретическое ограничение (если для этого не используется BigInt).

Тут дело скорей не в молодежи, а в уровне. Для меня короткое представление намного понятней (хотя мне меньше 40), экономит время на чтении текста. Хотя в статье есть другая интересная информация. Но начинающим может быть сложней ориентироваться в таком формате.

Конкретно для этого случая нет, для определения ключевых слов нужно учитывать пробелы и другие небуквенные символы. В int a оно не должно парситься. Вот с GT и GTEQ да, тут только по длине определять.

Так в случае с int и inta тоже по длине определять. Если точный match с ключевым словом, то это ключевое слово, если хоть на один символ больше, то идентификатор.

для интерполяции строк "Message: ${str}" нужно будет делать отдельный парсинг.

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

А правильное решение - не разбивать на лексемы первым шагом.

Есть разные способ решения, и решение автор тоже является вполне правильным.

Подумайте, что конкретно это дает? Ничего, мы просто заменяем одну последовательность байт на другую.

Дает - последовательность токенов намного короче последовательности символов, а значит быстрей в обработке. Также она имеет больше смысла с точки зрения парсинга.

Зато это создает много проблем, так как на уровне отдельной регулярки мы не знаем контекст, например, была ли уже открывающая кавычка или это комментарий, что и приходится решать заданием порядка.

Лексер имеет общие черты с регулярками, но это не регулярки. Открывающую кавычку, комментарий и другие вещи также можно детектить на уровне лексера (а еще там есть разные режимы).

При этом все равно приходится смотреть "на один токен вперёд". Вместо этого можно просто смотреть на несколько символов вперед.

Смотреть на один токен вперед (в случае лексера - на один символ) - это очень быстрая операция, и она оптимизируется компилятором в быструю jump table с O(1) скоростью. В то время как смотреть на несколько символов вперед медленней.

Будет чуть больше работы процессора на этапе парсинга, зато меньше на следующих этапах.

Это на каких этапах? На этапах после парсинга не нужно ничего, кроме получившегося дерева.

Information

Rating
2,364-th
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity