Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.12.24 05:19
Оценка:
Я так понял, что штатный способ прямого порождения байткода Java — это библиотека AST.
А есть ли аналог этой библиотеки на тайпскрипте?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Хочется странного
От: · Великобритания  
Дата: 15.12.24 08:51
Оценка:
Здравствуйте, Sinclair, Вы писали:

S> Я так понял, что штатный способ прямого порождения байткода Java — это библиотека AST.

S> А есть ли аналог этой библиотеки на тайпскрипте?
А у тайпскрипта разве есть байткод? wasm что-ли?
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[2]: Хочется странного
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 15.12.24 09:13
Оценка: :)
Здравствуйте, ·, Вы писали:

·>А у тайпскрипта разве есть байткод? wasm что-ли?

Я почему-то подумал, что коллега хочет именно Java-байткод на TS.
Под определение странного это вписывается вполне.
Re: Хочется странного
От: Слава  
Дата: 15.12.24 09:58
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Я так понял, что штатный способ прямого порождения байткода Java — это библиотека AST.

S>А есть ли аналог этой библиотеки на тайпскрипте?

Наверное есть на С++, а оттуда уже можно сделать wasm и к нему интерфейс на TS.
Re[2]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.12.24 16:07
Оценка:
Здравствуйте, ·, Вы писали:
·>А у тайпскрипта разве есть байткод? wasm что-ли?
Нет. Байткод нужен джавный. Просто писать компиляторщину на Java — это боль.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Хочется странного
От: · Великобритания  
Дата: 15.12.24 16:48
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>·>А у тайпскрипта разве есть байткод? wasm что-ли?

S>Нет. Байткод нужен джавный. Просто писать компиляторщину на Java — это боль.
А, понял вопрос. Да, сабж, очень сильно. А задача то какая? Зачем генерить именно байт-код? Может джаву лучше? Ещё кстати scala или kotlin если языка не хватает.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[4]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 01:23
Оценка:
Здравствуйте, ·, Вы писали:
·>А, понял вопрос. Да, сабж, очень сильно. А задача то какая? Зачем генерить именно байт-код? Может джаву лучше? Ещё кстати scala или kotlin если языка не хватает.
Задача — сделать компилятор воображаемого языка.
В JVM — потому, что это проще, чем в натив (и даже в LLVM).
В принципе, можно и Java-код порождать, но это не даст студентам понимания устройства байт-кода
Вот, кстати, смотрю в сторону kotlin. Похоже, на нём тоже неплохо пишется компилятор. Но для него, я так понял, в качестве IDE можно использовать только IntelliJ, т.к. интеграция с VS Code у него так себе.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Хочется странного
От: amironov79  
Дата: 16.12.24 06:26
Оценка: 82 (1)
Здравствуйте, Sinclair, Вы писали:

S>Задача — сделать компилятор воображаемого языка.

S>В JVM — потому, что это проще, чем в натив (и даже в LLVM).

GraalJs? Ну и "typescript for jvm" находит какие-то проекты, в большинстве случаев архивные.

S>В принципе, можно и Java-код порождать, но это не даст студентам понимания устройства байт-кода

S>Вот, кстати, смотрю в сторону kotlin. Похоже, на нём тоже неплохо пишется компилятор. Но для него, я так понял, в качестве IDE можно использовать только IntelliJ, т.к. интеграция с VS Code у него так себе.

Ну Kotlin с IntelliJ (есть community версия) всяко лучше будет, чем натягивать Ts на Jvm
Re[6]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 06:57
Оценка:
Здравствуйте, amironov79, Вы писали:

A>GraalJs? Ну и "typescript for jvm" находит какие-то проекты, в большинстве случаев архивные.

Большинство этих проектов — про исполнение typescript в JVM. А мне как раз это не очень надо, typescript пускай себе в node.js работает.

A>Ну Kotlin с IntelliJ (есть community версия)

Ладно, попробуем.
A>всяко лучше будет, чем натягивать Ts на Jvm
Натягивать TS на JVM нужды нет. Всё, что нужно — это порождать .class. Это можно делать из примерно любого языка — С++, Pascal, Java, you name it.
Вопрос только в доступности инструментальных средств.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Хочется странного
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 16.12.24 07:29
Оценка: 82 (1)
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, ·, Вы писали:

S>·>А, понял вопрос. Да, сабж, очень сильно. А задача то какая? Зачем генерить именно байт-код? Может джаву лучше? Ещё кстати scala или kotlin если языка не хватает.
S>Задача — сделать компилятор воображаемого языка.
О! Это какой-то курс по трансляторам?
А можете поделиться — вы планируете чтобы студенты и фронт (анализ) и бэк (генерацию) писали врукопашную?
Я в свое время на такое не решился (но там был курс для заочников — они бы просто не успели вообще всё).

И выбрал вариант:
— используем генератор анализаторов (я брал ANTLR)
— для генерации использовал выход в виде IL-файла

Мне такой вариант понравился тем, что:
— всё наглядно: сразу видно, что получилось
— можно использовать текстовые шаблоны генерации — это актуально если делать DSL, который порождает не сразу байткод, а код на другом языке.
Этот подход очень развит в том же ANTLR, с его глубокой интеграцией в текстовые шаблоны

Я делал по практике пару "методичек". Какраз по ANTLR и немного по IL.
Если вдруг заинтересует, можете посмотреть https://mihailromanov.github.io/docs/tutorials/
Но ... сейчас я бы всё сделал иначе + это всё очень устарело, но вдруг натолкнет на интересные мысли...

S>В принципе, можно и Java-код порождать, но это не даст студентам понимания устройства байт-кода

А если рассмотреть вариант с .Net?
Т.е. фронт на C# (или даже F#!) а для генерации, что-то типа https://www.nuget.org/packages/Fluent.IL

Или есть какие-то ограничения и .Net нельзя ни в коем случае?

P.S. Мне еще в качестве генераторов парсеров очень понравился Irony https://www.nuget.org/packages/Irony

Минимум зависимостей и не нужны специальные инструменты. По сути DSL для описания языка прямо на C#.
Re[6]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 08:12
Оценка: 20 (1)
Здравствуйте, Михаил Романов, Вы писали:
МР>О! Это какой-то курс по трансляторам?
Да. "Методы трансляции и компиляции".
МР>А можете поделиться — вы планируете чтобы студенты и фронт (анализ) и бэк (генерацию) писали врукопашную?
Нет, пусть они пользуются готовыми инструментами. Но им нужно научиться самим писать грамматики и трансформировать код.
У нас этот курс уже есть, но к нему есть претензии. Основная претензия — чрезмерная воображаемость языков.
Код практики пишется на языке flow9, которым пользуется примерно столько же народу, сколько у нас студентов .
При этом компиляция и верификация пишется для недетерминированного языка, что сильно ломает мозг студентам.
Вот, думаем над тем, чтобы
а) убрать реализацию своей VM — там всё равно VM получается ущербной, и совершенно непохожей на настоящие VM.
б) заменить недетерминированный воображаемый язык на что-то больше похожее на обычные императивные языки
в) использовать в качестве основного языка программирования что-то более промышленно-стандартное, то есть хорошо документированное и стабильно работающее.

МР>- используем генератор анализаторов (я брал ANTLR)

У нас используется PEG. У PEG-грамматик есть ряд преимуществ перед традиционными LL(*), LR(k) и прочимию LALR(1)/LR/IELR(1)/GLR
МР>- для генерации использовал выход в виде IL-файла
Ну, я думал над CIL в качестве целевого языка. Но по ряду причин лучше было бы взять Java. В частности, у меня есть желание научить их сразу генерировать отладочные символы, что даст возможность интерактивной отладки программок на их воображаемом языке. На майкрософтовской стороне забора это требует разбираться с PDB, который вообще ортогонален кодогенерации; а в жаве всё лежит в тех же .class файлах.

МР>- можно использовать текстовые шаблоны генерации — это актуально если делать DSL, который порождает не сразу байткод, а код на другом языке.

Порождать текстовый язык мы их и так будем учить — там одна из задач сводится к генерации системы уравнений для Z3 на его языке SMTLIB.
МР>Этот подход очень развит в том же ANTLR, с его глубокой интеграцией в текстовые шаблоны
МР>Я делал по практике пару "методичек". Какраз по ANTLR и немного по IL.
МР>Если вдруг заинтересует, можете посмотреть https://mihailromanov.github.io/docs/tutorials/
Да, спасибо, очень интересно.
МР>Но ... сейчас я бы всё сделал иначе + это всё очень устарело, но вдруг натолкнет на интересные мысли...

МР>А если рассмотреть вариант с .Net?

МР>Т.е. фронт на C# (или даже F#!) а для генерации, что-то типа https://www.nuget.org/packages/Fluent.IL
Если честно, C# — не лучший язык для таких вещей.
Идеально — строготипизированный язык с автовыводом типов. В частности, это позволяет очень сильно упростить описания грамматик в PEG, потому что не надо выписывать result type для каждого семантического действия.
Из промышленных языков больше всего похож на то, что надо, собственно typescript. Генерация кода — да, в дотнете она сделана сильно более понятно, чем в Java.
Для C# есть библиотека PEG-разбора, но грамматики на ней.... обнять и плакать. На F# не смотрел.
Никакого сравнения с грамматиками Lingo, которая встроена в flow9.
МР>Или есть какие-то ограничения и .Net нельзя ни в коем случае?
Да в целом-то ограничений нет; если бы просматривалась возможность покрыть все аспекты курса, оставаясь в рамках дотнета — то можно было бы наверное и его протащить. Но пока выглядит так, что Java в среднем встретит больше понимания (и органичнее впишется в другие курсы, которые читаются тем же студентам).

МР>P.S. Мне еще в качестве генераторов парсеров очень понравился Irony https://www.nuget.org/packages/Irony

Посмотрим.
МР>Минимум зависимостей и не нужны специальные инструменты. По сути DSL для описания языка прямо на C#.
Документации маловато. Из сэмплов выглядит так, что он генерирует LR парсеры?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Хочется странного
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 16.12.24 09:50
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Код практики пишется на языке flow9, которым пользуется примерно столько же народу, сколько у нас студентов .

Ну да, я впервые услышал https://github.com/area9innovation/flow9
Прикольно, что контрибьютеры в подавляющем большинстве из России или с Украины

S>У нас используется PEG. У PEG-грамматик есть ряд преимуществ перед традиционными LL(*), LR(k) и прочимию LALR(1)/LR/IELR(1)/GLR

У меня тут мало опыта, поэтому ничего сказать не могу. Наверное так и есть.

S>Ну, я думал над CIL в качестве целевого языка. Но по ряду причин лучше было бы взять Java. В частности, у меня есть желание научить их сразу генерировать отладочные символы, что даст возможность интерактивной отладки программок на их воображаемом языке. На майкрософтовской стороне забора это требует разбираться с PDB, который вообще ортогонален кодогенерации; а в жаве всё лежит в тех же .class файлах.

Опять же не разбирался, не могу ничего сказать.
Вроде как есть такие вещи как как ILGenerator.MarkSequencePointCore, но они тянут за собой пространство System.Diagnostics.SymbolStore, так что, похоже, всё не так просто как мне казалось.

S>Если честно, C# — не лучший язык для таких вещей.

S>Идеально — строготипизированный язык с автовыводом типов. В частности, это позволяет очень сильно упростить описания грамматик в PEG, потому что не надо выписывать result type для каждого семантического действия.
S>Из промышленных языков больше всего похож на то, что надо, собственно typescript.
Понятно. Я, увы, забросил этот вопрос весьма давно — хочется вернуться и посмотреть на что-то еще помимо, простых генераторов и как работается с ними в простых императивных языках. Но времени как всегда нет ни на что.

По поводу генерации — я немного ввел вас в заблуждение (хотя, может вы и были в курсе).
В .Net после Framework и вплоть до 9 версии, была недоступна функциональность выгрузки сгенерированной сборки вовне.
В 9 появился PersistedAssemblyBuilder, но всякие обертки над Emit его пока не подхватили.
А если взглянуть на использование его напрямую (на базовом Emit) то, конечно, делается печально https://learn.microsoft.com/en-us/dotnet/fundamentals/runtime-libraries/system-reflection-emit-persistedassemblybuilder.

МР>>Минимум зависимостей и не нужны специальные инструменты. По сути DSL для описания языка прямо на C#.

S>Документации маловато. Из сэмплов выглядит так, что он генерирует LR парсеры?
Это правда. Я смотрел на примеры и через утилиту (GrammarExplorer вроде)

По грамматике, вроде как LALR https://www.codeproject.com/Articles/22650/Irony-NET-Compiler-Construction-Kit?msg=2381770

Ну и я подумал, что вас он вряд ли впечатлит — там нормальной типизации узлов разбора не будет из коробки, а значит всё равно в рукопашную резвись с тем, что он там наразбирал...
Re[5]: Хочется странного
От: Pzz Россия https://github.com/alexpevzner
Дата: 16.12.24 11:14
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Задача — сделать компилятор воображаемого языка.

S>В JVM — потому, что это проще, чем в натив (и даже в LLVM).

А ты в курсе, что есть древний, как UNIX System 7, паттерн делать такие компиляторы, используя Си в качестве промежуточного представления? А потом уже штатным компилятором Си — в нативный код.
Re[6]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 12:16
Оценка:
Здравствуйте, Pzz, Вы писали:
Pzz>А ты в курсе, что есть древний, как UNIX System 7, паттерн делать такие компиляторы, используя Си в качестве промежуточного представления? А потом уже штатным компилятором Си — в нативный код.
В курсе. А ещё можно их фортрану обучать на перфокартах
Мы-то хотим более-менее современному их обучать. В частности, нет никакого желания тиранить их лексерами — ни рукопашными, ни автопорождёнными.
Ну и с представлениями тоже — никто в здравом уме не будет порождать код для JVM через Си как промежуточный язык.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[8]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 12:44
Оценка: 22 (2)
Здравствуйте, Михаил Романов, Вы писали:
МР>Ну да, я впервые услышал https://github.com/area9innovation/flow9
МР>Прикольно, что контрибьютеры в подавляющем большинстве из России или с Украины
Отож.

МР>У меня тут мало опыта, поэтому ничего сказать не могу. Наверное так и есть.

Главное — он безлексерный и unambiguous. Нет никаких конфликтов, которые нужно как-то разрешать.
Плюс — очень естественно обобщается на инкрементальность.

