Pull to refresh

Comments 31

PinnedPinned comments

почему уже в самом описании парсера нельзя указать, тут name ключевое слово или нет. Ну то есть если в парсере в этом месте написано "name", то явно именна такая последовательность тут и ожидается и это ключевое слово. При этом оно ведь ожидается только в этом месте, в других местах вы спокойно в грамматике пишите <kw_name:id> и если там разбираемом тексте встретится name, оно будет как идентификатор распознано, а не ключевое слово. Или я тут чего-то не понимаю? Кстати, не смотрели на rust-peg?

Почитав про rust-peg, я понял вашу мысль. Действительно, PEG парсер позволяет разрешать слабые ключевые слова довольно легко, за счёт своего базового свойства - в нём описываемые в грамматике альтернативы упорядочены, и конфликтов поэтому быть не может, в отличие от контекстно-свободного (CFG) парсера, который использовал я и для которого приходится ухищряться (в статье приводятся способы) при разрешении таких слабых слов. (В прежнем моём ответе выше есть объяснение, почему ваше предложение не работает для моего случая).

Навскидку кажется, что грамматика для rust-peg будет чуть более многословна - нужно везде использовать whitespace символы (различные пробельные символы и переводы строки) в качестве возможных разделителей для остальных токенов.

А также из-за указанного выше базового свойства (ordered choice) ожидается ухудшение перформанса и увеличение использования памяти, что требует в ручном режиме выставлять оптимальный порядок для таких альтернатив, если хочется улучшить перформанс.

Ещё видимо следует делать правила достаточно лёгкими или использовать их кэширование - так как правило может быть вызвано несколько раз на том же месте.

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

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

тоже почти как у вас, еще на эту тему хочу добавить, я сначала начинал со стековой машины, тоже аст - байткод - интерпретация или трансляция промежуточного кода в nasm, но было жгучее желание оживить систему, пришел к тому что проще оживить ассемблер виртуальный, и прям им писать внутри приложения, виртуальный опрос клавы и виртуальная область видео памяти, это просто имбово, ассемблер, дал понимание как должен работать настоящий dsl

Интересный опыт!

проще оживить ассемблер виртуальный

А что такое виртуальный ассемблер?

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

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

Какие вопросы были бы интересны в продолжение темы?

Как я и предполагал, будет много слов и кода, но мало картинок, то бишь, демонстрации работы с графикой (ну, да, вам это не нужно, понимаю), Соответственно, вопрос, как насчет GUI, в вашем новом, любимом языке?

Тема специального языка для моделирования многокомпонентных динамических систем давно меня зацепила

В некотором смысле, меня тоже, только без «специального языка» и, если мы имеем в виду одно и тоже.

Для меня «многокомпонентные динамические системы» это плагины, но, не только динамические (dll-файлы), но и статические (см. мой демо-проект; «Модульное программирование в C++. Статические и динамические плагины» в https://habr.com/ru/articles/566864/ ).

Пожелайте мне удачи в продуктовом продвижении моего поделия!

Желаю удачи! От бесплатного пет-проекта, к финансово окупаемому стартапу!

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

У меня, тоже, аналогичная ситуация. Действую по принципу: «Публикация бесплатной программы на бесплатном сайте и, если «взлетит», попросить донатов». Моя базовая программа описана в статье: «Уроки французского и пересоздание данных для изучения иностранного языка с помощью обучающей программы «L'école» в https://habr.com/ru/articles/972594/ » и всех предыдущих статьях, по которым можно пройтись по ссылкам.

Теоретически, статьи на «Хабре» нужно перенести на мои сайты, дать общий обзор, ссылки на обучающие данные и уже эти пресловутые «донаты» вполне можно просить. Но, как всегда, на завершающем этапе, довести дело до «ума» мешает лень :) .

Соответственно, вопрос, как насчет GUI, в вашем новом, любимом языке?

Сам язык чисто для моделирования и без GUI, а его результат в виде разделяемой библиотеки (dll) можно подключить в своё приложение.