МР>Вроде как есть такие вещи как как ILGenerator.MarkSequencePointCore, но они тянут за собой пространство System.Diagnostics.SymbolStore, так что, похоже, всё не так просто как мне казалось.

Вот и я не разбирался .

МР>В .Net после Framework и вплоть до 9 версии, была недоступна функциональность выгрузки сгенерированной сборки вовне.

Это вообще не проблема. Я когда переезжал с фреймворка на Core, взял https://github.com/Lokad/ILPack и поехал.
МР>В 9 появился PersistedAssemblyBuilder, но всякие обертки над Emit его пока не подхватили.
МР>А если взглянуть на использование его напрямую (на базовом Emit) то, конечно, делается печально https://learn.microsoft.com/en-us/dotnet/fundamentals/runtime-libraries/system-reflection-emit-persistedassemblybuilder.

МР>По грамматике, вроде как LALR https://www.codeproject.com/Articles/22650/Irony-NET-Compiler-Construction-Kit?msg=2381770

Спасибо за внятный пример.
Вот по нему уже видно, за что можно не любить все эти тяжеловесные парсер-генераторы.
Для сравнения — полный код PEG-грамматики, которая разбирает арифметические выражения и строит типизированное AST на Lingo:
expr = sum;
sum = mul:head summand*:tail { buildChain(:head, :tail) };
summand = (("+" {Add()}) | ("-" {Sub()})):op mul:s { BinOperand(:op, :s) };
mul = pow:head factor*:tail { buildChain(:head, :tail)};
factor = (("*" {MulOp()}) | ("/" {DivOp()})):op pow:m{ BinOperand(:op, :m) };
pow = atom:base "**" pow:degree { Bin(:base, :degree, Pow()) } | atom;
atom = var | number | "(" expr:e ")" {:e};
var = (letter digit*) $vn { Var($vn) }; 
number = (digit+) $n {Int(s2i($n))};
digit = '0'-'9';
letter = ('a' - 'z' | 'A' - 'Z');

Для того, чтобы это взлетело, нужны описания типов AST на стороне flow9 и однострочная функция для сворачивания левоассоциативных выражений:

Expr ::= Bin, Var, Int;
BinOperand(op: BinOp, right: Expr);
Bin(left: Expr, right: Expr, op:BinOp);
BinOp ::= AddOp, SubOp, MulOp, DivOp, PowOp;
AddOp(); SubOp(); MulOp(); DivOp(); PowOp();


МР>Ну и я подумал, что вас он вряд ли впечатлит — там нормальной типизации узлов разбора не будет из коробки, а значит всё равно в рукопашную резвись с тем, что он там наразбирал...

Именно. Гораздо удобнее работать с типизированным AST.
Как раз автовывод типов этим и прекрасен — ведь любое правило в PEG-грамматике описывается семантическим действием; если тип этого действия известен, то и тип правила известен.
Остаётся правильно вывести тип для правил с альтернативами — и мы получаем то, что нужно.
По идее это должно ездить и на typescript; но пока что я не нашёл идеальной ts-реализации PEG. PEGjs выглядит заброшенным и он всё же JS, а не TS; Ohm неплох (и умеет инкрементальность из коробки), но у них очень странные идеи про то, как привязывать семантические действия к грамматике.
В общем, нету серебряной пули
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Хочется странного
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.12.24 13:52
Оценка: -1 :)
Здравствуйте, Sinclair, Вы писали:

S>Я так понял, что штатный способ прямого порождения байткода Java — это библиотека AST.

S>А есть ли аналог этой библиотеки на тайпскрипте?

Пишем кастомный трансформер AST на TypeScript
и солнце б утром не вставало, когда бы не было меня
Re[2]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 14:23
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Пишем кастомный трансформер AST на TypeScript

Спасибо, но это не про то. У меня (пока) нет задачи улучшить компилятор тайпскрипта.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Хочется странного
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.12.24 14:27
Оценка: -1 :)
Здравствуйте, Sinclair, Вы писали:


S>>Пишем кастомный трансформер AST на TypeScript

S>Спасибо, но это не про то. У меня (пока) нет задачи улучшить компилятор тайпскрипта.

Не там есть пример получения ast.json

Каждый раз, когда мне необходимо проделать что-либо с AST, я первым делом открываю astexplorer.net, а затем начинаю действовать. Этот инструмент позволяет проанализировать AST, созданное различными парсерами, в том числе babel/parser и парсером компилятора TypeScript. С помощью astexplorer.net можно визуализировать структуры данных, с которыми вам предстоит работать, и ознакомиться с типами узлов AST каждого парсера.


Взгляните на пример файла исходных данных и AST, созданное на его основе с помощью babel-parser:



example.ts
import { protos } from 'my_company_protos'

export type User = protos.user.User;


ast.json
{
  "type": "Program",
  "start": 0,
  "end": 80,
  "loc": {
    "start": {
      "line": 1,
      "column": 0
    },
    "end": {
      "line": 3,
      "column": 36
    }
  },
  "comments": [],
  "range": [
    0,
    80
  ],
  "sourceType": "module",
  "body": [
    {
      "type": "ImportDeclaration",
      "start": 0,
      "end": 42,
      "loc": {
        "start": {
          "line": 1,
          "column": 0
        },
        "end": {
          "line": 1,
          "column": 42
        }
      },
... большой файл
и солнце б утром не вставало, когда бы не было меня
Re[4]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.12.24 16:38
Оценка:
Здравствуйте, Serginio1, Вы писали:
S> Не там есть пример получения ast.json
Там пример получения AST программы, написанной на typescript.
Предсказуемо, для этого применяется компилятор TS
У нас задача совсем другая — нужно получить AST своего воображаемого языка, а потом сгенерировать для него байткод.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Хочется странного
От: GarryIV  
Дата: 17.12.24 12:00
Оценка: 84 (1)
Здравствуйте, Sinclair, Вы писали:

S>Я так понял, что штатный способ прямого порождения байткода Java — это библиотека AST.

Есть еще JEP 466: Class-File API (Second Preview)
WBR, Igor Evgrafov
Re[3]: Хочется странного
От: novitk США  
Дата: 17.12.24 19:49
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, ·, Вы писали:

S>·>А у тайпскрипта разве есть байткод? wasm что-ли?
S>Нет. Байткод нужен джавный. Просто писать компиляторщину на Java — это боль.
Scala? Cotlin? Clojure? https://github.com/caoccao/Javet/?
Re[4]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.12.24 01:45
Оценка:
Здравствуйте, novitk, Вы писали:
N>Scala? Cotlin? Clojure? https://github.com/caoccao/Javet/?
Clojure недостаточно типизирована. Учебный компилятор — не то место, которое хочется в шесть слоёв покрывать тестами.
На Kotlin смотрю пока. Вот, вчера поставил IntelliJ.
Есть для него библиотека PEG-парсинга?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Хочется странного
От: · Великобритания  
Дата: 18.12.24 10:57
Оценка: 84 (1) +1
Здравствуйте, Sinclair, Вы писали:

S> N>Scala? Cotlin? Clojure? https://github.com/caoccao/Javet/?


S> Clojure недостаточно типизирована. Учебный компилятор — не то место, которое хочется в шесть слоёв покрывать тестами.

S> На Kotlin смотрю пока. Вот, вчера поставил IntelliJ.
S> Есть для него библиотека PEG-парсинга?
Для всяких CS-изысков обычно всё-таки Скалу юзают. Если я правильно понял, тут вроде всё что надо: https://github.com/sirthias/parboiled2

Для котлина тоже вроде гуглится, но по-моему не так красиво.
https://kpeg.io/
https://github.com/mikaelhg/kotlin-peg-dsl
https://github.com/h0tk3y/better-parse
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[5]: Хочется странного
От: novitk США  
Дата: 18.12.24 13:41
Оценка: 84 (1)
Здравствуйте, Sinclair, Вы писали:

S>Clojure недостаточно типизирована. Учебный компилятор — не то место, которое хочется в шесть слоёв покрывать тестами.

S>На Kotlin смотрю пока. Вот, вчера поставил IntelliJ.
я бывший скалист, Котлином не пользовался. ИМХО Скалка самый удобный и продвинытый язык из немаргинальных. Для компилятора сам бог велел.

S>Есть для него библиотека PEG-парсинга?

Для скалки в компиляторо-писание все есть:
https://github.com/lauris/awesome-scala?tab=readme-ov-file#parsing
Отредактировано 18.12.2024 16:34 novitk . Предыдущая версия . Еще …
Отредактировано 18.12.2024 13:50 novitk . Предыдущая версия .
Отредактировано 18.12.2024 13:46 novitk . Предыдущая версия .
Re: Хочется странного
От: alsemm Россия  
Дата: 25.12.24 15:34
Оценка: 84 (1)
Здравствуйте, Sinclair, Вы писали:

S>Я так понял, что штатный способ прямого порождения байткода Java — это библиотека AST.

S>А есть ли аналог этой библиотеки на тайпскрипте?
Можно попробовать запустить AST в среде JS через TeaVM. Берем AST, прогоняем через TeaVM, получаем AST, которую можно запускать в среде JS. Вроде бы то, что хочется получить.
Re[5]: Хочется странного
От: elmal  
Дата: 27.12.24 17:43
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Задача — сделать компилятор воображаемого языка.

S>В JVM — потому, что это проще, чем в натив (и даже в LLVM).
S>В принципе, можно и Java-код порождать, но это не даст студентам понимания устройства байт-кода
А зачем какие то библиотеки? Почему нельзя тупо писать байтики напрямую? Одно дело когда ты байткод сам анализируешь, тут библиотека поможет и снимет куча геморроя. Но если задача байткод генерить, да еще в учебных целях — ИМХО лучше тупо в файлик сразу байты писать да и все. Если не ставится задача вообще все покрыть, а чтоб было покрытие ограниченного подмножества — достаточно просто быстро и интересно делается.
Re[6]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.12.24 03:50
Оценка:
Здравствуйте, elmal, Вы писали:

E>Здравствуйте, Sinclair, Вы писали:


S>>Задача — сделать компилятор воображаемого языка.

S>>В JVM — потому, что это проще, чем в натив (и даже в LLVM).
S>>В принципе, можно и Java-код порождать, но это не даст студентам понимания устройства байт-кода
E>А зачем какие то библиотеки? Почему нельзя тупо писать байтики напрямую? Одно дело когда ты байткод сам анализируешь, тут библиотека поможет и снимет куча геморроя. Но если задача байткод генерить, да еще в учебных целях — ИМХО лучше тупо в файлик сразу байты писать да и все. Если не ставится задача вообще все покрыть, а чтоб было покрытие ограниченного подмножества — достаточно просто быстро и интересно делается.
Чтобы генерить байтики, нужно знать, какие байтики генерить.
Я не очень разбираюсь в JVM-ном байткоде, но из опыта дотнетного байткода уже понятно, что
а) мнемоники команд. Банальная штука типа "положи в стек целую константу" требует енкодинга команды и енкодинга константы. Делать это каждый раз руками? Код становится невозможно даже прочитать, не то что поддерживать. Интуитивно хочется иметь готовую функцию типа EmitLoadConstant(x byteCodeStream, int value) или byteCodeStream.EmitLoadConstant(value).
б) goto. Не хочется вручную вычислять байтовые смещения с риском промахнуться. Удобнее иметь функции вида MarkLabel() c возможностью использовать результат этой функции в эмите jump-инструкций
в) метаданные. Банальный Call использует в аргументах method token, который весьма нетривиально устроен. Вычислять его вручную — крайне громоздко.
г) предсказание будущего. Каждый метод указывает в заголовке размер байт-кода, количество переменных, а также максимальную глубину стека. При кодогенерации это довольно-таки тяжело оценить заранее — так что либо делать два прохода по внутреннему представлению, либо, всё-таки, инкапсулировать это всё в некий класс, отвечающий за порождение байтиков, который всё это рассчитает самостоятельно с гарантиями корректности и без замусоривания пользовательского кода.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Хочется странного
От: elmal  
Дата: 28.12.24 18:55
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>а) мнемоники команд. Банальная штука типа "положи в стек целую константу" требует енкодинга команды и енкодинга константы. Делать это каждый раз руками? Код становится невозможно даже прочитать, не то что поддерживать. Интуитивно хочется иметь готовую функцию типа EmitLoadConstant(x byteCodeStream, int value) или byteCodeStream.EmitLoadConstant(value).

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

Относительно готовых функция и того, как ты считаешь они должны выглядеть. То, что ты привел — это нарушение Single Responsibility Principle в чистом виде. Я бы делал проще, функция encode, на вход енам команды и опциональные параметры (если язык понавороченнее, то можно и поинтереснее фичи использовать вроде Sealed Class и тому подобному), на выходе массив байт. Внутри логика преобразования, причем весьма тривиальная. И отдельно уже идет запись в стрим или еще куда, уже стандартными средствами. Базовый принцип — нельзя смешивать логику и ввод вывод, это всегда должно быть отделено. В идеале сначала ввод без логики, затем операции, затем вывод без логики, тривиальный — если так делать, то код прекрасно становится читаемый и поддерживаемый.

Кстати рекомендую прочитать:
https://habr.com/ru/companies/jugru/articles/858418/
Принцип блин в 1977 сформулирован!

S>б) goto. Не хочется вручную вычислять байтовые смещения с риском промахнуться. Удобнее иметь функции вида MarkLabel() c возможностью использовать результат этой функции в эмите jump-инструкций

Тоже самое, эту функцию написать самому тривиально, там кода 3 строчки. Если студент не в состоянии это написать сам — рано ему компиляторами заниматься.

S>г) предсказание будущего. Каждый метод указывает в заголовке размер байт-кода, количество переменных, а также максимальную глубину стека. При кодогенерации это довольно-таки тяжело оценить заранее — так что либо делать два прохода по внутреннему представлению, либо, всё-таки, инкапсулировать это всё в некий класс, отвечающий за порождение байтиков, который всё это рассчитает самостоятельно с гарантиями корректности и без замусоривания пользовательского кода.

Да, нужно инкапсулировать. И там не будет ничего сложного и громоздкого. Можно через ленивые вычисления и все такое, совершенно не обязательно в несколько проходов. А на деле — а хоть бы и в несколько проходов, что тут такого? Ну медленнее, но зато код будет вообще шикарный и простой, прекрасно тестируемый. Хоть 10 проходов, лишь бы почище сам код был.