Но в его родной IDE AnyDynamics (указан в первой же главе статьи) - волне есть графический редактор для схем и карт поведения, а также возможность накидать примитивную графическую панель с управляющими контролами и индикаторами для работы в “визуальной модели“.

Язык придумал не я и IDE не моя - не имя отношения к авторам языка я взялся за более эффективную и кроссплатформенную реализацию языка самостоятельно. А дальше можно пофантазировать и о своей IDE, если взлетит.

Желаю удачи! От бесплатного пет-проекта, к финансово окупаемому стартапу!

Спасибо, такие пожелания очень греют!

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

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

Моя базовая программа описана в статье: «Уроки французского и пересоздание данных для изучения иностранного языка с помощью обучающей программы «L'école» 

И вам тоже удачи с продвижением вашей задумки!)

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

Согласен, нужно осваивать все подходящие площадки, в т.ч., доступные видео-хостинги. Там появляются подписчики, которых совершенно не ожидаешь увидеть.

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

Как-то все же остались неясности, почему уже в самом описании парсера нельзя указать, тут name ключевое слово или нет. Ну то есть если в парсере в этом месте написано "name", то явно именна такая последовательность тут и ожидается и это ключевое слово. При этом оно ведь ожидается только в этом месте, в других местах вы спокойно в грамматике пишите <kw_name:id> и если там разбираемом тексте встретится name, оно будет как идентификатор распознано, а не ключевое слово. Или я тут чего-то не понимаю? Кстати, не смотрели на rust-peg?

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

Как использовать в сборке зависимости через rlib-файлы без исходников

Было бы интересно почитать

почему уже в самом описании парсера нельзя указать, тут name ключевое слово или нет. Ну то есть если в парсере в этом месте написано "name", то явно именна такая последовательность тут и ожидается и это ключевое слово. При этом оно ведь ожидается только в этом месте, в других местах вы спокойно в грамматике пишите <kw_name:id> и если там разбираемом тексте встретится name, оно будет как идентификатор распознано, а не ключевое слово.

Так не выйдет, ведь слово "name" в грамматике обозначает токен, который выдает лексер - либо встроенный, либо внешний. А токен для идентификатора описывается регулярным выражением, конфликтующим с простым вышеуказанным словом "name" (как и с любым другим словом) и по умолчанию лексер выбирает выдать токен простого (ключевого) слова, а не токен описанный регулярным выражением. Выбор по-умолчанию наоборот был бы ещё хуже, ведь тогда никаких ключевых слов вообще было бы не ввести.

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

Кстати, не смотрели на rust-peg?

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

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

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

Это при условии, что вообще такой макрос может съесть исходный код - там же совсем непривычный может быть синтаксис и к тому же не UTF-8 кодировка.

И плюс бонусом медленная работа процедурного макроса, да ещё на большом объеме исходного кода.

А ещё исходный код может обладать несколькими синтаксисами, в моём случае это Ada и C# подобные (я поддерживаю пока только первый).

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

Ваша идея довольно экстремальная - это ж придётся в процедурном макросе фактически произвести весь парсинг,

Так вы же и так это делаете в своем парсере MVL. Просто как я понял, сейчас вы запускаете генератор, он делает файлы, а потом эти файлы идут на вход компилятору Rust. Компилятор Rust вынужден эти исходники парсить, чтобы получить список токенов, которые потом он обрабатывает. А можно на вход компилятору сразу подавать список токенов.

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

А сейчас это кто делает? Ваш pipeline сейчас: (1)MVL -> (2)модель MVL в декларативных макросах Rust -> (3)декларативные макросы генерируют Rust код -> (4)компилятор Rust делает бинарник.

Я предлагаю убрать шаг 2 с сразу генерировать Rust код, как будто вы руками раскрыли макросы с шага 2, т.е. так:
(1)MVL -> (2)процедурный макрос генерируют Rust код -> (3)компилятор Rust делает бинарник.

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

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