Вот студенты и должны научиться это делать. Написать компилятор учебный — это именно требуется разобраться как подобные вещи делаются с нуля. Без библиотек кодогенерации, только через стандартные структуры данных, средства языка и все такое. Для начала следует сделать интерпретатор, крайне б желательно было осилить книжку SICP, чтоб мозги на место поставить, и там собственно пример как делается интерпретатор вполне есть. Изменений как из интерпретатора сделать компилятор, кстати, будет вообще минимум! Тупо бежишь по AST, но не непосредственно выполняешь, а делаешь кодогенерарацию.

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

На деле — прекрасная учебная задача, на которой студенты могут набить руку и попробовать не городить спагетти говнокод, а написать прекрасный компактный и поддерживаемый код, пусть и не идеально шустрый, однопроходный и все такое. Однопроходный тоже кстати можно написать достаточно компактно и поддерживаемо, но напрягаться умственно придется сложнее, все эти ленивости и все такое, контекст держать — если нет цели сделать максимально шустро, лучше сделать просто максимально понятно. Нужно именно приучить студентов не говнокодить копипастить, а бороться со сложностью и запутанностью, походя самим писать вспомогательные функции для удобства на скорость, причем чтоб тратить на это меньше времени, чем если говнокодить все в лоб! А то ведь большинство такому не научится даже на работе реальной, тупо никто не покажет как можно, так и будут блин ждать пока добрый буржуй напишет удобную функцию, а если функции нет, так и будут копипастить блин один и тот же код и даже мысли блин не возникнет написать так, как удобно. Собственно большинство библиотек тоже ни фига не удобны в использовании.

А вообще, я блин в шоке насколько мало программистов с профильным блин образованием в курсе как работают интерпретаторы, компиляторы и т.д. Не на детальном уровне, а на базовом и общем!!!! Мне в обычной работе, если что, неоднократно приходилось это писать. Чаще всего интерпретаторы, именно компилятор не было смысла, но кодогенератор тоже приходилось писать далеко не один раз, и напишу еще не раз. Вроде не совсем ненужный навык.

PS Хотел еще ссылку на охрененный курс по компиляторам на ютубе привести, но блин не могу найти. Даже университет не помню какой, толь MIT, толь Беркли. Там несколько, более ранний был довольно стандартный, профессора звали что то вроде Кубианович, начинается точно на Куби, а вот более поздний там преподавали поинтереснее и был фокус на написании DSL и еще там в названии было Hack Your Language. Очень мне б блин самому не помешало пересмотреть, а то как понадобилось однопроходный парсер с приоритетами операций писать — я блин нормально хрен написал, тупо забыл как это все элегантно делается.
Re[8]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.12.24 09:07
Оценка: +2
Здравствуйте, elmal, Вы писали:

E>А что, сейчас такую вещь как словари, студенты не знают? Причем не знают в джаваскрипте, где это основная структура данных? Я вот считаю, что прежде чем рассказывать студентам как компилятор работает, нужно их с базовыми структурами данных познакомить и приучить их использовать. А так да, я в курсе что сейчас и выпускают специалистов без этого знания.

Непонятно, при чём тут словари.

E>Относительно готовых функция и того, как ты считаешь они должны выглядеть. То, что ты привел — это нарушение Single Responsibility Principle в чистом виде.

С чего бы это вдруг?
E>Я бы делал проще, функция encode, на вход енам команды и опциональные параметры (если язык понавороченнее, то можно и поинтереснее фичи использовать вроде Sealed Class и тому подобному), на выходе массив байт.
В принципе, можно и так. Хотя не очень понятно, как будет выглядеть сигнатура этой функции. И как потом этой функцией пользоваться.
E>Внутри логика преобразования, причем весьма тривиальная. И отдельно уже идет запись в стрим или еще куда, уже стандартными средствами.
Вы так говорите, как будто я предлагал что-то другое.
E>Базовый принцип — нельзя смешивать логику и ввод вывод, это всегда должно быть отделено. В идеале сначала ввод без логики, затем операции, затем вывод без логики, тривиальный — если так делать, то код прекрасно становится читаемый и поддерживаемый.

E>Кстати рекомендую прочитать:

E>https://habr.com/ru/companies/jugru/articles/858418/
E>Принцип блин в 1977 сформулирован!
Спасибо за ссылку на общеизвестное.
По-прежнему непонятно, как то, что вы предлагаете, противоречит идее библиотеки.

E>Да, нужно инкапсулировать. И там не будет ничего сложного и громоздкого. Можно через ленивые вычисления и все такое, совершенно не обязательно в несколько проходов. А на деле — а хоть бы и в несколько проходов, что тут такого? Ну медленнее, но зато код будет вообще шикарный и простой, прекрасно тестируемый. Хоть 10 проходов, лишь бы почище сам код был.

E>Вот студенты и должны научиться это делать. Написать компилятор учебный — это именно требуется разобраться как подобные вещи делаются с нуля. Без библиотек кодогенерации, только через стандартные структуры данных, средства языка и все такое. Для начала следует сделать интерпретатор, крайне б желательно было осилить книжку SICP, чтоб мозги на место поставить, и там собственно пример как делается интерпретатор вполне есть. Изменений как из интерпретатора сделать компилятор, кстати, будет вообще минимум! Тупо бежишь по AST, но не непосредственно выполняешь, а делаешь кодогенерарацию.
В итоге 3/4 курса студенты будут заниматься нудным выпиливанием лобзиком по вазелину, и только 1/4 — собственно компиляцией.

E>Если же пользоваться готовыми библиотеками — ни хрена студенты не поймут! И придется еще тратить время на то, чтоб с библиотекой разобраться. И далеко не факт что API библиотеки будет сделано достаточно хорошо. В результате что был курс, что его не было — в памяти не останется вообще ни черта! Особенно если упор делать не на реализацию и программу, а на отчет и его защиту с презентациями, как у нас тут некоторые делают, да еще и ЕСПД привлекают начиная с первого курса для даже лабораторных.

Если бы у нас было всё время мира — да, можно всё пилить с нуля. Но у нас — 1 семестр, и это не единственный предмет в семестре. Положа руку на сердце: вы напишете с нуля компилятор небольшого языка с кодогенерацией и статической верификацией корректности за 32 часа?

E>А вообще, я блин в шоке насколько мало программистов с профильным блин образованием в курсе как работают интерпретаторы, компиляторы и т.д. Не на детальном уровне, а на базовом и общем!!!! Мне в обычной работе, если что, неоднократно приходилось это писать. Чаще всего интерпретаторы, именно компилятор не было смысла, но кодогенератор тоже приходилось писать далеко не один раз, и напишу еще не раз. Вроде не совсем ненужный навык.

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

E>PS Хотел еще ссылку на охрененный курс по компиляторам на ютубе привести, но блин не могу найти. Даже университет не помню какой, толь MIT, толь Беркли. Там несколько, более ранний был довольно стандартный, профессора звали что то вроде Кубианович, начинается точно на Куби, а вот более поздний там преподавали поинтереснее и был фокус на написании DSL и еще там в названии было Hack Your Language. Очень мне б блин самому не помешало пересмотреть, а то как понадобилось однопроходный парсер с приоритетами операций писать — я блин нормально хрен написал, тупо забыл как это все элегантно делается.

Вот у нас студенты как раз учатся делать это элегантно — на PEG-грамматиках.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: Хочется странного
От: elmal  
Дата: 29.12.24 18:59
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Непонятно, при чём тут словари.

Для сопоставления инструкции на ее код и тому подобное. Я не очень понимаю смысл жестко хардкодить кучу методов вроде writeLoadInstructionToStream и т.д. Но это ладно, вкусовщина.

S>В итоге 3/4 курса студенты будут заниматься нудным выпиливанием лобзиком по вазелину, и только 1/4 — собственно компиляцией.

Да не будет там выпиливания лобзиком по вазелину.

S>Если бы у нас было всё время мира — да, можно всё пилить с нуля. Но у нас — 1 семестр, и это не единственный предмет в семестре. Положа руку на сердце: вы напишете с нуля компилятор небольшого языка с кодогенерацией и статической верификацией корректности за 32 часа?

Да, напишу. Правда без статической верификации корректности, этим никогда не занимался. Мне когда на практике такие задачи попадаются, естественно никто время на это не выделяет и не ставит задачу написания DSL. Но приходилось этим заниматься в трех разных конторах, навык оказался полезным.

S>Ну, вот мы их и обучаем. Причём в реальном производстве никогда они не будут с нуля ни токенайзер, ни парсер, ни кодогенератор писать. Бессмысленная затея. Значит, и навыки им нужны больше похожие на то, что в жизни понадобится.

Что интересно — мне это реально понадобилось в реальном проекте, и я писал и токенайзер (примитивный, тупо сплитом строки по регэкспу), и парсер, и кодогенератор. Причем на время и именно что с нуля. Язык, который пришлось парсить — 1С, естественно очень ограниченное подмножество . Некоторые таланты блин в базу зафигачили 1С выражение как строку. Тупо логическое выражение с приоритетом, но там тысячи переменных со скобками и сотни функций, и вот мне требовалось повторить логику, но в более чем тысячу раз быстрее, ибо если реюзать функцию на 1С оригинальную, расчет займет много лет при полной загрузке всех серверов . Как пример просто. Так еще доводилось DSL писать уже на текущем языке, чтоб можно было описывать уравнения на миллионы переменных в виде близкой к математической записи и затем из этого интерпретировать в различные решатели систем уравнений. Проект правда через года 3 всеж помер, из за смены языка программирования на питон, но тем не менее какое то время доводилось писать и классический интерпретатор, хоть и без токенайзера и парсера, ибо DSL была на том же языке сделана, тупо переопределены операторы были и был набор классов определенных и функций их конструирования, далее тупо обход AST и интерпретация, причем еще и с оптимизациями некоторыми. Написать компилятор тоже не составило б труда, но не было необходимости.
Навык написания как минимум интерпретаторов и кодогенератора, наколенный — позволяет сэкономить кучу времени, и если задачи типовые — реюзать и ОЧЕНЬ быстро реагировать на изменения требований. Тупо добавить потом пару строчек, нажать билд и деплой — и все. А не хреначить один и тот же копипастный код из проекта в проект.

S>Вот у нас студенты как раз учатся делать это элегантно — на PEG-грамматиках.

Нашел этот курс охрененный! Блин, его с ютуба удалили, потому и потерял. На всякий случай еще и сюда — http://www.infocobuild.com/education/audio-video-courses/computer-science/CS164-Spring2012-Berkeley/lecture-01.html. Ключевые слова CS 164 Ras Bodik Spring 2012. Здесь именно упор на написание DSL, кажется всеж этот, надо будет пересмотреть, а то я забыл все нафик. Или посмотреть что поновее было б неплохо, но именно от этого курса я был в свое время в восторге и этот курс много заставил переосмыслить. Надо б блин сохранить как нибудь, а то ведь удалят нафик снова ...
Re[10]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.12.24 08:25
Оценка:
Здравствуйте, elmal, Вы писали:
S>>Непонятно, при чём тут словари.
E>Для сопоставления инструкции на ее код и тому подобное. Я не очень понимаю смысл жестко хардкодить кучу методов вроде writeLoadInstructionToStream и т.д. Но это ладно, вкусовщина.
В байткоде инструкция и есть код. Я не понимаю, что вы предлагаете — возможно, потому, что вы пишете словами, а не кодом. Какими типами будет параметризован ваш словарь?

E>Да не будет там выпиливания лобзиком по вазелину.

Только оно и будет. Рукопашное порождение каждого байта — это вот оно и есть.
E>Да, напишу. Правда без статической верификации корректности, этим никогда не занимался.
Ну вот это, конечно, не суперсложная задача, но время на неё тоже надо.
E>Мне когда на практике такие задачи попадаются, естественно никто время на это не выделяет и не ставит задачу написания DSL. Но приходилось этим заниматься в трех разных конторах, навык оказался полезным.
Ну, может быть вы и напишете. Я может быть тоже напишу — но у меня за плечами не один год опыта. А у студентов что? Им только что отчитали курс дискретки с конечными автоматами; а сейчас быстро-быстро запихивают формальные грамматики вместе с тройками Хоара и алгоритмами прямого и обратного прослеживания.
E>Что интересно — мне это реально понадобилось в реальном проекте, и я писал и токенайзер (примитивный, тупо сплитом строки по регэкспу), и парсер, и кодогенератор. Причем на время и именно что с нуля.
Непонятно, зачем вы этим занимались. В такой задаче можно сэкономить примерно три четверти усилий, если взять готовую реализацию парсера на том же PEG.
E>Язык, который пришлось парсить — 1С, естественно очень ограниченное подмножество . Некоторые таланты блин в базу зафигачили 1С выражение как строку. Тупо логическое выражение с приоритетом, но там тысячи переменных со скобками и сотни функций
Вот примерно всё, что вы рассказываете — это лабораторная номер 7 (из 15), она же вторая в серии "про грамматики". Предыдущие работы — чисто на освоение языка программирования и его стандартной библиотеки; они не понадобятся, если брать менее экзотический язык.

E>Навык написания как минимум интерпретаторов и кодогенератора, наколенный — позволяет сэкономить кучу времени, и если задачи типовые — реюзать и ОЧЕНЬ быстро реагировать на изменения требований. Тупо добавить потом пару строчек, нажать билд и деплой — и все. А не хреначить один и тот же копипастный код из проекта в проект.\

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

E>Нашел этот курс охрененный! Блин, его с ютуба удалили, потому и потерял. На всякий случай еще и сюда — http://www.infocobuild.com/education/audio-video-courses/computer-science/CS164-Spring2012-Berkeley/lecture-01.html. Ключевые слова CS 164 Ras Bodik Spring 2012.

Посмотрим, спасибо.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 02.01.2025 11:17 Sinclair . Предыдущая версия .
Re[5]: Хочется странного
От: vsb Казахстан  
Дата: 30.12.24 08:33
Оценка: 123 (1)
Здравствуйте, Sinclair, Вы писали:

S>·>А, понял вопрос. Да, сабж, очень сильно. А задача то какая? Зачем генерить именно байт-код? Может джаву лучше? Ещё кстати scala или kotlin если языка не хватает.