Вы фактически предлагаете использовать лексер от Rust, но дело в том, что он выдаёт токены для лексики Rust, а не моего исходного языка - т.е. например, он выдаст как литералы 1u8 и b"something", что не являются валидными литералами в моём случае. Не говоря уже о том, что в качестве идентификаторов он выдаст и ключевые слова, которые потребуются всё равно отделять.

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

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

Т.о. заворачивать парсинг в процедурный макрос только из-за использования лексера Rust кажется слишком несоразмерным и не подходит для моего случая.

Как использовать в сборке зависимости через rlib-файлы без исходников

Было бы интересно почитать

Принято, постараюсь изложить

почему уже в самом описании парсера нельзя указать, тут name ключевое слово или нет. Ну то есть если в парсере в этом месте написано "name", то явно именна такая последовательность тут и ожидается и это ключевое слово. При этом оно ведь ожидается только в этом месте, в других местах вы спокойно в грамматике пишите <kw_name:id> и если там разбираемом тексте встретится name, оно будет как идентификатор распознано, а не ключевое слово. Или я тут чего-то не понимаю? Кстати, не смотрели на rust-peg?

Почитав про rust-peg, я понял вашу мысль. Действительно, PEG парсер позволяет разрешать слабые ключевые слова довольно легко, за счёт своего базового свойства - в нём описываемые в грамматике альтернативы упорядочены, и конфликтов поэтому быть не может, в отличие от контекстно-свободного (CFG) парсера, который использовал я и для которого приходится ухищряться (в статье приводятся способы) при разрешении таких слабых слов. (В прежнем моём ответе выше есть объяснение, почему ваше предложение не работает для моего случая).

Навскидку кажется, что грамматика для rust-peg будет чуть более многословна - нужно везде использовать whitespace символы (различные пробельные символы и переводы строки) в качестве возможных разделителей для остальных токенов.

А также из-за указанного выше базового свойства (ordered choice) ожидается ухудшение перформанса и увеличение использования памяти, что требует в ручном режиме выставлять оптимальный порядок для таких альтернатив, если хочется улучшить перформанс.

Ещё видимо следует делать правила достаточно лёгкими или использовать их кэширование - так как правило может быть вызвано несколько раз на том же месте.

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

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

В дополнение можно указать, что ошибка, выдаваемая rust-peg, более простая, в сравнении с lalrpop - а именно, первый выдаёт только позицию и список ожидаемых токенов,

Зато вы можете самостоятельно перепарсить это место (т.е. начать разбор с указанного парсером места ошибки) уже другим парсером (даже PEG парсером, т.е. фактически другим правилом из той же грамматики) и получить то, что хотите. Хоть отдельный символ (хотя это и так уже есть по умолчанию), хоть слово (причем вы сами определяете, что такое "слово"). Более того, такие правила (на ошибочный вход), можно сознательно вставлять в грамматику в вероятных местах ошибки и прямо включать в выстраиваемый AST, чтобы потом обработать их на более верхнем уровне. Еще лучше, чтобы это делал парсер автоматически, но rust-peg этого (пока?) не умеет. Но если поинтересоваться темой, то люди делали такое для PEG парсеров и на хабре есть статья об этом.

Пример (в синтаксисе pegjs):