S>Задача — сделать компилятор воображаемого языка.
S>В JVM — потому, что это проще, чем в натив (и даже в LLVM).
S>В принципе, можно и Java-код порождать, но это не даст студентам понимания устройства байт-кода
S>Вот, кстати, смотрю в сторону kotlin. Похоже, на нём тоже неплохо пишется компилятор. Но для него, я так понял, в качестве IDE можно использовать только IntelliJ, т.к. интеграция с VS Code у него так себе.

Я бы посоветовал генерировать байткод wasm.

Во-первых он реально очень простой, гораздо проще байткода JVM.

Во-вторых в нём будто всё сделано для того, чтобы его было просто генерировать.

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

JVM байткод не такой уж простой и там хватает нюансов...

Что такое библиотека AST я не знаю, никогда не слышал. Есть библиотека ASM. Это не официальный, но самый популярный способ генерировать байткод. Но там всё достаточно низкоуровневое, никакого компилятора в ней нет. Да и API у неё специфическое... https://www.baeldung.com/java-asm тут можно ознакомиться немного.
Отредактировано 30.12.2024 8:36 vsb . Предыдущая версия . Еще …
Отредактировано 30.12.2024 8:34 vsb . Предыдущая версия .
Re[6]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.12.24 14:06
Оценка:
Здравствуйте, vsb, Вы писали:
S>>Задача — сделать компилятор воображаемого языка.
S>>В JVM — потому, что это проще, чем в натив (и даже в LLVM).
S>>В принципе, можно и Java-код порождать, но это не даст студентам понимания устройства байт-кода
S>>Вот, кстати, смотрю в сторону kotlin. Похоже, на нём тоже неплохо пишется компилятор. Но для него, я так понял, в качестве IDE можно использовать только IntelliJ, т.к. интеграция с VS Code у него так себе.
vsb>Я бы посоветовал генерировать байткод wasm.
vsb>Во-первых он реально очень простой, гораздо проще байткода JVM.
А вот это интересная идея.
vsb>Во-вторых в нём будто всё сделано для того, чтобы его было просто генерировать.
Посмотим.
vsb>В-третьих у него есть шикарный официальный лиспо-подобный синтаксис, который ещё проще генерировать, а уж из него в байты переконвертировать код есть.
vsb>JVM байткод не такой уж простой и там хватает нюансов...
Отож.
vsb>Что такое библиотека AST я не знаю, никогда не слышал. Есть библиотека ASM. Это не официальный, но самый популярный способ генерировать байткод. Но там всё достаточно низкоуровневое, никакого компилятора в ней нет. Да и API у неё специфическое... https://www.baeldung.com/java-asm тут можно ознакомиться немного.
Да, я как раз про неё — опечатался в названии.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: Хочется странного
От: alsemm Россия  
Дата: 05.01.25 15:50
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Есть библиотека ASM. Это не официальный, но самый популярный способ генерировать байткод.

Я бы сказал, один из популярных. Есть еще, как минимум, ByteBuddy и Lombok. Интересно, что у ByteBuddy под капотом ASM.

Что касается официальности, то ASM засунут внутрь OpenJDK и, очевидно, для чего-то там используется
Re[7]: Хочется странного
От: vsb Казахстан  
Дата: 06.01.25 14:30
Оценка:
Здравствуйте, alsemm, Вы писали:

vsb>>Есть библиотека ASM. Это не официальный, но самый популярный способ генерировать байткод.

A>Я бы сказал, один из популярных. Есть еще, как минимум, ByteBuddy и Lombok. Интересно, что у ByteBuddy под капотом ASM.

Ну ByteBuddy насколько я понимаю — обёртка вокруг asm, не совсем корректно их сравнивать. При чём тут lombok я не очень понял.

A>Что касается официальности, то ASM засунут внутрь OpenJDK и, очевидно, для чего-то там используется


Скорей всего для реализации java.lang.reflect.Proxy, может ещё для чего-нибудь. На самом деле это то ли уже сделано, то ли в грядущих версиях сделают — вместо asm сделают стандартный API в стандартной библиотеке. Но не уверен насчёт статуса этой фичи, ну и в любом случае обычно последние версии жавы не используют, так что упоминать не стал.
Re[8]: Хочется странного
От: alsemm Россия  
Дата: 07.01.25 04:03
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>При чём тут lombok я не очень понял.

Кодогенератор.

vsb>Скорей всего для реализации java.lang.reflect.Proxy,

Динамические прокси в жаве с первых дней, точнее с версии 1.3. Сомневаюсь, что ASM тогда уже был (посмотрел, так и есть, первый публичный релиз ASM два года спустя java 1.3). Никто перепиливать работающий код не будет. ASM в OpenJDK для лямбд.

vsb>вместо asm сделают стандартный API в стандартной библиотеке.

Кто сделает? Авторы ASM? Зачем им это?
Re[9]: Хочется странного
От: · Великобритания  
Дата: 07.01.25 08:36
Оценка: +1
Здравствуйте, alsemm, Вы писали:

a> vsb>вместо asm сделают стандартный API в стандартной библиотеке.

a> Кто сделает? Авторы ASM? Зачем им это?
Авторы JDK: https://openjdk.org/jeps/484 Уже сделано, кстати, финализируют в марте.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[7]: Хочется странного
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.01.25 08:03
Оценка:
Здравствуйте, Sinclair, Вы писали:

Напишу тут.

В принципе, вопрос не совсем по разбору, но столкнулся я с этим именно при разборе.

Я решил сделать очередной подход к разбору своих языков, и наколбасил лексер/токенизатор. В принципе, то, что получилось, мне вполне нравится, получилось достаточно гибко, уже можно многие существующие языки разобрать с соотв. настройками. Пока ограничился плюсиками и сделал выхлоп в HTML с посветкой синтаксиса.

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

Наткнулся на хабре на интересный цикл статей от Гвидо, автора питона — https://habr.com/ru/articles/471860/

В принципе, похожие идеи у меня тоже бродили в голове, но ещё не оформились, и эти статьи здорово мне время сэкономили.

В общем, запилил я список токенов с ленивым фетчем, о котором говорит Гвидо, и пока вроде всё норм. Но столкнулся с такой проблемой, которая пока не особо проблема, но тем не менее. Я на каждый токен храню положение его в исходном тексте, номер строки, положение в строке. Дополнительно, опционально храню разобранное число для числовых констант, или разобранное значение строкового литерала (с разобранными эскейпами). От второго никуда не уйти, но это далеко не с каждым токеном идёт. А вот положение в исходниках — хранится для всех. Токенов в среднем раза в три меньше, чем символов в исходном тексте. И с учетом хранимой инфы у меня выходит оверхед в 50 раз по памяти по сравнению к размеру сорца. Пока это не особо парит, но теоретически, это может стать проблемой. Вот думаю, как поступить. Если не сейчас сделать, то хотя бы продумать, как поступить, когда припрёт
Маньяк Робокряк колесит по городу
Re[8]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.01.25 08:23
Оценка:
Здравствуйте, Marty, Вы писали:

M>В общем, запилил я список токенов с ленивым фетчем, о котором говорит Гвидо, и пока вроде всё норм. Но столкнулся с такой проблемой, которая пока не особо проблема, но тем не менее. Я на каждый токен храню положение его в исходном тексте, номер строки, положение в строке. Дополнительно, опционально храню разобранное число для числовых констант, или разобранное значение строкового литерала (с разобранными эскейпами). От второго никуда не уйти, но это далеко не с каждым токеном идёт. А вот положение в исходниках — хранится для всех. Токенов в среднем раза в три меньше, чем символов в исходном тексте. И с учетом хранимой инфы у меня выходит оверхед в 50 раз по памяти по сравнению к размеру сорца. Пока это не особо парит, но теоретически, это может стать проблемой. Вот думаю, как поступить. Если не сейчас сделать, то хотя бы продумать, как поступить, когда припрёт

Я вообще скептически отношусь к этим всем двухфазным парсерам, потому что есть вменяемые альтернативы.
У лексеров есть принципиальная проблема: не всегда удаётся опознать токен без информации от парсера, т.к. в разных контекстах одни и те же токены могут означать разные вещи.

По поводу перерасхода памяти и прочих штук: как всегда, всё очень зависит от задачи.
Например, если нас не интересует инкрементальный парсинг, то можно использовать одну стратегию оптимизации. А если интересует — то другую.
Вот PEG в частности прекрасен как раз тем, что легко обобщается на инкрементальность, что очень хорошо для построения языковых инструментов для IDE.
И в нём вполне прозрачным образом можно определить, что вообще нам нужно, а что нет.
В простом предельном случае нас вообще интересует только финальное AST, в котором нет никаких паразитных токенов вроде пунктуации.
В более сложном случае мы хотим сэкономить на повторном парсинге, когда какие-то фрагменты исходного грамматического дерева, ненужные в исходном варианте, становятся нужны после внесения правки.
Пока что всё, что я видел из коммерчески-пригодного, работает одним из трёх способов:
— никогда не мемоизируем (читай — оставляем при разборе только то, что нужно для AST)
— всегда мемоизируем (читай — тратим память на примитивные узлы, которые дешевле было бы распарсить заново)
— вручную управляем мемоизацией (читай — программист должен быть достаточно умным, чтобы корректно оценить стоимость повторного парсинга и выбрать между затратами памяти и затратами процессора)
Интуитивно кажется, что можно прикрутить некоторую автоматику, которая сама по коду правила понимает его стоимость и решает, мемоизировать его или нет.

Да, во всех перечисленных случаях, наиболее конструктивный способ хранить информацию про положение в исходниках — это собственно пара чисел "начало, конец". С учётом того, что после разбора у нас остаётся только "полезная" часть AST, оверхед на них не особо большой.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: Хочется странного
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.01.25 08:36
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Я вообще скептически отношусь к этим всем двухфазным парсерам, потому что есть вменяемые альтернативы.

S>У лексеров есть принципиальная проблема: не всегда удаётся опознать токен без информации от парсера, т.к. в разных контекстах одни и те же токены могут означать разные вещи.

Это вообще не проблема. Цепочка символов же одна? Значит, и айди будет один, просто в зависимости от контекста по разному будет обрабатываться. У меня, кстати, есть обратная связь, я её обдумывал, когда вспоминал о проблеме >> vs > и > в плюсовых шаблонах.

S>По поводу перерасхода памяти и прочих штук: как всегда, всё очень зависит от задачи.

S>Например, если нас не интересует инкрементальный парсинг, то можно использовать одну стратегию оптимизации. А если интересует — то другую.
S>Вот PEG в частности прекрасен как раз тем, что легко обобщается на инкрементальность, что очень хорошо для построения языковых инструментов для IDE.
S>И в нём вполне прозрачным образом можно определить, что вообще нам нужно, а что нет.
S>В простом предельном случае нас вообще интересует только финальное AST, в котором нет никаких паразитных токенов вроде пунктуации.
S>В более сложном случае мы хотим сэкономить на повторном парсинге, когда какие-то фрагменты исходного грамматического дерева, ненужные в исходном варианте, становятся нужны после внесения правки.
S>Пока что всё, что я видел из коммерчески-пригодного, работает одним из трёх способов:
S>- никогда не мемоизируем (читай — оставляем при разборе только то, что нужно для AST)
S>- всегда мемоизируем (читай — тратим память на примитивные узлы, которые дешевле было бы распарсить заново)
S>- вручную управляем мемоизацией (читай — программист должен быть достаточно умным, чтобы корректно оценить стоимость повторного парсинга и выбрать между затратами памяти и затратами процессора)
S>Интуитивно кажется, что можно прикрутить некоторую автоматику, которая сама по коду правила понимает его стоимость и решает, мемоизировать его или нет.

У меня задумывается как универсальное средство: 1) для разбора сорцов и построения AST, с выдачей диагностических сообщений с указанием места ошибки/предупреждения — в этом варианте доп нагрузку на токенах можно дропать, когда она больше не требуется; 2) хочется иметь возможность репарсинга с определенной позиции, для реализации хотя бы подсветки синтаксиса в редакторе


S>Да, во всех перечисленных случаях, наиболее конструктивный способ хранить информацию про положение в исходниках — это собственно пара чисел "начало, конец". С учётом того, что после разбора у нас остаётся только "полезная" часть AST, оверхед на них не особо большой.


Как минимум, номер строки тоже надо хранить
Маньяк Робокряк колесит по городу
Re[10]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.01.25 11:35
Оценка:
Здравствуйте, Marty, Вы писали:

M>Это вообще не проблема. Цепочка символов же одна? Значит, и айди будет один, просто в зависимости от контекста по разному будет обрабатываться.

Если в одном контексте a --i означает "вызвать функцию a с аргументом декремент от i", а в другом — "вычесть результат применения унарного минуса к i из a", то лексер не может оперировать лексемой "minusminus".
Он должен порождать две лексемы minus. Это делает смысл лексера эфемерным, потому что нафига он такой нужен? Проще сразу писать парсер.
Композитная лексема — просто очередной нетерминал. Прекрасно работает для контекстно-специфичных ключевых слов. Те же get и set в C#, которые являются ключевыми словами исключительно внутри property definition.

M>У меня, кстати, есть обратная связь, я её обдумывал, когда вспоминал о проблеме >> vs > и > в плюсовых шаблонах.

Я верю, что вы придумали, что с этим делать. С моей точки зрения, это ненужная сложность. Вот вам лексер зачем, собственно, нужен?

M>У меня задумывается как универсальное средство: 1) для разбора сорцов и построения AST, с выдачей диагностических сообщений с указанием места ошибки/предупреждения — в этом варианте доп нагрузку на токенах можно дропать, когда она больше не требуется; 2) хочется иметь возможность репарсинга с определенной позиции, для реализации хотя бы подсветки синтаксиса в редакторе

Ну вот PEG как раз репарсинг прекрасно автоматизирует, т.к. в нём не нужно думать о том, как получить корректный поток лексем для нового представления. Там всего один кэш с простой стратегией вытеснения.
Идеального решения я пока так и не нашёл, но PEG ближе всего к тому, что мне нужно. Судя по всему, я в ближайшем будущем посажу дипломников пилить нормальный фреймворк, а то, скажем, инкрементальный ohm-js сделан крайне странно в плане семантических действий; и в нём нет error autorecovery. При этом статьи про доработку PEG для восстановления после неудачного парсинга есть — надо просто перенести их к продакшн.