string
  = '"' $[^"]* '"'
  // функция error возвращает AST узел с ошибкой, ее вы сами определяете
  / '"' { return error("unclosed string"); }

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

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

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

Множественные ошибки может выдавать и lalrpop.

По вашему примеру с незакрытым строковым литералом - для CFG парсера (например lalrpop) это делается прямо в лексере, и он выдаёт кастомную ошибку.

Я ж говорю, интересно было бы провести исследование и сравнить показатели перформанс-память против удобства и обработки ошибок для PEG (rust-peg) vs CFG (lalrpop) на реально нагромождённом языке типа моего случая.

Языки моделирования содержат средства описания объектов в терминах предметных систем, их связи, а также и возможное взаимодействие во времени. Корректнее говорить именно как о таковых системах моделирования (СМ), а не языках, так как первое более широкое понятие чем второе. Как языков программирования, не существует универсальной СМ "на все случаи жизни", все определяет конкретная задача и область моделирования. Понятия, структура и описание обьектов относящихся к СМ в принципе ни коим образом НЕ соотносятся и НЕ пересекаются с понятиями и объектами в универсальных языков програмирования, как упорно пытается сделать автор статьи. Это совершенно разные по своей сути и назначению инструментальные средства.

Понятия, структура и описание обьектов относящихся к СМ в принципе ни коим образом НЕ соотносятся и НЕ пересекаются с понятиями и объектами в универсальных языков програмирования, как упорно пытается сделать автор статьи

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

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

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

Любая система моделирования (обьектов или процессов) в первую очередь базируется на математическое аппарате для конкретного типа задач в своей предметной области. В принципе НЕ может бы универсальной системы моделирования или, как вы её называете, одного языка моделирования "на все случаи жизни". В противном случае, говоря упрощенно, не было бы тогда и механиков, электриков, гидравликов и прочих других тех.специальностей. Другое дело, что может иметь место применение какие-то общих математические методов которые подходят к разным техническим системам и обьектам. Тогда соответственно и системы моделирования специализируется на этих математических методах. Например, одна из старейших систем имитационное моделирования GPSS для систем массового обслуживания или системы моделирования с помощью метода конечных элементов типа ANSYS. Везде свой математический аппарат, если уж так хотите, свой язык моделирования имеющие мало чего общего с универсальными языками для программирования ЭВМ.

В принципе НЕ может бы универсальной системы моделирования или, как вы её называете, одного языка моделирования "на все случаи жизни".

Можете указать, где я такое писал? Вы как будто прочитали другой текст и спорите не понятно с кем.

И в основном тексте, и в ответах к вам указаны конкретные сферы и примеры применения языка, где он неплохо подходит.

Касаемо самого языка - вы Dyad видели? Работает поверх Julia и по сути развитие Modelica

Интересно, посмотрю на Dyad, спасибо. Если там та же Modelica, то в статье я привёл сравнение с ней - вкратце, она имеет меньше возможностей по сравнению с MVL и поэтому проще в реализации.

Интересна содержательная часть работы, а особенно постановка задачи: что представляют собой физические движки, какие типы бывают (вы же наверняка один из существующих типов реализовали - но почему выбрали этот тип).
К чему ведёт выбор того или иного типа движка: "мощность" (что может \ не может симулировать) vs сложность реализации.
Наличие специфических (кажется нет) оптимизаций.....
Что с точностью? Есть ли анализ точности? Как делается?
(глаз зацепился, что вы в примерах не задумываясь double пишите).

Могу ли я (кажется нет - но поправьте) нарисовать "рельеф" и запустить по нему кататься шарик? Чем закончится? Накапливаемая ошибка?

П.С.
Личное мнение: кажется в 2025 году (за пределами студенческих курсовых или специальных экспоненциальных случаев разбора или содержательных сообщений об ошибках) - задачи лексинга \ парсинга не являются актуальными, они просто делаются и всё.
Сам бы взял парсер-комбинатор. ИМХО это оптимальный по соотношению "всё ещё грамматика \ долго писать \ сложно отлаживать \ подставить костыль в любое место 'если что' ". В Rust это nom. Nom8 сам не пробовал, т.к. пробовал на Rust 3-4 года назад.

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

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

Т.е. моделист-пользователь может описать требуемые физические законы для какого-то объекта с нужной для него детализацией в виде набора состояний с разным поведением.

Наличие специфических (кажется нет) оптимизаций.....

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

Что с точностью? Есть ли анализ точности? Как делается?(глаз зацепился, что вы в примерах не задумываясь double пишите).

А нужно single float? Не уверен, хватит ли его при требуемой точности в 1e-6 например. Вообще, точность задаётся в файле проекта, и если её выставить малой, то может быть можно и single float использовать внутри реализации, это интересная мысль.

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

Сейчас же и в моей, и в оригинальной реализации используется double float, в последней точность учитывается, а я ещё не дошёл до этого.

Могу ли я (кажется нет - но поправьте) нарисовать "рельеф" и запустить по нему кататься шарик? Чем закончится? Накапливаемая ошибка?

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

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

Сам бы взял парсер-комбинатор

Да, можно наверное и так. А пробовали ли вы для реально нагромождённых языков со слабыми ключевыми словами?

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

Спасибо за ответ.
Будет интересно почитать другие статьи - именно в упор на другие модели механики \ оптимизации существующих (насколько я понимаю перед этим надо задать ограничения).

> А нужно single float?
C меня коньяк если найдёте где я это предлагал ;)
Я как раз скорее про увеличение точности в вычислениях (принимая решение в зависимости от аппаратной поддержки).