С подсветкой синтаксиса всё нетривиально.
Та же VS Code сдалась; в ней красить синтаксис парсером считается неэффективным. Применяют двухуровневую раскраску — основа красится движком на основе регекспов, а парсеру оставляют семантическую раскраску, которой должно быть мало по сравнению с синтаксической. Типа там покрасить в жёлтый переменные функционального типа, затенить константы или недостижимый код, и прочие мелочи.
Но это заставляет решать задачу разбора минимум дважды — один раз грамматикой, второй раз регекспами; особенно бесит при работе над нестабилизированным языком, где синтаксис, грамматика и семантика правятся по нескольку раз в неделю.

А по-другому получается плохо, т.к. проблема курицы и яйца. Чтобы понять, насколько проектируемый язык удобен и хорош, нужно написать на нём приличный корпус текстов. Писать тексты без IDE Assistance крайне утомительно.
Поэтому примеров выходит мало, и на их основе трудно сделать какие-то выводы.
В идеале хочется иметь возможность в наскетчить язык в несколько десятков строчек, и сразу получить все плюшки вроде онлайн диагностики и раскраски синтаксиса; и при этом ещё иметь возможность резко сказать "ой, что-то у нас фигня выходит, давайте теперь переходы будут не просто "номер метки", а goto <labelName>, а labelName — это не номер, а строка, начинающаяся с $. И получить новый extension сразу после перекомпиляции, а не после трёхдневного переписывания лексера, парсера, и textMate раскрасчика синтаксиса.

Как устроена подсветка в настоящей VS, я не в курсе — но явно лучше, чем в VS Code, т.к. последняя красит тот же C# значительно хуже.
Подозреваю, что там какой-то хардкор, трудновоспроизводимый в домашних условиях.

M>Как минимум, номер строки тоже надо хранить

Это всё легко пересчитывать туда-обратно по мере необходимости. Хранить ли позицию в виде "строка/колонка" или просто в виде индекса в строке — дело вкуса.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Отредактировано 27.01.2025 11:35 Sinclair . Предыдущая версия .
Re[11]: Хочется странного
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 27.01.25 18:53
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Marty, Вы писали:


M>>Это вообще не проблема. Цепочка символов же одна? Значит, и айди будет один, просто в зависимости от контекста по разному будет обрабатываться.

S>Если в одном контексте a --i означает "вызвать функцию a с аргументом декремент от i", а в другом — "вычесть результат применения унарного минуса к i из a", то лексер не может оперировать лексемой "minusminus".

Это очень странный язык. Никто так не делает.


M>>У меня, кстати, есть обратная связь, я её обдумывал, когда вспоминал о проблеме >> vs > и > в плюсовых шаблонах.

S>Я верю, что вы придумали, что с этим делать. С моей точки зрения, это ненужная сложность. Вот вам лексер зачем, собственно, нужен?

Сейчас просто синтаксис раскрашиваю, тоже нужная мне штука. Без особых проблем можно настроить под любой язык. Для PHP/Perl, и прочих, где есть такие штуки, как Document Here, надо немного доделать, но пока не нужно было


S>С подсветкой синтаксиса всё нетривиально.

S>Та же VS Code сдалась; в ней красить синтаксис парсером считается неэффективным. Применяют двухуровневую раскраску — основа красится движком на основе регекспов, а парсеру оставляют семантическую раскраску, которой должно быть мало по сравнению с синтаксической. Типа там покрасить в жёлтый переменные функционального типа, затенить константы или недостижимый код, и прочие мелочи.
S>Но это заставляет решать задачу разбора минимум дважды — один раз грамматикой, второй раз регекспами; особенно бесит при работе над нестабилизированным языком, где синтаксис, грамматика и семантика правятся по нескольку раз в неделю.

Не очень понятно, зачем там регеэксы. Я как-то для себя делал тулзу, которая выдирает комент /*! \file \brief bla-bla */ из плюсовых файлов — это доксиген-компатибл описание. Было на регэксах — жутко тормозило (да, я знаю, в плюсиках сейчас они тормозные), и выдирало кривовато, потому что не осилил совсем всё правильно сделать. Переделал через свой токенизатор, обрабатывают только коменты — летает, и выдирает то, что нужно.
По мелочам можно простенькие инструменты по-быстрому лепить.


S>В идеале хочется иметь возможность в наскетчить язык в несколько десятков строчек, и сразу получить все плюшки вроде онлайн диагностики и раскраски синтаксиса; и при этом ещё иметь возможность резко сказать "ой, что-то у нас фигня выходит, давайте теперь переходы будут не просто "номер метки", а goto <labelName>, а labelName — это не номер, а строка, начинающаяся с $. И получить новый extension сразу после перекомпиляции, а не после трёхдневного переписывания лексера, парсера, и textMate раскрасчика синтаксиса.


Ну, теоретически такое наверное осилю


M>>Как минимум, номер строки тоже надо хранить

S>Это всё легко пересчитывать туда-обратно по мере необходимости. Хранить ли позицию в виде "строка/колонка" или просто в виде индекса в строке — дело вкуса.

Номер строки пересчитывать не слишком быстро, это надо с начала файла бежать каждый раз
Маньяк Робокряк колесит по городу
Re[12]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.01.25 01:42
Оценка:
Здравствуйте, Marty, Вы писали:

M>Сейчас просто синтаксис раскрашиваю, тоже нужная мне штука. Без особых проблем можно настроить под любой язык. Для PHP/Perl, и прочих, где есть такие штуки, как Document Here, надо немного доделать, но пока не нужно было

Лексером? Мало какой язык можно раскрасить лексером.

M>Не очень понятно, зачем там регеэксы. Я как-то для себя делал тулзу, которая выдирает комент /*! \file \brief bla-bla */ из плюсовых файлов — это доксиген-компатибл описание. Было на регэксах — жутко тормозило (да, я знаю, в плюсиках сейчас они тормозные), и выдирало кривовато, потому что не осилил совсем всё правильно сделать. Переделал через свой токенизатор, обрабатывают только коменты — летает, и выдирает то, что нужно.

M>По мелочам можно простенькие инструменты по-быстрому лепить.
Регекспы там затем, что они работают быстрее, чем обращение по протоколу LSP.

M>Номер строки пересчитывать не слишком быстро, это надо с начала файла бежать каждый раз

Так никто не делает. При работе в IDE файл хранится в виде дерева строк, по нему преобразование — O(logN) в любую сторону.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.01.25 06:01
Оценка:
Здравствуйте, Marty, Вы писали:
M>Это очень странный язык. Никто так не делает.
Контекстных историй — овердохрена. Вы же сами приводите пример с >>, и тут же пишете "никто так не делает".
Или, скажем, string interpolation. Токенизатор создаёт существенные проблемы, т.к. шаблон строки плохо укладывается в идею "тут у нас просто строковая константа".
var q = $@"Hello, {
    getHelloTarget("simple")}";

Ну, ок, давайте скажем, что у нас тут токены VarKeyword, Identifier('q'), InterpolationStringFragment('Hello, '), а дальше-то что? Нельзя просто искать следующую }, потому что а) в коде выражения фигурные скобки вполне себе могут встречаться и б) она может вовсе не встретиться. Вот такой вот кусок кода должен быть токенизирован совершенно по другому:
var q = $@"Hello, {
    getHelloTarget(";


Безлексерному парсеру — всё равно. Ему нет проблемы включить режим "разбираем ескейпы и прочую чухню", потом "разбираем expression", потом "а теперь снова ескейпы и ждём конца строки".

M>Ну, теоретически такое наверное осилю

Это было бы замечательно. На удивление, довольно мало production-ready вещей. Примерно все едят кактус. Вот, например, state-of-the-art у самих авторов концепции LSP: https://github.com/microsoft/tolerant-php-parser/blob/main/docs/HowItWorks.md
Читаем внимательно:
— Incremental parsing (Note: not yet implemented)
— Error Tokens: There are also some instances, where the aforementioned error handling wouldn't be appropriate, and special-casing based on certain heuristics, such as whitespace, would be required.
— Open Questions: Мы всё ещё не знаем, как нам правильно это пилить, присылайте свои идеи
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[13]: Хочется странного
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 28.01.25 07:43
Оценка:
Здравствуйте, Sinclair, Вы писали:

M>>Сейчас просто синтаксис раскрашиваю, тоже нужная мне штука. Без особых проблем можно настроить под любой язык. Для PHP/Perl, и прочих, где есть такие штуки, как Document Here, надо немного доделать, но пока не нужно было

S>Лексером? Мало какой язык можно раскрасить лексером.

Я плюсики раскрашиваю вроде норм.

Отвечая также на соседнее сообщение, скажу, что у меня наверное не совсем честный лексер. Так, у меня строковые символьные литералы парсятся отдельным классом, который надо "проинсталлить" в лексер. проблема с PHP/PERL в общем-то только с тем, что для DOCUMENT HERE надо написать отдельный парсер этого литерала, мне пока не до этого.

Далее, выхлоп токенизера отправляется в пользовательский обработчик, завернутый в std::function. Потом мне показалось этого мало, и я сделал возможность добавлять "фильтры" на выхлоп. Сильно переделывать уже не хотелось, и у меня немножко странно получилось — фильтры устанавливаются в голову, и получается, что раньше отрабатывают фильтры, установленные позже.

Ф фильтрах я при необходимости делаю небольшие автоматики, которые делают что-то полезное. Так, например, для числовых литералов, если за ними сразу, без каких-либо пробелов и чего-то другого, следует идентификатор — я это склеиваю, и получаю новомодные плюсовые пользовательские литерали, или как оно там называется. Или препроцессор. Сначала было всё в конечном обработчике, потом сделал фильтр, который умеет посылать токены PP_START/PP_END, по которым я устанавливаю другой цвет фонта при раскраске.

Вот так у меня выглядит создание токенизатора: http://files.rsdn.org/2511/cpp.html
А так — использование: http://files.rsdn.org/2511/tokenizer_test_011.html

Эти файлы раскрашены этим тестом


S>Регекспы там затем, что они работают быстрее, чем обращение по протоколу LSP.


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


M>>Номер строки пересчитывать не слишком быстро, это надо с начала файла бежать каждый раз

S>Так никто не делает. При работе в IDE файл хранится в виде дерева строк, по нему преобразование — O(logN) в любую сторону.

Я пока с IDE не работаю, у меня текст в одной строке, и все ссылки на исходный текст идут как индекс в этой строке


ЗЫ Заметил баг — съедает закрывающий символ "*/" в многострочных коментариях
Маньяк Робокряк колесит по городу
Re[14]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.01.25 08:30
Оценка:
Здравствуйте, Marty, Вы писали:
M>Я плюсики раскрашиваю вроде норм.
Скорее всего ключевое слово тут "вроде". В частности, лексером невозможно корректно раскрасить код с макросами, т.к. вплоть до раскрытия макроопределений неизвестно даже, является ли код частью юнита компиляции.
Ну, то есть вопрос в постановке задачи. Если хочется просто красить лексемы — то "кому и кобыла невеста".
А вот делать полноценную современную семантическую разметку — увы.

M>Отвечая также на соседнее сообщение, скажу, что у меня наверное не совсем честный лексер. Так, у меня строковые символьные литералы парсятся отдельным классом, который надо "проинсталлить" в лексер. проблема с PHP/PERL в общем-то только с тем, что для DOCUMENT HERE надо написать отдельный парсер этого литерала, мне пока не до этого.

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

M>Далее, выхлоп токенизера отправляется в пользовательский обработчик, завернутый в std::function. Потом мне показалось этого мало, и я сделал возможность добавлять "фильтры" на выхлоп. Сильно переделывать уже не хотелось, и у меня немножко странно получилось — фильтры устанавливаются в голову, и получается, что раньше отрабатывают фильтры, установленные позже.

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

Проблема всех таких решений — write-only code, в котором совершенно невозможно понять, что и как разбирает результат всех этих применений фильтров к фильтрам и каскадов парсеров.

M>Ф фильтрах я при необходимости делаю небольшие автоматики, которые делают что-то полезное. Так, например, для числовых литералов, если за ними сразу, без каких-либо пробелов и чего-то другого, следует идентификатор — я это склеиваю, и получаю новомодные плюсовые пользовательские литерали, или как оно там называется. Или препроцессор. Сначала было всё в конечном обработчике, потом сделал фильтр, который умеет посылать токены PP_START/PP_END, по которым я устанавливаю другой цвет фонта при раскраске.

Во-во, об этом я и говорю. В теории вы даже можете сделать фильтр, который проверяет, попадает ли выхлоп IFDEF в компиляцию, или нет. Но зачем называть это токенизатором?

M>Вот так у меня выглядит создание токенизатора: http://files.rsdn.org/2511/cpp.html

M>А так — использование: http://files.rsdn.org/2511/tokenizer_test_011.html

M>Эти файлы раскрашены этим тестом

Ну, если вы пишете токенизатор для конкретного языка — то да, можно делать примерно всё, что угодно. Всё равно это write-only код, который потом никто не будет проверять или поддерживать.

S>>Регекспы там затем, что они работают быстрее, чем обращение по протоколу LSP.

M>Ну, вот тут не уверен, что это всегда так. В любом случае, мой токенизер гораздо быстрее работает.
Скорость работы токенизатора не очень важна, когда узким местом является передача его результатов в IDE.

M>Я пока с IDE не работаю, у меня текст в одной строке, и все ссылки на исходный текст идут как индекс в этой строке

Когда начнёте работать с инкрементальностью, неизбежно перейдёте на древовидное хранение. Аккурат потому, что O(N) операции вас задолбают.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[15]: Хочется странного
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.01.25 00:42
Оценка:
Здравствуйте, Sinclair, Вы писали:

M>>Я плюсики раскрашиваю вроде норм.

S>Скорее всего ключевое слово тут "вроде". В частности, лексером невозможно корректно раскрасить код с макросами, т.к. вплоть до раскрытия макроопределений неизвестно даже, является ли код частью юнита компиляции.

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


S>Ну, то есть вопрос в постановке задачи. Если хочется просто красить лексемы — то "кому и кобыла невеста".


Часто большее и не нужно


S>А вот делать полноценную современную семантическую разметку — увы.


Да, это не самое простое.


S>Вот у вас уже внутри лексера используется парсер, который, надо полагать, внутри использует лексер. Ну и нафига это всё, спрашивается, когда можно просто перестать себя обманывать и притворяться, что существует какой-то отдельный от "парсера" "токенизатор"?


Есть токенизатор, есть ручки, которые можно дергать. К токенизатору можно прикрутить надстройки, и да, он становится не совсем честным. И что?
Внутри мой токенизатор устроен как куча говнокода, там без тонких материй

Да, я до возможностей IDE сильно не дотягиваю, но у меня уже гораздо лучше, чем том же notepad++.

Когда я на говне запилил свой первый DSL, который локально хорошо взлетел (но не первый мой DSL вообще), то был вопрос, а где его редактировать, чтобы красиво. Получилось в NPPP и Кейле. В NPPP — через его настройки кстомной раскраски, в Кейле — через правки конфигов какого-то движка, который я перепутал с тем, что наша местная терраинформатика делает. И там и там всё было на пределе возможностей, приходилось извращаться. А сейчас у меня уже гораздо лучше.


S>Проблема всех таких решений — write-only code, в котором совершенно невозможно понять, что и как разбирает результат всех этих применений фильтров к фильтрам и каскадов парсеров.


Моё решение предлагает задание операторов оптом, задание различных типов скобок, и наборы фильтров. Всё это можно варьировать при настройке и получать результат лучше, чем в NPP. Уже годно для тупого лексера.

write-only code... Ну, хз...
Так-то, почти любое решение — дерьмо. С начала ты трескаешь то, что тебе дали разработчики решения, и тебя всё устраивает, и ты не паришься, что там под капотом. Потом ты упираешься в ограничения этого решения, но ты ничего не можешь изменить...


S>Во-во, об этом я и говорю. В теории вы даже можете сделать фильтр, который проверяет, попадает ли выхлоп IFDEF в компиляцию, или нет. Но зачем называть это токенизатором?


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


S>Ну, если вы пишете токенизатор для конкретного языка — то да, можно делать примерно всё, что угодно.


Мой "токенизатор" писался с упором на то, чтобы можно было в первую очередь распарсить существующие языки. Что может придумать воспалённый мозг, я не знаю. Например, что a--b, это не полная хрень, а a минус b с унарным минусом. Если нужно такое — это не ко мне. У меня жадный алгоритм токенизации. И он выплюнет a, --, b, для примитивной раскраски этого достаточно, как в прочем, и для дальнейшего разбора.


S>Всё равно это write-only код, который потом никто не будет проверять или поддерживать.


Не очень понятно, что ты хотел сказать.


M>>Я пока с IDE не работаю, у меня текст в одной строке, и все ссылки на исходный текст идут как индекс в этой строке

S>Когда начнёте работать с инкрементальностью, неизбежно перейдёте на древовидное хранение. Аккурат потому, что O(N) операции вас задолбают.

Мне до этого ещё далеко. Но не вижу особых проблем. Не уверен, что на каждое нажатие клавиши надо делать вставки в единственный глобальный string с текстом. На вскидку — будет глобальный текст, и список строк, которые ссылаются индексами на глобальный текст. Если пошло редактирование строки, то глобальный текст не перестраивается при каждом вводе, просто для строки выделяется отдельный буфер и строка маркируется признаком своего буфера. Потом вставляем, пробегаем и обновляем индексы после нашей строки, переделываем раскарску. Раскраску при вводе/удалении можно сдвигать/удалять по месту, на базе старой, без перескана, при паузах и в фоне можно всё перестраивать/пересканивать как угодно. В общем, что-то не вижу особых проблем. Мои варианты решений конечно далеки от дедовских, которые шуршали даже на XT, но, как минимум не хуже того, что сейчас в тренде.
Маньяк Робокряк колесит по городу
Re[16]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.01.25 01:27
Оценка:
Здравствуйте, Marty, Вы писали:
M>Да. Но в большинстве случаев это не нужно. Например, у меня в перспективе маячит раскраска кода листингов в документации, того, который в маркдауне ограничен тремя бэктиками, а на кывте обрамляется тэгом code.
Ну, тогда я не совсем понимаю, чего вы хотите. В начале вы сослались на Гвидо, который объясняет причины, по которым он предпочёл бы переехать на PEG. Но PEG — это не лексер, это безлексерный парсер.
M>Часто большее и не нужно
Я ж не спорю — если ваши планы заканчиваются на лексической раскраске, то ваше решение прекрасно.
M>Есть токенизатор, есть ручки, которые можно дергать. К токенизатору можно прикрутить надстройки, и да, он становится не совсем честным. И что?
То, что теряется смысл выделять отдельно токенизатор, т.к. это затрудняет разработку полного решения.
M>Да, я до возможностей IDE сильно не дотягиваю, но у меня уже гораздо лучше, чем том же notepad++.
M>Когда я на говне запилил свой первый DSL, который локально хорошо взлетел (но не первый мой DSL вообще), то был вопрос, а где его редактировать, чтобы красиво. Получилось в NPPP и Кейле. В NPPP — через его настройки кстомной раскраски, в Кейле — через правки конфигов какого-то движка, который я перепутал с тем, что наша местная терраинформатика делает. И там и там всё было на пределе возможностей, приходилось извращаться. А сейчас у меня уже гораздо лучше.
Стандарт де-факто сейчас — это VS Code, а точнее — протокол LSP.

M>Моё решение предлагает задание операторов оптом, задание различных типов скобок, и наборы фильтров. Всё это можно варьировать при настройке и получать результат лучше, чем в NPP. Уже годно для тупого лексера.

Ну так и замечательно. Просто если вы хотите что-то куда-то развивать, то тупой лексер, с моей точки зрения — тупик.

M>Мой "токенизатор" писался с упором на то, чтобы можно было в первую очередь распарсить существующие языки. Что может придумать воспалённый мозг, я не знаю.

А что тут не знать?
M>Например, что a--b, это не полная хрень, а a минус b с унарным минусом. Если нужно такое — это не ко мне. У меня жадный алгоритм токенизации. И он выплюнет a, --, b, для примитивной раскраски этого достаточно, как в прочем, и для дальнейшего разбора.
Ну, интерполированные строки он сможет разобрать?

M>Не очень понятно, что ты хотел сказать.

Что поддерживать парсер языка, в котором собственно грамматика размазана по токенизатору, парсеру, и пачке "фильтров", которые меняют поведение токенизатора и парсера — то ещё занятие.

M>Мне до этого ещё далеко. Но не вижу особых проблем. Не уверен, что на каждое нажатие клавиши надо делать вставки в единственный глобальный string с текстом. На вскидку — будет глобальный текст, и список строк, которые ссылаются индексами на глобальный текст. Если пошло редактирование строки, то глобальный текст не перестраивается при каждом вводе, просто для строки выделяется отдельный буфер и строка маркируется признаком своего буфера. Потом вставляем, пробегаем и обновляем индексы после нашей строки, переделываем раскарску. Раскраску при вводе/удалении можно сдвигать/удалять по месту, на базе старой, без перескана, при паузах и в фоне можно всё перестраивать/пересканивать как угодно. В общем, что-то не вижу особых проблем. Мои варианты решений конечно далеки от дедовских, которые шуршали даже на XT, но, как минимум не хуже того, что сейчас в тренде.


Очень хорошо.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[17]: Хочется странного
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.01.25 02:11
Оценка:
Здравствуйте, Sinclair, Вы писали:

M>>Да. Но в большинстве случаев это не нужно. Например, у меня в перспективе маячит раскраска кода листингов в документации, того, который в маркдауне ограничен тремя бэктиками, а на кывте обрамляется тэгом code.

S>Ну, тогда я не совсем понимаю, чего вы хотите. В начале вы сослались на Гвидо, который объясняет причины, по которым он предпочёл бы переехать на PEG. Но PEG — это не лексер, это безлексерный парсер.

Гвидо там же говорит, что у него есть свой офигенский лексер, который он не хочет выкидывать. Я в такой же ситуации. Вот и всё. Для разминки думаю набросать пару языков на ручном рекурсивном спуске с использованием своего "лексера", а там дальше видно будет.

Packet Diagram выглядит хорошим кандидатом, мне как раз надо как-то по-простому описать кастомную раскладку памяти в прошивке, чтобы её не компилятор генерил, а я своей тулзой (хочу прошить во флешку инфу по железке раз и навсегда, а потом бутлоадер будет проверять, соответствует ли фирмварь хардварной ревизии), и этот кусочек прошивки хочу описать в виде Packet Diagram, а тулзе значения переменных отдавать, и она бы HEX генерила по такому описанию. Должно получится на имеющемся быстро и не слишком сложно


M>>Часто большее и не нужно

S>Я ж не спорю — если ваши планы заканчиваются на лексической раскраске, то ваше решение прекрасно.

Мои планы на этом только начинаются


S>Стандарт де-факто сейчас — это VS Code, а точнее — протокол LSP.


Вы (ничего, что я на Вы?) сами же говорите, что это полное говно, нет?
И что там двухстадийная раскраска, и первая фаза на регэксах? У меня работает гораздо быстрее регэксов


M>>Моё решение предлагает задание операторов оптом, задание различных типов скобок, и наборы фильтров. Всё это можно варьировать при настройке и получать результат лучше, чем в NPP. Уже годно для тупого лексера.

S>Ну так и замечательно. Просто если вы хотите что-то куда-то развивать, то тупой лексер, с моей точки зрения — тупик.

Посмотрю, как пойдёт. Пока так, что есть малой кровью


M>>Например, что a--b, это не полная хрень, а a минус b с унарным минусом. Если нужно такое — это не ко мне. У меня жадный алгоритм токенизации. И он выплюнет a, --, b, для примитивной раскраски этого достаточно, как в прочем, и для дальнейшего разбора.

S>Ну, интерполированные строки он сможет разобрать?

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


M>>Не очень понятно, что ты хотел сказать.

S>Что поддерживать парсер языка, в котором собственно грамматика размазана по токенизатору, парсеру, и пачке "фильтров", которые меняют поведение токенизатора и парсера — то ещё занятие.

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


M>>Мне до этого ещё далеко. Но не вижу особых проблем. Не уверен, что на каждое нажатие клавиши надо делать вставки...


S>Очень хорошо.


Вы, наверное, забыли тут вставить
Маньяк Робокряк колесит по городу
Re[17]: Хочется странного
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.01.25 02:24
Оценка:
Здравствуйте, Sinclair, Вы писали:

M>>Не очень понятно, что ты хотел сказать.

S>Что поддерживать парсер языка, в котором собственно грамматика размазана по токенизатору, парсеру, и пачке "фильтров", которые меняют поведение токенизатора и парсера — то ещё занятие.

А тут, мне кажется, есть вполне себе плюсы. В конфигах можно задавать свои операторы (алисами к существующим, или заменой), ключевые слова, и тд и тп. Без кодирования можно переделать под себя правкой джейсонов
Маньяк Робокряк колесит по городу
Re[18]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.01.25 03:36
Оценка:
Здравствуйте, Marty, Вы писали:

M>Гвидо там же говорит, что у него есть свой офигенский лексер, который он не хочет выкидывать.

Где вы там такое нашли? Всё, что там есть — длинное перечисление проблем в существующем парсере, как объяснение его интереса к PEG.

M>Я в такой же ситуации. Вот и всё. Для разминки думаю набросать пару языков на ручном рекурсивном спуске с использованием своего "лексера", а там дальше видно будет.

Кто ж вам запретит, делайте.
Меня собственно запиливание ручного рекурсивного спуска не интересует уже очень давно.
Интересует как можно более компактное решение типовых проблем современных парсеров:
— внятная диагностика синтаксических ошибок (у PEG с этим всё очень хорошо)
— внятная поддержка инкрементального парсинга (у PEG с этим всё очень хорошо; неплохо бы ещё автоматизировать и следующие стадии — скажем, корректировка таблиц имён и связанных с ними референсов без полного повтора семантического анализа, но это уже не про грамматики)
— внятная поддержка отката после ошибок (у PEG с этим всё неплохо — есть теоретические наработки, но не воплощены на практике).

Делать всё это вручную и каждый раз с нуля как-то не очень хочется.

M>Packet Diagram выглядит хорошим кандидатом, мне как раз надо как-то по-простому описать кастомную раскладку памяти в прошивке, чтобы её не компилятор генерил, а я своей тулзой (хочу прошить во флешку инфу по железке раз и навсегда, а потом бутлоадер будет проверять, соответствует ли фирмварь хардварной ревизии), и этот кусочек прошивки хочу описать в виде Packet Diagram, а тулзе значения переменных отдавать, и она бы HEX генерила по такому описанию. Должно получится на имеющемся быстро и не слишком сложно

Ну, тут формат примитивный, для него PEG делается в несколько строчек.

M>Вы (ничего, что я на Вы?) сами же говорите, что это полное говно, нет?

Ну да, а чему это противоречит? Неговна незавезли.
M>И что там двухстадийная раскраска, и первая фаза на регэксах? У меня работает гораздо быстрее регэксов
:sigh: Что именно работает быстрее регекспов?
Предположим, что вы придумали новый язык описания чего-нибудь. Неважно — программного кода, расположения прошивок в памяти, диаграмм, или дерева эффектов в фильме.
Современные пользователи избалованы — они хотят не просто тул, который можно вызывать из командной строки с разнообразными флагами.
Они хотят полноценный интерактивный экспириенс — чтобы файлики эти можно было открывать там же, где они редактируют остальной контент; чтобы там раскраска синтаксиса работала, сворачивание регионов, навигация по коду, чтоб ошибки были и в списке project problems, и подчёркнуты прямо в редакторе, чтобы были quick fixes для этих ошибок, чтобы работал автокомплит, всякие go to definition и find all usages. И чтобы всё это — прямо на лету, интерактивно, и без please wait for project reindexing.
Можно начать колхозить свою IDE с блэкджеком и С++, но это — очень большая работа. В современной IDE уже наколбашено огромное количество функций, как встроенных, так и при помощи плагинов.
Даже если отказаться от собственно интегрированности, то даже "простой редактор кода" — это уже овердофига всяких фич, которые дорого писать с нуля. Поэтому берут за основу, скажем, тот же Monaco.
И вот теперь возникает вопрос — а как этому редактору обмениваться с вашим супербыстрым лексером? Ах, если бы он был написан на чистых плюсах, то ваш код можно было бы добавить к коду этого редактора, и собрать всё одним компилятором. Но нет — не написан он на плюсах. Поэтому поток маркеров стиля вы будете ему отдавать в виде JSON. И в итоге сколько бы вы времени ни сэкономили на переходах в конечном автомате, это просто потеряется на фоне стоимости сериализации/десериализации в JSON.
Именно поэтому современные IDE красят текст регекспами. Регекспы грузятся в память основного редактора, компилируются там, и работают приемлемо быстро, не создавая гигабайтного трафика между редактором и LSP.

M>Ну, надо будет плагин-парсер запилить для интерполированных строк, как и для любых нетривиальных литералов

Отож. Любую проблему можно решить допиливанием костыля для костыля. Кроме проблемы избытка костылей.

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

Хороший инструмент — это PEG.

M>Вы, наверное, забыли тут вставить

Нет, зачем. Я искренне рад за вас — сам люблю баловаться всякими велосипедами. Вот, в нынешнем проекте я из любви к искусству запилил VS Code extension с парсером и семантическим анализатором для нашего языка программирования. Пока остальная команда делала компилятор по-старинке — через bison и yacc. Когда есть возможность сравнить — сразу видно, насколько PEG выигрывает у классики.
Очень много тавтологичного бойлерплейта требуется для написания парсера традиционным методом.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[18]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.01.25 03:41
Оценка:
Здравствуйте, Marty, Вы писали:
M>А тут, мне кажется, есть вполне себе плюсы. В конфигах можно задавать свои операторы (алиасами к существующим, или заменой), ключевые слова, и тд и тп. Без кодирования можно переделать под себя правкой джейсонов
Да, для решения конкретной ограниченной задачи такое подойдёт. Я помню, клиппер лет 30 назад изобретал что-то подобное — у него был конфигурируемый набор алиасов для команд; кто-то развлекался созданием русифицированного языка на его основе.
А вообще, вы не первый, кто пытается сделать конфигурируемую систему раскраски синтаксиса. Примерно все остановились на регекспах как наиболее универсальном способе.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[19]: Хочется странного
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.01.25 20:17
Оценка:
Здравствуйте, Sinclair, Вы писали:

M>>Гвидо там же говорит, что у него есть свой офигенский лексер, который он не хочет выкидывать.

S>Где вы там такое нашли? Всё, что там есть — длинное перечисление проблем в существующем парсере, как объяснение его интереса к PEG.

Там цикл статей, во второй статье:

Токенизация Python достаточно сложна, поэтому я не хочу реализовывать её на правилах PEG. Например, вы должны отслеживать отступы (для этого требуется стек внутри токенизатора); интересна также и обработка новых строк в Python (они значимы, кроме заключенных в соответствующие скобки). Многие типы строк также вызывают некоторую сложность. Короче говоря, у меня нет никаких претензий к уже существующему токенизатору Python, поэтому я хочу оставить его как есть. Кстати, у CPython есть два токенизатора: внутренний, который используется парсером, он написан на C, и стандартный библиотечный, который является точной копией, реализованной на чистом Python. Это пригодится в моём проекте.



S>Кто ж вам запретит, делайте.

S>Меня собственно запиливание ручного рекурсивного спуска не интересует уже очень давно.
S>Интересует как можно более компактное решение типовых проблем современных парсеров:
S>- внятная диагностика синтаксических ошибок (у PEG с этим всё очень хорошо)
S>- внятная поддержка инкрементального парсинга (у PEG с этим всё очень хорошо; неплохо бы ещё автоматизировать и следующие стадии — скажем, корректировка таблиц имён и связанных с ними референсов без полного повтора семантического анализа, но это уже не про грамматики)
S>- внятная поддержка отката после ошибок (у PEG с этим всё неплохо — есть теоретические наработки, но не воплощены на практике).

Да, это всё очень замечательно, кто же спорит


S>Ну, тут формат примитивный, для него PEG делается в несколько строчек.


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


M>>Вы (ничего, что я на Вы?) сами же говорите, что это полное говно, нет?

S>Ну да, а чему это противоречит? Неговна незавезли.

Не говно — это когда функционал LSP доступен не через пайп, а через inproc плагин.


M>>И что там двухстадийная раскраска, и первая фаза на регэксах? У меня работает гораздо быстрее регэксов

S>:sigh: Что именно работает быстрее регекспов?

Мой токенизатор.


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

S>Современные пользователи избалованы — они хотят не просто тул, который можно вызывать из командной строки с разнообразными флагами.
S>Они хотят полноценный интерактивный экспириенс — чтобы файлики эти можно было открывать там же, где они редактируют остальной контент; чтобы там раскраска синтаксиса работала, сворачивание регионов, навигация по коду, чтоб ошибки были и в списке project problems, и подчёркнуты прямо в редакторе, чтобы были quick fixes для этих ошибок, чтобы работал автокомплит, всякие go to definition и find all usages. И чтобы всё это — прямо на лету, интерактивно, и без please wait for project reindexing.
S>Можно начать колхозить свою IDE с блэкджеком и С++, но это — очень большая работа. В современной IDE уже наколбашено огромное количество функций, как встроенных, так и при помощи плагинов.
S>Даже если отказаться от собственно интегрированности, то даже "простой редактор кода" — это уже овердофига всяких фич, которые дорого писать с нуля. Поэтому берут за основу, скажем, тот же Monaco.
S>И вот теперь возникает вопрос — а как этому редактору обмениваться с вашим супербыстрым лексером? Ах, если бы он был написан на чистых плюсах, то ваш код можно было бы добавить к коду этого редактора, и собрать всё одним компилятором. Но нет — не написан он на плюсах. Поэтому поток маркеров стиля вы будете ему отдавать в виде JSON. И в итоге сколько бы вы времени ни сэкономили на переходах в конечном автомате, это просто потеряется на фоне стоимости сериализации/десериализации в JSON.
S>Именно поэтому современные IDE красят текст регекспами. Регекспы грузятся в память основного редактора, компилируются там, и работают приемлемо быстро, не создавая гигабайтного трафика между редактором и LSP.

Тут надо разбираться, как сделать плагин для какой-нибудь IDE, это самое сложное. У меня вообще в тудушке есть пункт собрать некоторые свои плюсовые проекты в вебассемблю. Может появится побочный эффект, что я смогу на плюсиках делать плагины для ВСКода, но не факт.


M>>Ну, надо будет плагин-парсер запилить для интерполированных строк, как и для любых нетривиальных литералов

S>Отож. Любую проблему можно решить допиливанием костыля для костыля. Кроме проблемы избытка костылей.

Не костыля, а плагина


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

S>Хороший инструмент — это PEG.

А насколько он хорош для плюсов?


M>>Вы, наверное, забыли тут вставить

S>Нет, зачем. Я искренне рад за вас — сам люблю баловаться всякими велосипедами. Вот, в нынешнем проекте я из любви к искусству запилил VS Code extension с парсером и семантическим анализатором для нашего языка программирования. Пока остальная команда делала компилятор по-старинке — через bison и yacc. Когда есть возможность сравнить — сразу видно, насколько PEG выигрывает у классики.
S>Очень много тавтологичного бойлерплейта требуется для написания парсера традиционным методом.

bison и yacc

Вы хотели сказать, наверное, lex+yacc/flex+bison?

Я когда-то flex+bison тыкал, тоже не помню для чего, может те же плюсики раскрашивал. Это ужасно
Маньяк Робокряк колесит по городу
Re[19]: Хочется странного
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.01.25 20:24
Оценка:
Здравствуйте, Sinclair, Вы писали:

M>>А тут, мне кажется, есть вполне себе плюсы. В конфигах можно задавать свои операторы (алиасами к существующим, или заменой), ключевые слова, и тд и тп. Без кодирования можно переделать под себя правкой джейсонов

S>Да, для решения конкретной ограниченной задачи такое подойдёт. Я помню, клиппер лет 30 назад изобретал что-то подобное — у него был конфигурируемый набор алиасов для команд; кто-то развлекался созданием русифицированного языка на его основе.
S>А вообще, вы не первый, кто пытается сделать конфигурируемую систему раскраски синтаксиса. Примерно все остановились на регекспах как наиболее универсальном способе.

То-то современные IDE такие жирные и тормозные. То ли дело — старикашка кейл, у него раскраска на базе scintilla, летает, голубчик

Глянул, кто её использует:

Известные приложения, использующие Scintilla:

SciTE — текстовый редактор, который первоначально был создан для демонстрации возможностей Scintilla.
Notepad++ — текстовый редактор для Microsoft Windows.
Geany — легковесная кроссплатформенная интегрированная среда разработки.
FbEdit — среда разработки под Windows для языка FreeBasic.
Code::Blocks — кроссплатформенная интегрированная среда разработки с открытым исходным кодом.
CodeLite — свободная кроссплатформенная среда разработки программного обеспечения для языка C/C++ с открытым исходным кодом.
FlashDevelop — открытая среда разработки RIA Flex, Flash, Haxe для Microsoft Windows.
Aegisub[5] — кроссплатформенный редактор субтитров.
Notepad2 — текстовый редактор для Microsoft Windows, как замена стандартному приложению Блокнот.
PureBasic IDE — кроссплатформенная интегрированная среда разработки для языка PureBasic.
MySQL Workbench — инструмент для визуального проектирования баз данных.
Visual Prolog — Visual Prolog.
µVision (начиная с версии 4.53.0.4) — интегрированная среда разработки для микроконтроллеров.
TortoiseGit — визуальный клиент системы управления исходными кодами программ git.


Сам юзал µVision (он же кейл), Notepad++, Code::Blocks — все они весьма шустры, по сравнению c например Eclipse, или IDE от JetBrains (IDEA, CLion). VSCode в принципе шустр, но с подсветкой тоже подтупливает
Маньяк Робокряк колесит по городу
Отредактировано 29.01.2025 20:29 Marty . Предыдущая версия .
Re[20]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 30.01.25 02:31
Оценка:
Здравствуйте, Marty, Вы писали:
M>Там цикл статей, во второй статье:
M>

M>Токенизация Python достаточно сложна, поэтому я не хочу реализовывать её на правилах PEG. Например, вы должны отслеживать отступы (для этого требуется стек внутри токенизатора); интересна также и обработка новых строк в Python (они значимы, кроме заключенных в соответствующие скобки). Многие типы строк также вызывают некоторую сложность. Короче говоря, у меня нет никаких претензий к уже существующему токенизатору Python, поэтому я хочу оставить его как есть. Кстати, у CPython есть два токенизатора: внутренний, который используется парсером, он написан на C, и стандартный библиотечный, который является точной копией, реализованной на чистом Python. Это пригодится в моём проекте.

А, спасибо, посмотрю. Да, indent-based синтаксисы традиционно трудны для вообще всех грамматических парсеров. У меня есть идея, как это можно было бы изящно сделать в PEG, не встраивая в него костыли. Но её надо проверять.

S>>Ну, тут формат примитивный, для него PEG делается в несколько строчек.

M>Можно будет сравнить, если вам не лень будет этим заняться. Я, когда запилю, напомню, на таком простом примере наверное не сложно будет уделать рукопашный парсер?
Что значит "уделать"? Опередить по компактности и читаемости кода — 100%.

M>Не говно — это когда функционал LSP доступен не через пайп, а через inproc плагин.

Ну так его-то и не завезли. Собственно, за систему inproc-плагинов люди и не любили старую студию.

M>Мой токенизатор.

При отдаче результата в dev>null? Или он у вас там порождает стилизированный HTML?

M>Тут надо разбираться, как сделать плагин для какой-нибудь IDE, это самое сложное. У меня вообще в тудушке есть пункт собрать некоторые свои плюсовые проекты в вебассемблю. Может появится побочный эффект, что я смогу на плюсиках делать плагины для ВСКода, но не факт.

Во-первых, на плюсиках плагины для ВСКода и так можно делать. Их уже делают кто во что горазд.
Во-вторых, сборка в wasm упростит деплоймент, но вряд ли улучшит быстродействие. Потому что узким местом LSP всё равно является JSON-RPC.
Встроить раскраску синтаксиса во встроенный редактор можно только через LSP либо TextMate2. Если вы захотите делать inproc-раскраску, вам придётся напилить свой custom editor.

M>Не костыля, а плагина

А какой смысл тогда называть "это" токенизатором, если у него внутри полноценный парсер?

M>А насколько он хорош для плюсов?

Для разбора плюсов или для порождения плюсового кода? Для разбора — нормально; для порождения — надо смотреть на инструменты.
Есть сразу несколько библиотек с реализацией PEG для плюсов. Но я на них не смотрел — не моя специализация.

M>Вы хотели сказать, наверное, lex+yacc/flex+bison?

Наверное. Но глядя на примеры "PEG" для плюсов (https://github.com/taocpp/PEGTL/blob/main/src/example/pegtl/calculator.cpp) я вижу, что проблема не столько в конкретном выбранном виде парсеров, сколько в твёрдом убеждении их авторов в неизбежности страданий. Типа, "нельзя просто написать грамматику с действиями и разбирать ей тексты!". Надо получить обязательную порцию унижений в виде пачки бойлерплейта. В итоге, калькулятор с 18 операциями превращается в 360 строк кода . При этом, собственно, от грамматики в исходнике ничего не остаётся — всё размазано по вспомогательным структурам и рукопашным методам match.
Вот этот вариант выглядит получше, но всё делает в рантайме. Из этого мы сразу выводим что
а) косяки в грамматике тоже обнаружатся в рантайме, а в компайл-тайме нам ничего не скажут. То есть "приходи, дорогой друг, завтра, когда отработают тесты найтли билда".
б) быстродействие, скорее всего, хуже чем у плюсовых регекспов и аналогов на Javascript.
В общем, беглым взглядом я ничего не нашёл. Скорее всего, можно навелосипедить приличное решение, которое умеет разбирать текст DSL, который содержит грамматику и семантические действия, и порождать код на плюсах. Вот это, собственно, и даст возможность быстро выполнять как прототипирование, так и собственно разбор текста получившимся кодом.