> со слабыми ключевыми словами?
Тут вроде боле-менее стандартно:
- в пределах того же уровня (лексер \ парсер ) - откат при обнаруженной ошибке делается из коробки (*) сколько угодно раз - формально это экспонента, на практике при любом разумном коде никакой экспоненты и близко нет.
- в пределах разных уровней - вроде из коробки в nom этого нет - придётся учить (делать дополнительные обёртки, которые умеют пробрасывать в лексер ошибки парсера)


*) для этого лексер должен выдавать вам "имя", а уже парсер представлять это (разрешая до семантического анализа все непределённости) как "keyword(string) | ident(string)"

в пределах того же уровня (лексер \ парсер ) - откат при обнаруженной ошибке делается из коробки (*) сколько угодно раз

вроде из коробки в nom этого нет - придётся учить (делать дополнительные обёртки, которые умеют пробрасывать в лексер ошибки парсера)

Почитал про nom - с ним действительно должно быть нетрудно справляться со слабыми ключевыми словами - судя по описанию, ведь в нём есть возможность использовать выбор из упорядоченного списка альтернатив. Соответственно всё тот же набор trade-off по скорости, памяти и удобству относительно использованного мной CFG парсера, как и для PEG парсера, что приведены в ответе выше.

Использование nom кажется будет ещё более многословнее, чем rust-peg, но зато через него можно протянуть кастомные ошибки, как и с lalrpop, что использовал я.

А лексера в nom (и rust-peg) никакого специально не выделяется, поиск идёт по диапазону байтов, в отличие от CFG парсера (lalrpop), где лексер выдаёт более крупные токены.

Будет интересно почитать другие статьи - именно в упор на другие модели механики \ оптимизации существующих (насколько я понимаю перед этим надо задать ограничения).

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

Про оптимизацию вы, видимо, подразумеваете задачи оптимизации функционалов и систем управления - в языке есть соответствующие конструкции.

парсить не сложно, эту модель парсинга с рекурсивным спуском да, дадут в ВУЗе наверно, но когда вы делаете этот спуск исключая, что его оценят именно это совершенно другая плоскость познавания, по-сути второй мозг на ошибках уже, ну лекс-парсер на рекурсии до байткода действительно не сложный, разок на С можно посмотреть и повторить его просто, главное разделить стейты и всё заполнять в нужное время

например обливион всё еще обсчитать можно уложившись поидее, на мой нубский взгляд

Благодарю за шикарную статью, интересуюсь языками.. один лишь вопрос.. вроде же принят стандарт комментов // зачем использовать оператор декремента в качестве коммента? Очень плохочитаемый мувдля dsl, ещё и подрывающий общепринятые некие стандарты, которые должны были "врожденно" наличествовать при вашем тезисе "пишу много лет на си/раст/го/жава/..." Использовать # ещё можно понять , как дань традиции sh/perl/python.. но декремент!?

в форте(скобочки и черточки для визуализации ) или лиспе(тут точка с запятой) есть и вообще там если смотреть по модели С - всё не так )

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

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

Sign up to leave a comment.

Articles