M>Я когда-то flex+bison тыкал, тоже не помню для чего, может те же плюсики раскрашивал. Это ужасно

Отож.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[21]: Хочется странного
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 01.02.25 18:50
Оценка:
Здравствуйте, Sinclair, Вы писали:


S>>>Ну, тут формат примитивный, для него PEG делается в несколько строчек.

M>>Можно будет сравнить, если вам не лень будет этим заняться. Я, когда запилю, напомню, на таком простом примере наверное не сложно будет уделать рукопашный парсер?
S>Что значит "уделать"? Опередить по компактности и читаемости кода — 100%.

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


M>>Не говно — это когда функционал LSP доступен не через пайп, а через inproc плагин.

S>Ну так его-то и не завезли. Собственно, за систему inproc-плагинов люди и не любили старую студию.

То есть, inproc-плагины — это говно, а по пайпу туда-сюда гонять джейсон — это офигенно?


M>>Мой токенизатор.

S>При отдаче результата в dev>null? Или он у вас там порождает стилизированный HTML?

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


M>>Тут надо разбираться, как сделать плагин для какой-нибудь IDE, это самое сложное. У меня вообще в тудушке есть пункт собрать некоторые свои плюсовые проекты в вебассемблю. Может появится побочный эффект, что я смогу на плюсиках делать плагины для ВСКода, но не факт.

S>Во-первых, на плюсиках плагины для ВСКода и так можно делать. Их уже делают кто во что горазд.

Это интересно, но не на столько, чтобы я кинулся сейчас сразу искать информацию на эту тему. Если есть под рукой годные ссылки, то буду благодарен.


S>Во-вторых, сборка в wasm упростит деплоймент, но вряд ли улучшит быстродействие. Потому что узким местом LSP всё равно является JSON-RPC.


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


S>Встроить раскраску синтаксиса во встроенный редактор можно только через LSP либо TextMate2. Если вы захотите делать inproc-раскраску, вам придётся напилить свой custom editor.


LSP — понятно, а TextMate/2 — что за зверь? Какие с ним проблемы? (Да, я бегло погуглил, но ничего не понял )


M>>Не костыля, а плагина

S> А какой смысл тогда называть "это" токенизатором, если у него внутри полноценный парсер?

Так не полноценный же. Сам по себе, без надстроек — он вполне себе только токенизатор.

У меня ещё есть разделение на TokenizerBuilder и Tokenizer. Сейчас TokenizerBuilder умеет создавать Tokenizer, но, теоретически, TokenizerBuilder будет уметь сериализовать Tokenizer в плюсовый код, из которого можно создать Tokenizer. А этот Tokenizer можно будет запихать без билдера в STM32, чтобы он там что-то простецкое разбирал. Но я пока эту ветку не прорабатывал.


M>>Вы хотели сказать, наверное, lex+yacc/flex+bison?

S>Наверное. Но глядя на примеры "PEG" для плюсов (https://github.com/taocpp/PEGTL/blob/main/src/example/pegtl/calculator.cpp) я вижу, что проблема не столько в конкретном выбранном виде парсеров, сколько в твёрдом убеждении их авторов в неизбежности страданий. Типа, "нельзя просто написать грамматику с действиями и разбирать ей тексты!". Надо получить обязательную порцию унижений в виде пачки бойлерплейта. В итоге, калькулятор с 18 операциями превращается в 360 строк кода . При этом, собственно, от грамматики в исходнике ничего не остаётся — всё размазано по вспомогательным структурам и рукопашным методам match.

Глянул, что-то такое себе


S>Вот этот вариант выглядит получше, но всё делает в рантайме. Из этого мы сразу выводим что

S>а) косяки в грамматике тоже обнаружатся в рантайме, а в компайл-тайме нам ничего не скажут. То есть "приходи, дорогой друг, завтра, когда отработают тесты найтли билда".
S>б) быстродействие, скорее всего, хуже чем у плюсовых регекспов и аналогов на Javascript.
S>В общем, беглым взглядом я ничего не нашёл. Скорее всего, можно навелосипедить приличное решение, которое умеет разбирать текст DSL, который содержит грамматику и семантические действия, и порождать код на плюсах. Вот это, собственно, и даст возможность быстро выполнять как прототипирование, так и собственно разбор текста получившимся кодом.

А вот это — интересно, надо приглядется, спасибо
Маньяк Робокряк колесит по городу
Re[22]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 02.02.25 08:24
Оценка:
Здравствуйте, Marty, Вы писали:
M>Я пока не очень разобрался, как всё это работает в конкретных инструментах, но наверное на каждое правило должно быть навешено какое-то действие, типа, добавить элемент в AST. Можно считать, что код по навешиванию действий в PEG варианте не входит в парсер, а во втором варианте считать наоборот
Ну, вообще на эту тему чуть больше мнений, чем есть реализаций PEG. Но более-менее традиционным всё же считается подход, в котором semantic actions вписаны прямо в грамматику.
Можно и по-другому, но тогда начинаются всякие мелкие неприятности при написании, да и читаемость страдает.

M>То есть, inproc-плагины — это говно, а по пайпу туда-сюда гонять джейсон — это офигенно?

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

M>Не очень понял.

А что тут не понять? Бенчмаркать "чистый токенизатор", который отдаёт результат в dev/null, не имеет никакого смысла. Это всё равно, что мерить скорость какого-нибудь "i++".
Интересна скорость прикладной задачи с использованием различных решений.
M>Мой токенизатор может порождать стилизированный HTML, я уже приводил этот пример. И я могу без проблем какому-то хосту отдавать информацию, что и с какой позиции надо красить каким стилем.
Всё упирается в то, каким способом это отдаётся этому хосту. Понимаете, лексический анализ при правильной реализации — штука феерически дешёвая. Ну, то есть понятно, что ваш код теоретически можно разогнать ещё в три-пять раз, но даже уже и так он работает настолько эффективно, что становятся заметны вызовы getNext. Любое использование результата вызова getNext будет ещё заметнее.
M>Это интересно, но не на столько, чтобы я кинулся сейчас сразу искать информацию на эту тему. Если есть под рукой годные ссылки, то буду благодарен.
Годные ссылки лежат прямо на сайте VS Code — с пошаговыми тьюториалами и примерами. На данном этапе важно понять принцип: собственно JSON-RPC был там придуман ровно для того, чтобы LSP можно было реализовать на чём угодно, хоть даже и на плюсах. Поэтому, к примеру, сервер для Rust написан на Rust, а сервер для Java — на Java.

M>Ну, я очень мало знаю о том, как устроен VSCode, и пока не копал. Слышал, что он весь из себя на JS сделанный, и плагины тоже как-то так делаются. Про web assembly я тоже очень мало знаю, но, теоретически, это вроде как единственный путь собирать плюсовый код, чтобы он работал на жиэсе.

VS Code совершенно всё равно, на чём работает ваш код. Да, работа на JS упрощает деплоймент, потому что не нужно думать о том, как запустить ваш код на конкретной платформе. А в остальном стандартный способ — стартовать процесс на том, на чём он написан, и работать с ним через локальные веб-вызовы.
И даже это не единственный способ — поскольку VS Code умеет работать в веб (zero-deployment), ваш LSP сервер вообще может торчать в интернете, и VS Code будет с ним работать на лету через честное сетевое соединение.
Но я эту возможность пока что мало изучал, по ряду административных причин.

M>LSP — понятно, а TextMate/2 — что за зверь? Какие с ним проблемы? (Да, я бегло погуглил, но ничего не понял )

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

M>Так не полноценный же. Сам по себе, без надстроек — он вполне себе только токенизатор.



M>У меня ещё есть разделение на TokenizerBuilder и Tokenizer. Сейчас TokenizerBuilder умеет создавать Tokenizer, но, теоретически, TokenizerBuilder будет уметь сериализовать Tokenizer в плюсовый код, из которого можно создать Tokenizer. А этот Tokenizer можно будет запихать без билдера в STM32, чтобы он там что-то простецкое разбирал. Но я пока эту ветку не прорабатывал.

Ну, в целом это и есть самый конструктивный подход. Потому что если делать "только конфигурацию в рантайме", то вы пропустите оптимизации. Будет примерно то же самое по производительности, что и регекспы на плюсах (я же правильно понял, что там они всё ещё интерпретируются?). А если делать рукопашное написание токенизатора, то код становится громоздким и плохо поддерживаемым.
Так что да — берём код грамматики на удобном DSL, по нему строим код на целевом языке и алга. Ну, там дальше возможны варианты — не обязательно же сначала порождать код C++, чтобы потом его какой-нибудь Clang или ICC превращал в LLVM IR. Можно и сразу LLVM IR порождать, минуя лишний этап.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[23]: Хочется странного
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 02.02.25 21:21
Оценка:
Здравствуйте, Sinclair, Вы писали:

M>>Я пока не очень разобрался, как всё это работает в конкретных инструментах, но наверное на каждое правило должно быть навешено какое-то действие, типа, добавить элемент в AST. Можно считать, что код по навешиванию действий в PEG варианте не входит в парсер, а во втором варианте считать наоборот

S>Ну, вообще на эту тему чуть больше мнений, чем есть реализаций PEG. Но более-менее традиционным всё же считается подход, в котором semantic actions вписаны прямо в грамматику.
S>Можно и по-другому, но тогда начинаются всякие мелкие неприятности при написании, да и читаемость страдает.

Это интересный вопрос, на самом деле: имхо было бы удобно описывать правила отдельно, а действия, которые производятся при матче правил — отдельно. Тогда грамматику языка можно описать один раз, а построение AST можно пилить для target языков отдельно, и биндить к правилам при выводе в целевой язык.


M>>То есть, inproc-плагины — это говно, а по пайпу туда-сюда гонять джейсон — это офигенно?

S>Конечно. Основная причина — криворукий плагин не роняет студию, а просто отпадает, ни на что не влияя.
S>А то, что там гигабайты под капотом летают — ну и хрен с ними, пока это не мешает пользоваться студией. Многочисленные преимущества вот так вот взяли да и перевесили недостатки.

Криворукий плагин не роняет фар, а просто выгружается. Хотя в фаре плагины inproc. По-моему, это тривиально делается. В винде для этого есть SEH, в других системах наверняка должно быть что-то подобное.


S>Годные ссылки лежат прямо на сайте VS Code — с пошаговыми тьюториалами и примерами. На данном этапе важно понять принцип: собственно JSON-RPC был там придуман ровно для того, чтобы LSP можно было реализовать на чём угодно, хоть даже и на плюсах. Поэтому, к примеру, сервер для Rust написан на Rust, а сервер для Java — на Java.


Спс, я не интересовался настолько, чтобы что-то копать. LSP это конечно интересно, но вообще для VSCode есть куча плагинов на все случаи жизни, а не только для подсветки кода. Или LSP настолько всеобъемлющ, что позволяет реализовать любые типы плагинов для VSCode? Но да, в контексте раскраски синтаксиса и интеллисенса от LSP наверное никуда не деться.
Маньяк Робокряк колесит по городу
Re[24]: Хочется странного
От: Sinclair Россия https://github.com/evilguest/
Дата: 03.02.25 02:36
Оценка:
Здравствуйте, Marty, Вы писали:

M>Это интересный вопрос, на самом деле: имхо было бы удобно описывать правила отдельно, а действия, которые производятся при матче правил — отдельно. Тогда грамматику языка можно описать один раз, а построение AST можно пилить для target языков отдельно, и биндить к правилам при выводе в целевой язык.

Это имеет смысл в ограниченном количестве случаев. Ситуации, когда одна и та же грамматика применяется для разных целевых языков, лично мне в жизни не встречались и ожиданий таковых нет.
И даже если такое встретится, мне, скорее всего, будет проще просто склонировать грамматику и переписать правила, чем мучиться с выписыванием отдельного решения.
Впрочем, если хочется попрактиковаться — именно так устроен Ohm-js. В реальности получается не особо удобно, несмотря на офигенную гибкость TypeScript. Основная проблема — безымянные части правил.
В Lingo, к примеру, я могу писать семантическия действия прямо по месту, ещё и выбирая для байндинга только нужные мне части правил:
...
Add = Term:l "+" Add:r { Sum(:l, :r}} | Term 
...

В Ohm у меня справа от = стоит безымянная альтернатива; чтобы забиндить к ней какое-то действие, нужно дать ей имя. И аргументами для действия будут все ноды, независимо от их полезности, а тип результата будет каким-то общим супертипом для всех узлов. Средства для всего этого в библиотеке есть, но выглядит костыльно:
...
Add = 
  Term "+" Add:r --two
  | Term 
...

const actions = {
  ...
  Add_two: (l, _plus, r) => Add.create(l.getAst(), r.getAst()),
  ...
} satisfies ArithmeticSemantics<AstNode>

Примерно то же самое придётся делать в более-менее любом подходе, где действия отделены от семантики. Причём ценность этого равна примерно нулю, потому что, повторюсь, целевой язык компилятора обычно известен к тому моменту, когда пишется грамматика. И лучше помочь тем, кто пилит в этом направлении, чем портить жизнь остальным 99.9% пользователей. Авторы Ohm.js приводят вырожденные примеры — типа "а давайте мы забабахаем калькулятор на семантических правилах; а теперь давайте на той же грамматике забабахаем претти-принтер". Ну вот в реальной жизни наиболее практичный способ — это не вычислять грамматикой значение выражения, а породить AST, из которого уже легко, непринуждённо, и типобезопасно получается и "вычисление значения", и pretty print, и вообще примерно всё остальное.
Особенно с учётом того, что реальные языки (в отличие от школьных примеров типа целочисленной арифметики) используют разные типы узлов в AST, и крайне полезно статически проверять корректность сборки родителей из детей.

M>Криворукий плагин не роняет фар, а просто выгружается. Хотя в фаре плагины inproc. По-моему, это тривиально делается. В винде для этого есть SEH, в других системах наверняка должно быть что-то подобное.

По-моему, вы фантазируете. Никакой SEH не поможет вам от плагина, который просто срёт в общее адресное пространство потому, что кто-то не освоил адресную арифметику, или отлаживался в дебаг-режиме, а в релизе у него неинициализированный указатель показывает в космос, а не в null.

M>Спс, я не интересовался настолько, чтобы что-то копать. LSP это конечно интересно, но вообще для VSCode есть куча плагинов на все случаи жизни, а не только для подсветки кода. Или LSP настолько всеобъемлющ, что позволяет реализовать любые типы плагинов для VSCode?

Нет, LSP — только для языковых инструментов. Плагины, которые расширяют саму студию — всякие альтернативные редакторы, интеграция юнит-тестирования или системы контроля версий пишутся на тайпскрипте и, в некотором смысле, работают in-proc. Но вас-то интересуют не они. Ну, по крайней мере мне как раз интересно, как с минимально возможными усилиями завести IDE для нового языка, а не новый пункт меню в одной случайно выбранной IDE.
M>Но да, в контексте раскраски синтаксиса и интеллисенса от LSP наверное никуда не деться.
Да, вся навигация по коду, автодополнение, signature hint, рефакторинги и всё прочее — это LSP.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.